In response to this comment from the OP.
However, #1 is required when updating (if not just mutating the current item or building the results as a new list) and comes with the index. Since the List<> is an ArrayList<> in this case, the get() (and size()) is O(1), but that isn't the same for all List-contract types.
Lets look at these issues:
It is certainly true that get(int)
is not O(1)
for all implementations of the List
contract. However, AFAIK, size()
is O(1)
for all List
implementations in java.util
. But you are correct that #1 is suboptimal for many List
implementations. Indeed, for lists like LinkedList
where get(int)
is O(N)
, the #1 approach results in a O(N^2)
list iteration.
In the ArrayList
case, it is a simple matter to manually hoist the call to size()
, assigning it to a (final) local variable. With this optimization, the #1 code is significantly faster than the other cases ... for ArrayList
s.
Your point about changing the list while iterating the elements raises a number of issues:
If you do this with a solution that explicitly or implicitly uses iterators, then depending on the list class you may get ConcurrentModificationException
s. If you use one of the concurrent collection classes, you won't get the exception, but the javadocs state that the iterator won't necessarily return all of the list elements.
If you do this using the #1 code (as is) then, you have a problem. If the modification is performed by the same thread, you need to adjust the index variable to avoid missing entries, or returning them twice. Even if you get everything right, a list entry concurrently inserted before the current position won't show up.
If the modification in the #1 case is performed by a different thread, it hard to synchronize properly. The core problem is that get(int)
and size()
are separate operations. Even if they are individually synchronized, there is nothing to stop the other thread from modifying the list between a size
and get
call.
In short, iterating a list that is being concurrently modified is tricky, and should be avoided ... unless you really know what you are doing.