Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List object reference changed during Java loop

I couldn't find any topic about this. I want to know if it is safe to change the reference for the list class during a loop like the one bellow:

Tree minimalTree = someTree;
for (Tree st : minimalTree.getSubtrees()) {
  if (condition)
    minimalTree = st;
}

Does the iterator gets reset and starts again for the new reference?

Edit: I forgot to say: this code is suited for situations where I want to narrow down the search for elements in the tree, let's say, the smaller tree that contains certain elements. In this case, it would be faster to keep looking only for the inner structures of "minimalTree" instead of the entire "someTree" structure.

like image 846
Pablo Faria Avatar asked Feb 24 '15 21:02

Pablo Faria


People also ask

Can we modify a list while iterating Java?

Even though java. util. ArrayList provides the remove() methods, like remove (int index) and remove (Object element), you cannot use them to remove items while iterating over ArrayList in Java because they will throw ConcurrentModificationException if called during iteration.

Can we update list while iterating?

Because you iterate over a copy of the list, you can modify the original list without damaging the iterator.

How do you iterate through a list of objects?

Obtain an iterator to the start of the collection by calling the collection's iterator() method. Set up a loop that makes a call to hasNext(). Have the loop iterate as long as hasNext() returns true. Within the loop, obtain each element by calling next().

Is a for loop pass by reference?

The loop simply gives you a reference to the next item in the list on each iteration. It does not let you change the original list itself (that's just another set of balloon labels); instead it gives you a new label to each of the items contained.


2 Answers

No, the iteration won't be reset. According to the JLS:

The enhanced for statement is equivalent to a basic for statement of the form:

for (I #i = Expression.iterator(); #i.hasNext(); ) {
     {VariableModifier} TargetType Identifier = (TargetType) #i.next();
     Statement
}

The definition makes it obvious that the iterator is only initialised once, before the first iteration of the loop.

The behaviour when iterating across an array with an enhanced for statement is similar in this respect.

However I'd personally consider it poor practice as it makes the code hard to understand.

like image 154
biziclop Avatar answered Sep 28 '22 04:09

biziclop


Actually, there are two questions:

I want to know if it is safe to change the reference for the list class during a loop like the one bellow:

Yes, it is safe. And for safe I mean: changing the reference does not interfere with the already running loop.

Does the iterator gets reset and starts again for the new reference?

No, the iterator is never reset. It would be exactly the opposite of safe.

In my opinion, it is not a good practice to change iterator or collection variables inside a loop. It makes the code harder to understand, and probably the result is not what you expect when you do that (like in your case I understood you expected the loop to start over reevaluating the collection).

In your case, encapsulate in a method and recursively call it on subtree:

Tree findMinimalTree(Tree tree) {
   for (Tree st : tree.getSubtrees()) {
     if (condition)
       return findMinimalTree(st);
   }
   return tree;
}
like image 41
Filipe Borges Avatar answered Sep 28 '22 05:09

Filipe Borges