List size has unexpected value - java

Suppose the following situation in a loop:
LinkedList<String> myList = someMethodReturnsList();
int start = 0, end = 0;
while (end < myList.size() && someOtherCondition)
++end;
List<String> subList = myList.sublist(start, end);
... (do stuff and possibly alter list)
start = end;
I'm having a situation where only sometimes, that call to sublist will throw an IndexOutOfBoundsException. Given my first test of end < myList.size(), this troubled me, so I wrote some debug code. My debug code told me that somewhere between that while loop and calling sublist, my end value ended up being 34 while myList.size() was returning 33.
How is that even possible? There are no other threads that can be operating on this list in my program, so how did my loop check pass and increment end to 34?
EDIT: this consistently happens at a particular point in my code's execution, so it's not a fluke error, but it doesn't happen with every input that this function has, which makes this even stranger.

What you are describing is impossible.
Actually, the only way for this to happen is your own debugging: There are IDE features like code elements inspection that execute parts of the code while the application is paused on a breakpoint.
You have to be changing the value of end with the debugger tools.

My guess is along the lines of what #Jalitha said, off by one: the sublist call should be:
List<String> subList=myList.sublist(start,end-1);
The reason that you are sometimes getting the correct number probably has to do with your someOtherCondition.
Remember that size() is 1 more than the last index and subList works on indexes.
I would have put this in a comment but unable due to reputation :(

Aha! I've figured it out through careful debugging.
Turns out, on the loop iteration where this exception occurs, the end value is starting at 34. Thus, the increment loop passes, and there is an index error.
The reason is that in the previous iteration, myList.size() was 36, but over the course of that loop, 3 elements were removed.

Looks to me like a classic 'off-by-one' array error. You're likely having end equal to myList.size(), and then referencing one more ahead than you mean to.
From your while loop for e.g. if array had 5 elements:
while (end < 5 && conditions)
{
++end; //results in end being 5
}
then later on it goes
List<String> subList = myList.sublist(0, 5);
and 5 is outside the bounds as the array only has indices 0,1,2,3,4
I think you should either make it while (end+1 < 5 && conditions) or myList.sublist(0, end-1);
EDIT: Props to #Justen, for pointing out my mistake.

Related

Using If-Statement as test condition for For-Loop in Vb.net

I've been writing some software in Vb.net and I've come to a point in the program where it would be best if I could place an if-statement in the header of a for-loop.
For example, in java, I could achieve what I need like so..
for (int I = 0; myArray[I].compareTo("") == 0; I ++)
{
'code here
}
Unfortunately in Vb.net, all I know how to do is increment one number to a given number in a for-loop. I am aware however, that what I need to do can be accomplished using an if-test inside the for-loop
For I as Integer = 0 To myArray.length 'only possible test is comparison between two ints
'code here
If myArray(I).compareTo("") <> 0 Then
Exit For
End If
Next
Its not a big deal having to do this but if there is a way to streamline this more into the for-loop control then I would like to know for now and future reference.
So my question is, is it possible to check an if-condition (other than comparing two numbers) inside the header of a for-loop in Vb.net?
Update: In response to #Olivier Jacot-Descombes 's answer, I just wanted to clarify that I know while loops are used to test if-conditions in loops, but they lose the functionality of auto-incrementing possessed by for-loops. In Java, for-loops can do both of these. Which is why I'm wondering if Vb.net has the same functionality all within the header of a for-loop control somehow.
Use a While-Loop instead
Dim i As Integer = 0
While i < myArray.Length AndAlso String.IsNullOrEmpty(myArray(i))
'Code here
i += 1
End While
In VB a string can be empty ("") or Nothing (null in C#). In order to cope with both situations use String.IsNullOrEmpty(s).
AndAlso (unlike And) ensures shortcut evaluation. I.e. if the first condition is not True then the second will not be evaluated. We need this here, otherwise the array would throw an "Index out of bounds" exception. Note also that the array index goes from 0 to array.Length - 1.
But you can also exit from a For-loop with Exit For
For I As Integer = 0 To myArray.Length-1
'code here
If Not String.IsNullOrEmpty(myArray(I)) Then
Exit For
End If
Next
But exiting a loop like this can make the code unreadable. The problem is that the For-loop has now 2 exit points and loop and exit conditions defined at different places.
There is also a Do...Loop statement allowing you to test the condition at the end of the loop.
The short answer is no. Visual Basic languages don't have anything like the C/java style for() loop.
The longer answer is that depending on what you want, you might not even need a loop.
Dim a = {"a", Nothing, "", "b"}
' this will print from 0 to 1, but Array.IndexOf returns -1 if value is not found
For i = 0 To Array.IndexOf(a, "") - 1
Debug.Print(i & "")
Next
For Each item In a : If item = "" Then Exit For ' this is actually 2 lines separated by :
Debug.Print("'{0}'", item)
Next
For Each item In a.TakeWhile(Function(s) s > "") ' TakeWhile is a System.Linq extension
Debug.Print("'{0}'", item)
Next
a.TakeWhile(Function(s) s > "").ToList.ForEach(AddressOf Debug.Print) ' prints a
a.TakeWhile(Function(s) s > "").ToList.ForEach(Sub(s) Debug.Print(s)) ' prints a

Index Error with a For-Loop and a LinkedList

I am trying to make a little game on my own to get used to Java and I just had a problem with LinkedList Index. I found a way to patch my problem but I still don't understand why my first solution is not working. This code:
for (int i=0; i <= PlanetList.size(); i++)
{
g.drawImage(PlanetList.get(i).planetImage, PlanetList.get(i).xPos, PlanetList.get(i).yPos);
}
Gave me a java.lang.IndexOutOfBoundsException but this code:
for (int i=1; i <= PlanetList.size(); i++)
{
g.drawImage(PlanetList.get(i-1).planetImage, PlanetList.get(i-1).xPos, PlanetList.get(i-1).yPos);
}
The thing is ... my index start at 0 in both case. Why does the first gives me an Error?
Your last index in the first example is going above the allowed index range. For e.g., if the size of the list is 10, the allowed index range is [0 9]. In your first loop, it goes up to 10 (i <= PlanetList.size()). Change the terminal condition to i < PlanetList.size() to fix your issue.
The alternate is to use no indices to access elements in your list as #GhostCat has suggested:
for (Planet planet : PlanetList) {
g.drawImage(planet.planetImage, planet.xPos, planet.yPos);
}
This is called for-each loop in Java
The other solution is to simply use the index-free version to iterate "collections" that was introduced years ago:
for (Planet planet : PlanetList) {
g.drawImage(planet.planetImage, planet.xPos, planet.yPos);
As a nice side effect, that also eliminates the code duplication that you had in your example.
And while we are at it: you are somehow violating the "tell dont ask" principle. Meaning: you are asking your planet object to give all the details you need to draw it. In good Object Oriented designs, you avoid that. Instead, you tell objects to do something. In other words: you could change your planet class to
public void drawWith(Graphics g) { ...
With that the above code can be rewritten as:
for (Planet planet : ... ) {
planet.drawWith(g);
YOU are getting the Out of bounds error because the variable i declared in the for loop is running for less than equal to condition of planetlist size as i starts from zero it will go till the linked list size but since you have given less than equal to it goes in the loop one more time therefore out of bounds exception .Just change the for loop condition to i less than linked list size it will work

select odd/even elements of array using recursion

Am working on some programming homework and am a bit lost. The project is to select the even/odd elements of a listarray and store in another array. It is not the even numbers in each element, but the elements themselves so if an array had values "1,2,5,7,9" and returned the even elements it would give "1, 5, 9". Also have to use recursion. Would anyone be able to give me a starting point or some advice. Though about starting with 2 elements and taking 2nd element and then building up from that, but don't know how it would add on the 2nd pass
public static ArrayList<Integer> even(ArrayList<Integer> list)
ArrayList<Integer> evenlist = ListMethods.deepClone(tList);//make copy of list
if (evenlist.size()<=1) // The list is empty or has one element
{
// return null;// Return the list as is
}
if
(evenlist.size()==2)
{
//return right element
//call method again
//add to list
}
Psuedocode
int[] evens,odds;
function categorize(List<Integer> in,int idx)
if(idx>=in.length)
return
int cur = in[idx]
if(even), add to evens
else add to odds
categorize(in,idx+1)
This sounds similar to the homework I just completed, so if it is (And you're in my class!), I'll not tell you to use any terminology we haven't covered as I know it can be daunting trying to discover something new for practicals (beyond what we have to do).
First, set your exit condition. As you've already said, you have to create a new ArrayList out of the existing one. You are going to remove items from the existing ArrayList, storing the integers that are at even (or odd) indices, until the list is empty.
So your exit condition is:
if (evenList is Empty)
return evenList;
Then, work your way through the steps. I would advise determining if the Array you start with has an even of odd number of steps, something like this:
if (evenList has Even Elements)
int holderForIntsAtEvenElements = last evenList EVEN element
Note we start at the last element, so when you are coming OUT of the recursive method, this will be the last one added to your new ArrayList, and thus it'll be in numerical order. You might find this post interesting to do this: What does this boolean return mean?
We then want to remove the last element from the list and recursively call the method again.
Finally, when we hit our exit condition and start to come out, we want to add the ints we've been storing to them, e.g.:
evenList.add(holderForIntsAtEvenElements);
return evenList;
That doesn't solve one problem, which is what to do with the very first element if the list does NOT have an even number of elements - however, I'll let you try and solve that!
That's a good mix of code and pseudo code and will hopefully help to get you on the right track.
You could use a simple for loop like this:
for (int i = 0; i < list.size(); i += 2) {
System.out.println(list.get(i));
}
If you have to use recursion, here's an outline of the steps you might take. (I won't tell you exactly what to do because you haven't tried anything and it is like homework.)
Take first element and store it
Remove (new) first element from list
Call self

For Loops and Logical AND + OR [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Why does this code take not run?
for(int i=0;i<11;i++){
for(int j=0;j<11;j++){
if(i>0){
if((staticWallLoc[i--][j]&4)>0){staticWallLoc[i][j]=staticWallLoc[i][j]|1;}
}
if(j<10){
if((staticWallLoc[i][j++]&8)>0){staticWallLoc[i][j]=staticWallLoc[i][j]|2;}
}
if(i<10){
if((staticWallLoc[i++][j]&1)>0){staticWallLoc[i][j]=staticWallLoc[i][j]|4;}
}
if(j>0){
if((staticWallLoc[i][j--]&2)>0){staticWallLoc[i][j]=staticWallLoc[i][j]|8;}
}
System.out.println(i+" "+j);
}
}
By the way, staticWallLoc[11][11] is a two dimensional array that has 11 indexes in each dimension (0-10).
Just wondering why my program literally cannot get passed this code.
Dude - why are you decrementing in the loop body the same variables you're using to control the loop counter?!?
Sounds like "one step forward, two steps back", doesn't it ;)?
SUGGESTION:
Run the debugger, single step through a few iterations, and carefully note what happens to "i" and "j".
How soon do you think either or both will reach "11" ;)?
Inside your if(i > 0), i is decremented by staticWallLoc[i--]. Change it to staticWallLoc[i-1], and do the same for j.
if(i>0){
// Try something like this instead
if((staticWallLoc[i-1][j]&4)>0){
staticWallLoc[i][j]=staticWallLoc[i][j]|1;
}
}
You will also want to change your [i++] to [i+1].
In your loop, you have statements like if (i>0) {staticWallLoc[i--][j].... These are directly altering the loop index. So, when i is 1, it is changed back to 0. When the loop is incremented, it goes back to 1, and then 0 again, creating an infinite loop.
Do you perhaps mean to use staticWallLoc[i - 1][j]..., etc. ? This gets the desired index without changing the loop index.
rather than using i++ i-- etc in your code, just use offsets i-1 or i+1.
General rule of thumb: in for loops, don't mess with the for loop variables within the body.
(there are exceptions to the rule, but this doesn't look like an exceptional case)
Without knowing what the heck the contents of your array is it's hard to say. Might it be because you're modifying the values of i and j on the fly with -- and ++? Do you mean to be keeping those values constant and doing something like:
if((staticWallLoc[i+1][j]&1)>0){staticWallLoc[i][j]=staticWallLoc[i][j]|4;} // changed i++ to i+1
Once j reaches 10, it does not get incremented in the "if (j < 10)" section, but it gets decremented in the "if (j > 0)" section, so j will end the loop at 9, then get incremented back to 10 by the loop management. So you will have an infinite loop with i = -1/0 (since it gets decremented and incremented in the loop) and j = 9/10 (for the same reason).
You do a j-- in the last if once j >=10. The loop will stuck at j==10.
It's not a very good idea to manipulate the loop variable :)

Value (not index) greater than 3 in array causes java.lang.ArrayIndexOutOfBoundsException

I'm a novice programmer. This may be a simple problem but I've never seen this before. First of all, let me clarify that I'm not even trying to manipulate the index. Here's the part of the code that is causing the exception:
int[] bumpercatcher = new int[4];
//time variable that helps control events
int time = 0;
public void setup()
{
bumpercatcher[0]=4;
bumpercatcher[1]=4;
bumpercatcher[2]=4;
bumpercatcher[3]=4;
As you can see I'm trying to set them all equal to 4 at the start of the program. This causes the arrayindexoutofbounds exception. If I set them all equal to 0~3 then there is no problem (until I set them to a value greater than 3 later in the program). I don't understand it.
-it doesn't matter if I set the array size to 10, I still get the same exception
-it doesn't matter if I set only one of the values (i.e. at index 1, which is definitely within bounds of the array). same exception
Is there something I'm doing wrong? Thanks.
well, here' the entire code if you want to take a look(not too long, 1 class, bad programming practies): http://dl.dropbox.com/u/33501308/Pong.java
Here's the html from which you can see the program from (not much to see. it just freezes instantly.): http://dl.dropbox.com/u/33501308/bin.zip
by the way I'm using eclipse.
I don't really know what SSCEE is. sorry
Your posted code file includes loops along the lines of
for(int j: bumpercatcher) {
if(bumpercatcher[j]>5)
...
}
This is an issue. This is a different kind of loop than a traditional for loop. It is an extended or enhanced for, also called a foreach. It reads "for each integer j in array bumpercatcher do x." You are taking your element j (a value) and using it as an index to the array. When your value exceeds the maximum index, you will get an exception.
Write your code with a proper for loop if you want to access by index, or try simply restructuring your logic like
for (int j : bumpercatcher) {
if (j > 5) // j is the value!
...
}
I'm not sure what the problem is, but a far more readable way of doing this would be with a for loop:
for(int i = 0; i < bumpercatcher.length; i++) {
bumpercatcher[i] = 4;
}

Categories