Being somewhat new to the Java language I'm trying to familiarize myself with all the ways (or at least the non-pathological ones) that one might iterate through a list (or perhaps other collections) and the advantages or disadvantages of each.
Given a List<E> list object, I know of the following ways to loop through all elements:
Basic for loop (of course, there're equivalent while / do while loops as well)
// Not recommended (see below)!
for (int i = 0; i < list.size(); i++) {
E element = list.get(i);
// 1 - can call methods of element
// 2 - can use 'i' to make index-based calls to methods of list
// ...
}
Note: As @amarseillan pointed out, this form is a poor choice
for iterating over Lists, because the actual implementation of
the get method may not be as efficient as when using an Iterator.
For example, LinkedList implementations must traverse all of
the elements preceding i to get the i-th element.
In the above example there's no way for the List implementation to
"save its place" to make future iterations more efficient.
For an ArrayList it doesn't really matter, because the complexity/cost of get is constant time (O(1)) whereas for a LinkedList is it proportional to the size of the list (O(n)).
For more information about the computational complexity of the built-in Collections implementations, check out this question.
Enhanced for loop (nicely explained in this question)
for (E element : list) {
// 1 - can call methods of element
// ...
}
Iterator
for (Iterator<E> iter = list.iterator(); iter.hasNext(); ) {
E element = iter.next();
// 1 - can call methods of element
// 2 - can use iter.remove() to remove the current element from the list
// ...
}
ListIterator
for (ListIterator<E> iter = list.listIterator(); iter.hasNext(); ) {
E element = iter.next();
// 1 - can call methods of element
// 2 - can use iter.remove() to remove the current element from the list
// 3 - can use iter.add(...) to insert a new element into the list
// between element and iter->next()
// 4 - can use iter.set(...) to replace the current element
// ...
}
Functional Java
list.stream().map(e -> e + 1); // Can apply a transformation function for e
Iterable.forEach, Stream.forEach, ...
(A map method from Java 8's Stream API (see @i_am_zero's answer).)
In Java 8 collection classes that implement Iterable (for example, all Lists) now have a forEach method, which can be used instead of the for loop statement demonstrated above. (Here is another question that provides a good comparison.)
Arrays.asList(1,2,3,4).forEach(System.out::println);
// 1 - can call methods of an element
// 2 - would need reference to containing object to remove an item
// (TODO: someone please confirm / deny this)
// 3 - functionally separates iteration from the action
// being performed with each item.
Arrays.asList(1,2,3,4).stream().forEach(System.out::println);
// Same capabilities as above plus potentially greater
// utilization of parallelism
// (caution: consequently, order of execution is not guaranteed,
// see [Stream.forEachOrdered][stream-foreach-ordered] for more
// information about this).
What other ways are there, if any?
(BTW, my interest does not stem at all from a desire to optimize performance; I just want to know what forms are available to me as a developer.)
List, but if there are other interesting ways to work with, say, aCollection, I'd be interested to know them. – jacobq Aug 23 '13 at 19:11