3

Possible Duplicate:
for loop optimization

In java i have a block of code:

List e = {element1, element2, ...., elementn};
for(int i = 0; i < e.size(); i++){//Do something in here
};

and another block:

List e = {element1, element2, ...., elementn};
int listSize = e.size();
for(int i = 0; i < listSize; i++){//Do something in here
};

I think that the second block is better, because in the first block, if i++, we have to calculate e.size() one more times to compare the condition in the for loop. Is it right or wrong? And comparing the two block above, what is the best practice for writing for? And why?Explain clearly and try this loop yourself

Community
  • 1
  • 1
Kingfisher Phuoc
  • 8,052
  • 9
  • 46
  • 86

12 Answers12

14

Personally I'd use the enhanced for statement instead:

for (Object element : e) {
    // Use element
}

Unless you need the index, of course.

If I had to use one of the two forms, I'd use the first as it's tidier (it doesn't introduce another local variable which is only used in that loop), until I had concrete evidence that it was causing a problem. (In most list implementations, e.size() is a simple variable access which can be inlined by the JIT anyway.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    [http://developer.android.com/guide/practices/design/performance.html](http://developer.android.com/guide/practices/design/performance.html) As i read in the link before, the second block is better than the first one! :( – Kingfisher Phuoc May 11 '12 at 08:52
  • 2
    @Kingfisher: That's *specifically* for Android, where the JIT was more primitive, although I wouldn't be surprised to hear that it copes with this situation now anyway. But in general, *don't micro-optimize without evidence*. – Jon Skeet May 11 '12 at 09:04
6

Usually, the most brief and readable code is the best choice, all things being equal. In the case of Java, the enhanced for loop (which works with any class that implements Iterable) is the way to go.

for (Object object : someCollection) { // do something }

In terms solely of the two you posted, I think the first is the better option. It's more readable, and you have to remember that, under the hood, JIT will attempt to optimize a great deal of the code you write anyway.

EDIT: Have you heard the phrase "premature optimisation is the root of all evil"? Your second block is an example of premature optimisation.

Jon
  • 3,510
  • 6
  • 27
  • 32
  • As Jon Skeet suggests, if for some reason you need the index into the collection you are iterating over, take use the first form of the loop. – Jon May 11 '12 at 08:34
  • 1
    +1 achievable and comprehensive – GingerHead May 11 '12 at 08:36
  • 1
    [_Link Here_](http://developer.android.com/guide/practices/design/performance.html) As i read in the link here, the second block is better than the first one! – Kingfisher Phuoc May 11 '12 at 08:48
  • @Kingfisher that is interesting. But at the start of the document it does say this: "This document is about Android-specific micro-optimization, so it assumes that you've already used profiling to work out exactly what code needs to be optimized" – Jon May 11 '12 at 13:00
5

I would always use (if you need an index variable):

List e = {element1, element2, ...., elementn};
for(int i = 0, size = e.size(); i < size; i++){
    // Do something in here
};

Since e.size() could be an expensive operation.

Your 2nd option is not good, since it introduces a new variable outside of the for loop. I recommend to keep variable visibility as limited as possible.

Otherwise a

for (MyClass myObj : list) {
    // Do something here
}

is even cleaner, but might introduce a small performance hit (the index approach doesn't require to instantiate an Iterator).

Moritz Petersen
  • 12,902
  • 3
  • 38
  • 45
  • +1 for the initalisation of a size variable in the for loop, I think it's pretty elegant (although I don't believe in micro-optimisation, unless it's REALLY necessary). Anyway, good snippet :) – szegedi Oct 27 '12 at 23:51
  • -1 e.size() it's NOT an expensive operation, why would it be!? if you decompile implementation of e.size() method you will see that's just return size variable, and that's not "expensive" operation. – Andrea Bori Jan 31 '17 at 10:19
  • @AndreaBori that's just an example. Of course it is not an expensive operation for a simple `List`. But it is best practice to not use a method call in the condition part of a for loop. – Moritz Petersen Jan 31 '17 at 12:16
4

If you check the size() implementation on a LinkedList class, you will find that the size is incemented or decremented when an element is added or removed from the list. Calling size() just returns the value of this property and does not involve any calculation.
So directly calling size() method should be better as you will save on the save for another integer.

NiranjanBhat
  • 1,812
  • 13
  • 17
2

Yes, the second form is marginally more efficient as you don't repeated perform the size() method invocation. Compilers are good are doing this sort of optimisation themselves.

However, it's unlikely that this would be the performance bottleneck of your application. Avoid premature optimisation. Make your code clean and readable foremost.

Greg Kopff
  • 15,945
  • 12
  • 55
  • 78
1

Second one is better approach because in the first block, you are calling the e.size() is a method which is an operation in a loop that is a extra burden to JVM.

UVM
  • 9,776
  • 6
  • 41
  • 66
  • 1
    Best practice suggests writing the most *readable* code first, rather than micro-optimizing... – Jon Skeet May 11 '12 at 08:27
  • Thanks @JonSkeet. But in many places it is often misread or misunderstood.I also thought that best practices means, writing code that will be too lite for JVM to execute. – UVM May 11 '12 at 08:49
1

HotSpot will move e.size() from cycle in most cases. So it will calculate size of List only once.

As for me I prefer the following notation:

for (Object elem: e) {
   //Do something
}
yatul
  • 1,103
  • 12
  • 27
1

i think this should be much more better.. may be initializing the int variable every time can be escaped from this..

List e = {element1, element2, ...., elementn};
int listSize = e.size();
int i=0;
for(i = 0; i < listSize; i++){//Do something in here
};
Punith Raj
  • 2,164
  • 3
  • 27
  • 45
0

Im not so sure but i think the optimizer of java will replace the value with a static value, so in the end it will be the same.

memo
  • 441
  • 2
  • 6
0

To avoid all this numbering and iterators and checkings in writing the code use the following simple most readable code that has its performance to maximum. Why this has maximum performance (details are coming up)

for (Object object : aCollection) { 
// Do something here
}

If the index is needed then:
To choose between the above two forms:
The second is the better as you said because it only calculated the size once.

GingerHead
  • 8,130
  • 15
  • 59
  • 93
0

I think now we have a tendency to write short and understandable code, so the first option is better.

Michał Skóra
  • 351
  • 2
  • 6
  • 18
-1

the second is better , cos in the firt loop in the body of it maybe u will do this statment e.remove, and then the size of e will be changed , so it is better to save the size in a parameter before the looop

William Kinaan
  • 28,059
  • 20
  • 85
  • 118
  • Wouldn't that throw a ConcurrentModificationException (or something like that)? – jahroy May 11 '12 at 08:24
  • no , it will no throw any exception if u remove an element of a list inside a loog , just u will get an element without scaning – William Kinaan May 11 '12 at 08:26
  • If you remove an item from the list, the size will indeed be changed - so your loop boundary is then broken. Sounds like an argument for the first form to me (although you'd *also* have to decrement `i` to avoid skipping an element). – Jon Skeet May 11 '12 at 08:26
  • I guess it will actually just throw an IndexOutOfBoundsException if you don't adjust the variable used to keep track of the list size. – jahroy May 11 '12 at 08:31
  • no it will not , cos the size of the list in ur first cas calcualte dynamicly for every value of i , it is not static – William Kinaan May 11 '12 at 08:32
  • I'm talking about the Exception getting thrown with Option 2 (since that's what was suggested by this answer). If you use option 2 and remove an element from the list, you will get an Exception if you attempt to access every element. – jahroy May 11 '12 at 08:34