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.
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.
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;
}
Related
I have quick question
Does it matter if I use clause this way :
for(Object obj : something.b.c.d.getList(){
...
}
or this
List list = something.b.c.d.getList();
for(Object obj : list){
...
}
I'm wondering if one is faster than other
The main difference is stylistic. The semantics are pretty much the same. The only significant semantic difference is that, in the second example, the list reference is named and can be accessed both inside and after the loop:
List list = something.b.c.d.getList();
for(Object obj : list){
if (list.contains(...)) { // inefficient, used purely as an illustration
...
}
}
int n = list.size();
The above cannot be achieved in the first example without evaluating something.b.c.d.getList() again.
If you are concerned that the first example repeatedly evaluates something.b.c.d.getList(), that's certainly not the case. Both of your examples evaluate the expression exactly once.
There's likely no difference in performance, but performance overall would depend on how expensive it is to access those fields (i.e. lazy loading from a framework). Accessing the fields would only happen once, regardless of whichever style you chose to use for this loop.
Both approaches are acceptable if both items are something that can be used in the enhanced-for statement.
I wouldn't concern myself with optimizations like this unless a profiler designated this particular area of your code as a trouble spot.
I often come across cases where I want to use an enchanced for-loop for some Collection or array that I get from some object.
e.g.
items = basket.getItems();
for (int item : items) {
// Do something
}
Another way to do that is:
for (int item : basket.getItems()) {
// Do something
}
The second one is more compact and improves readability in my opinion, especially when the item variable won't be used anywhere else.
I would like to know whether the getter in the for statement has any impact in performance. Will it be optimized to something similar to the 1st one? Or will it access the getter every time? Of course the getItems() might do something quite slow (e.g. network access, etc)
Question is similar to some others, but is referring to the getter of the collection/array itself and not the size of it. However, it may be the same case in the end.
The getItems() method will be called only once in both cases. There is no difference between the two, apart from one using an extra local variable which you could use somewhere else.
As you can read in JLS 14.14.2, the enhanced for loop is translated roughly to this traditional for loop:
for (I #i = Expression.iterator(); #i.hasNext(); ) {
TargetType Identifier = (TargetType) #i.next();
Statement
}
#i is an automatically generated identifier that is distinct from any other identifiers (automatically generated or otherwise) that are in scope (§6.3) at the point where the enhanced for statement occurs.
From here it's clear that Expression is evaluted only once.
As you can see on the following code sample, on the enhanced for, the initialization of the collection on which to iterate is done only once. So, the second choice is more compact, and does not impact performance.
package test;
public class Main {
static class Basket {
int[] items = { 1, 2, 3 };
public int[] getItems() {
System.out.println("in getItems()");
return items;
}
}
public static void main(String[] args) {
Basket basket = new Basket();
for (int item : basket.getItems()) {
System.out.println(item);
}
}
}
Yes second one improves readability of code.
if you are getting the objects from network and then iterating over it in a for loop then I think yes it has performance impact because you are making network access every time and that is inefficient also as for a small/single object doing network access is not recommended. instead of that get it once from network access store it locally and iterate over it
thus 1st option is performance optimized in network access case
if your object is local then any method will do. there wont be much performance difference.
I don't think it will call getter every time. If it does it will get new list every time and Loop wont break. You can test this by putting simple Sysout inside getter method. Performance will be same in these two cases.
I am having a discussion (read argument!) with one of my colleagues. I maintain that this code is very wrong but he thinks there is nothing wrong with it:
for (Iterator<String> iter = collectionOfStrings.iterator(); iter.hasNext();) {
String item = iter.next();
...
}
I maintain that this code is wrong because there is a duplication of looping. Either use Iterator or use a For loop but there is no need to use them both at the same time.
I would re-write the code as follows:
Iterator<String> iter = collectionOfStrings.iterator();
while (iter.hasNext()) {
String item = iter.next();
...
}
What do you think?
Neither code is not "wrong", in the sense that both do what is expected. The second code, although equivalent, pollutes the local variables, because iter remains defined after the loop ends.
Both of your examples are syntactically correct. One advantage of putting the declaration in the for loop is that the variable is released after the code block ends, whereas the iterator persists after the while loop ends
The second is good.
The first is slightly better. It limits the loop variable's scope.
But since Java 1.5, the foreach loop can sometimes be more elegant than either:
for ( String item : collectionOfStrings ) {
...
}
Actually it's the same. For is just a variation of while, or while is just a variation of for, however you like to put it. You can write a for
for (init;cond;incr){
...
}
like this
init
while(cond){
....
incr
}
Your colleague is right. The first code, with the for loop, should run just fine.
In fact, while is also a loop, so both your code and his contains one loop and iterator.
I am new in Java and I have a problem in using if statement within while loop.
I wrote the code as follows:
while(lexicalizations.hasNext())
{
myObject = lexicalizations.next().getObject();
language= myObject.getTermLanguage();
if (language.equals(languageCode)) {
System.out.println(lexicalizations.next());
}
}
However, whenever the if condition is true, the program executes its block and then terminates the while loop. So, the rest of items are not checked out.
How could I solve that?
Thanks so much.
Cheers,
Aya.
Each invocation of Iterator.next() moves the iterator to the next element of the collection, therefore you must be very careful not to call this method more than once per iteration. You must save the element into a local variable and work with the variable throughout the loop body.
In order to systematically avoid this kind of pitfalls, always prefer to use the enhanced for loop whenever applicable:
for (String lex : lexicalizations) {
... your code uses lex here ...
}
Note that when you do that println you "consume" the next element, so if there is only one left there will be zero when you get back to the while.
You are moving to the next object in the iterator within if statement block. To avoid this just use myObject and you will 'visit' every object:
while (lexicalizations.hasNext())
{
myObject = lexicalizations.next().getObject();
language= myObject.getTermLanguage();
if (language.equals(languageCode)) {
System.out.println(myObject);
}
}
I had an argument with my friend regarding this.
Consider the below snippet,
for(i=0; i<someList.size(); i++) {
//some logic
}
Here someList.size() will be executed for every iteration, so it is recommended to migrate this size calculation to outside(before) the loop.
Now what happens when I use an extended for loop like this,
for(SpecialBean bean: someBean.getSpecialList()) {
//some logic
}
Is it necessary to move someBean.getSpecialList() to outside the loop?
How many times will someBean.getSpecialList() execute if I were to retain the 2nd snippet as it is?
Repeated calls to list.size() won't result in any performance penalty. The JIT compiler will most probably inline it and even if it doesn't, it will still be quite inexpensive because it just involves reading the value of a field.
A much more serious problem with your first example is that the loop body will have to involve list.get(i) and for a LinkedList, acessing the i th element has O(i) cost with a quite significant constant factor due to pointer chasing, which translates to data-dependent loads on the CPU level. The CPU's prefetcher can't optimize this access pattern.
This means that the overall computational complexity will be O(n2) when applied to a LinkedList.
Your second example compiles to iteration via Iterator and will evaluate someBean.getSpecialList().iterator() only once. The cost of iterator.next() is constant in all cases.
From Item 46 in Effective Java by Joshua Bloch :
The for-each loop, introduced in release 1.5, gets rid of the clutter
and the opportunity for error by hiding the iterator or index
variable completely. The resulting idiom applies equally to
collections and arrays:
// The preferred idiom for iterating over collections and arrays for
(Element e : elements) {
doSomething(e); } When you see the colon (:), read it as “in.” Thus, the loop above reads as “for each element e in elements.” Note
that there is no performance penalty for using the for-each loop, even
for arrays. In fact, it may offer a slight performance advantage over
an ordinary for loop in some circumstances, as it computes the limit
of the array index only once. While you can do this by hand (Item 45),
programmers don’t always do so.
See also is-there-a-performance-difference-between-a-for-loop-and-a-for-each-loop
An alternative to the first snippet would be:
for(i=0, l=someList.size(); i<l; i++) {
//some logic
}
With regard to the for..each loop, the call to getSpecialList() will only be made once (you could verify this by adding some debugging/logging inside the method).
As the extended loop uses an Iterator taken from the Iterable, it wouldn't be possible or sensible to execute someBean.getSpecialList() more than once. Moving it outside the loop will not change the performance of the loop, but you could do it if it improves readability.
Note: if you iterate by index it can be faster for random access collections e.g. ArrayList as it doesn't create an Iterator, but slower for indexed collections which don't support random access.
for each variation will be same as below
for (Iterator i = c.iterator(); i.hasNext(); ) {
doSomething((Element) i.next());
}
From Item 46: Prefer for-each loops to traditional for loops of Effective java
for-each loop provides compelling advantages over the tradi-
tional for loop in clarity and bug prevention, with no performance penalty. You
should use it wherever you can.
So My first guess was wrong there is no penalty using function inside for each loop.