Evolution of the for loop in java
Let’s show the different alternatives of the for loop in java applied to a List
Defining the List<String>
we will use across the code:
List<String> names = Arrays.asList("foo", "bar", "baz", "foobar", "raboof");
Standard for loop
this is the for
loop found in different programming languages
for (int i = 0; i < names.size(); i++) {
doSomething(names.get(i));
}
Iterator for loop
slightly variation of the standard for
loop, note how we keep all 3 parts of the standard for
loop but the break condition uses the i.hasNext()
and the increment is in the loop’s body as i.next()
for (Iterator<String> i = names.iterator(); i.hasNext(); ) {
doSomething(i.next());
}
forEach loop
this loop was added in Java5.
note how the above Iterator
ceremony has been replaced by this new approach
although not a silver bullet it is a very convenient way of forward traversing this Collection
https://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html
for (String name : names) {
doSomething(name);
}
forEach Loop associated to a Collection
with lambda expression
J8 added the forEach to Collections
removing a bit more of the ceremony and clutter from before.
here with a lambda expression that takes 1 List
item as an argument and passes it to a function to process.
names.forEach(name -> doSomething(name));
with method reference
same as above, but we replaced the lambda expression with a method reference this removes all redundant mentions to arguments to be processed by a given function.
names.forEach(this::doSomething);
forEach loop associated to the Iterator
interface
also added in J8 and thou called forEachRemaining()
, according to the javadocs, this for
loop is implemented by default behaving as while(hasNext())
if you go to the actual Oracle’s hotSpot
class you will see that it actually is a while
loop!
private static void iteratorForEachRemaining() {
Iterator<String> iterator = names.iterator();
iterator.forEachRemaining(name -> doSomething(name));
}
//or why not with a method::reference
private static void iteratorForEachRemaining() {
Iterator<String> iterator = names.iterator();
iterator.forEachRemaining(this::doSomething);
}
BONUS - the ListIterator<T>
an oldie not very common to see… the ListIterator<T>
added in J2 is close to the iterator
with the added possibility of backwards traversing a list
.
it is basically used as an iterator
with the difference that when you want to traverse backwards a List
you specify the element on the List
you want use as the point from where you want to move backwards.
We are going to start from the very end of the List
in this example to show reverse traversing.
forward
// traversing forward
// same form as the Iterator but we use the ListIterator interface instead
for (ListIterator<String> listIterator = names.listIterator(); listIterator.hasNext(); ) {
doSomething(listIterator.next());
}
backwards
// traversing backwards
// we specify here the size of the list to position the iterator cursor at the very end of the list
for (ListIterator<String> listIterator = names.listIterator(names.size()); listIterator.hasPrevious(); ) {
doSomething(listIterator.previous());
}