I have seen people say to cache the values of size
for a list or length
for an array when iterating, to save the time of checking the length/size over and over again.
So
for (int i = 0; i < someArr.length; i++) // do stuff
for (int i = 0; i < someList.size(); i++) // do stuff
Would be turned into
for (int i = 0, length = someArr.length; i < length; i++) // do stuff
for (int i = 0, size = someList.size(); i < size; i++) // do stuff
But since Array#length
isn't a method, just a field, shouldn't it not have any difference? And if using an ArrayList, size()
is just a getter so shouldn't that also be the same either way?
It is possible the JIT compiler will do some of those optimizations for itself. Hence, doing the optimizations by hand may be a complete waste of time.
It is also possible (indeed likely) that the performance benefit you are going to get from hand optimizing those loops is too small to be worth the effort. Think of it this way:
The corollary is that:
Having said all of that:
theArr.length
is very fast, probably just a couple of machine instructions theList.size()
will probably also be very fast, though it depends on what List
class you are using. ArrayList
the size()
call is probably a method call + a field fetch versus a field fetch for length
.ArrayList
the size()
call is likely to be inlined by the JIT compiler... assuming that the JIT compiler can figure that out.length
fetch out of the loop. It can probably deduce that it doesn't change in the loop.size()
call, but it will be harder for it to deduce that the size doesn't change. What this means is that if you do hand optimize those two examples, you will most likely get negligible performance benefit.
In general the loss is negligible. Even a LinkedList.size()
will use a stored count, and not iterate over all nodes.
For large sizes you may assume the conversion to machine code may catch up, and optimize it oneself.
If inside the loop the size is changed (delete/insert) the size variable must be changed too, which gives us even less solid code.
The best would be to use a for-each
for (Bar bar: bars) { ... }
You might also use the somewhat more costing Stream:
barList.forEach(bar -> ...);
Stream.of(barArray).forEach(bar -> ...);
Streams can be executed in parallel.
barList.parallelStream().forEach(bar -> ...);
And last but not least you may use standard java code for simple loops:
Arrays.setAll(barArray, i -> ...);
We are talking here about micro-optimisations . I would go for elegance.
Most often the problem is the used algorithm & datastructurs. List
is notorious, as everything can be a List
. However Set
or Map
often provide much higher power/expressiveness.
If a complex piece of software is slow, profile the application. Check the break lines: java collections versus database queries, file parsing.
It is best not to call a method on every loop round, so you should avoid calling size() on the condition part that is evaluated on every round. If you use a for each loop, this does not apply.
for (int i = 0; i < foos.bar(); i++) // slow
for (int i = 0, size = foos.bar(); i < size; i++) // fast
for (Foo foo : foo.bar()) // fast
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.