Five for loops in Java
- List of strings
- Traditional for loop
- Enhanced for loop from Java 5
- forEach lambda from Java 8
- Stream.iterate with one lambda from Java 8
- Stream.iterate with two lambdas from Java 9
- All five for loops together
The main conceptual difference between for
and while
loops is that a for loop uses some form of index or counting variable to track what row, record or iteration you are up to whereas a while loop does not.
Here are five ways to use "for loops" in Java.
List of strings
I start out with a list of strings.
final List<String> strings = Arrays.asList("one", "two", "three", "four", "five");
Traditional for loop
The traditional for loop allows us to specify three things:
- The
seed
value: the initial value to give our index. The seed is 0 in this example. - The
hasNext
condition (a.k.a. exit condition): a boolean expression to answer the question should we continue? In our example, we continue as long asindex
is less than the size of thestrings
list. - The
next
value: an expression to generate the next index. In our example, we getnext
by adding 1 to index.
System.out.printf("Old school for loop.%n"); for (int index = 0; index < strings.size(); index++) { System.out.printf("Next string is %s%n", strings.get(index)); }
Enhanced for loop from Java 5
In Java 5, we got the enhanced for loop, which feels more like a while
loop because we don't have an index any more. The enhanced for loop specifically helps us in situations where you are iterating over all items in a collection. You don't need to specify seed
, hasNext
or next
: they are all implied. Start with the first element, end with a last element and make sure we loop over each element in between.
System.out.printf("%nEnhanced for loop from Java 5.%n"); for (final String string : strings) { System.out.printf("Next string is %s%n", string); }
forEach lambda from Java 8
Java 8 gave us lambdas and a new way to loop over elements. Again, this feels more like a while in some ways because we don't have an index.
Just like the enhanced for loop, it is perfect for situations where you have a collection and you want to do something with each element. Any collection in Java has forEach
(through the java.lang.Iterable
interface).
System.out.printf("%nThe forEach lambda from Java 8.%n"); strings.forEach(string -> System.out.printf("Next string is %s%n", string));
Java 8 introduced java.util.stream.Stream
and gave us a whole new way to think about looping. Instead of thinking about how to formulate a while or for loop (by specifying seed and exit conditions), with streams we focus on defining the set of values (a stream) that we want to operate on. Stream also has forEach
, so we start thinking more about "iterating over a stream of values".
Stream.iterate with one lambda from Java 8
Stream.iterate
provides a way to use for loop ideas with a stream of values.
System.out.printf("%nUsing Stream.iterate with one lambda from Java 8.%n"); Stream.iterate(0, index -> index + 1) .limit(strings.size()) .forEach(index -> { System.out.printf("Next string is %s%n", strings.get(index)); });
This version of iterate()
has only two arguments, allowing us to specify:
- The
seed
value: the initial value to give our index. The seed is 0 in this example. - The
next
value: an expression to generate the next index. In our example, we getnext
by adding 1 to index.
We still need a way to provide the exit condition though, so I have added a limit()
call from the Stream
API.
Stream.iterate with two lambdas from Java 9
Stream.iterate
in Java 9 got overloaded to give a way to specify all three things we use in a traditional for loop.
System.out.printf("%nUsing Stream.iterate with two lambdas from Java 9.%n"); Stream.iterate(0, index -> index < strings.size(), index -> index + 1).forEach(index -> { System.out.printf("Next string is %s%n", strings.get(index)); });
Now we can give:
- The
seed
value: the initial value to give our index. The seed is 0 in this example. - The
hasNext
condition (a.k.a. exit condition): a boolean expression to answer the question should we continue? In our example, we continue as long asindex
is less than the size of thestrings
list. - The
next
value: an expression to generate the next index. In our example, we getnext
by adding 1 to index.
All five for loops together
In summary, the techniques all together are below.
import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public final class Scrapbook { public static void main(final String[] args) { final List<String> strings = Arrays.asList("one", "two", "three", "four", "five"); System.out.printf("Old school for loop.%n"); for (int index = 0; index < strings.size(); index++) { System.out.printf("Next string is %s%n", strings.get(index)); } System.out.printf("%nEnhanced for loop from Java 5.%n"); for (final String string : strings) { System.out.printf("Next string is %s%n", string); } System.out.printf("%nThe forEach lambda from Java 8.%n"); strings.forEach(string -> System.out.printf("Next string is %s%n", string)); System.out.printf("%nUsing Stream.iterate with one lambda from Java 8.%n"); Stream.iterate(0, index -> index + 1).limit(strings.size()).forEach(index -> { System.out.printf("Next string is %s%n", strings.get(index)); }); System.out.printf("%nUsing Stream.iterate with two lambdas from Java 9.%n"); Stream.iterate(0, index -> index < strings.size(), index -> index + 1).forEach(index -> { System.out.printf("Next string is %s%n", strings.get(index)); }); } }
Which gives the following output.
Old school for loop. Next string is one Next string is two Next string is three Next string is four Next string is five Enhanced for loop from Java 5. Next string is one Next string is two Next string is three Next string is four Next string is five The forEach lambda from Java 8. Next string is one Next string is two Next string is three Next string is four Next string is five Using Stream.iterate with one lambda from Java 8. Next string is one Next string is two Next string is three Next string is four Next string is five Using Stream.iterate with two lambdas from Java 9. Next string is one Next string is two Next string is three Next string is four Next string is five