5 Ways to Iterate Collections in Java
- Details
- Written by Nam Ha Minh
- Last Updated on 18 July 2024   |   Print Email
4. Using forEach method with Lambda Expressions
Before going to each kind of collection iteration, suppose that we have a List collection initialized as follows:List<String> listNames = new ArrayList<>(); listNames.add("Tom"); listNames.add("Mary"); listNames.add("Peter"); listNames.add("John"); listNames.add("Kim");This list contains names of all students in a class. Note that the diamond operator <>used in the right side of the assignment:
ArrayList<>();This syntax can be used from Java 7, which allows us to declare generics collections in a more compact way, as the compiler can infer the parameter type in the right side from the left side (thus the so-called type inference).Now, let’s look at each method in details.
1. Using Classic For Loop:
for (int i = 0; i < listNames.size(); i++) { String aName = listNames.get(i); System.out.println(aName); }Output:
Tom Mary Peter John KimHere are the pros of this method:
- This is the most familiar construct in programming.
- Useful if we need to access and use the counter variable, e.g. print the numeric order of the students: 1, 2, 3, etc.
- Using a counter variable requires the collection must store elements in form of index-based like ArrayList, and we must know the collection’s size beforehand.
- The collection must provide a method to access its elements by index-based, which not supported by all collections, e.g. a Set does not store elements as index-based. Thus this method cannot be used with all collections.
2. Using Iterator:
Due to the limitations of the classic for loop, the Iterator method is created to allow us to iterate all kinds of collections. Thus you can see the Collection interface defines that every collection must implement the iterator() method.The following example explains the concept of iterator:Iterator<String> iterator = listNames.iterator(); while (iterator.hasNext()) { String aName = iterator.next(); System.out.println(aName); }This code snippet does the same thing as the classic for loop example above. You may need some explanations:
- The hasNext() method returns true if the collection has more elements to traverse, otherwise return false.
- The next() method returns the current element. Note that we don’t have to cast the returned object as we use generics.
Set<Integer> numbers = new HashSet<>(); numbers.add(100); numbers.add(35); numbers.add(89); numbers.add(71); Iterator<Integer> iterator = numbers.iterator(); while (iterator.hasNext()) { Integer aNumber = iterator.next(); System.out.println(aNumber); }Output:
35 100 71 89And here’s another example demonstrating how to iterate over a Map using an interator:
Map<Integer, String> mapAscii = new HashMap<>(); mapAscii.put(65, "A"); mapAscii.put(66, "B"); mapAscii.put(67, "C"); mapAscii.put(68, "D"); Iterator<Integer> keyIterator = mapAscii.keySet().iterator(); while (keyIterator.hasNext()) { Integer key = keyIterator.next(); String value = mapAscii.get(key); System.out.println(key + " -> " + value); }Output:
65 -> A 66 -> B 67 -> C 68 -> DBecause the map stores elements in form of key=value pairs, first we need to get the iterator of the keys (a Set collection), then use this iterator to get each key, and retrieve the value corresponds to that key. Check this guide to learn more about using iterator in Java programming language.
3. Using Enhanced For Loop:
Since Java 5, programmers can use a more succinct syntax to iterate over a collection - It’s the enhanced for loop. For example, the following code uses the enhanced for loop to iterate over the listNames collection above:for (String aName : listNames) { System.out.println(aName); }Does it look nicer, doesn’t it? The code is more compact and more readable. That’s why this construct is called enhanced for loop - an enhanced feature of the Java programming language. NOTES: The enhanced for loop actually uses an iterator behind the scenes. That means the Java compiler will convert the enhanced for loop syntax to iterator construct when compiling. The new syntax just gives the programmers a more convenient way for iterating over collections.Using the enhanced for loop, we can re-write the code to iterate the Set collection above like this:
for (Integer aNumber : numbers) { System.out.println(aNumber); }Compare to the previous code (using iterator), this code is incredible simpler and more understandable right?And the code that iterates over a Map can be re-written using the enhanced for loop like this:
for (Integer key : mapAscii.keySet()) { String value = mapAscii.get(key); System.out.println(key + " -> " + value); }Wow! This looks much simpler than the previous code using iterator, right? Thanks to the enhanced for loop - it helps programmers write code more quickly and more readable.As the Java programming language evolves, we have a new method which is describe below.
4. Using forEach Method with Lambda Expressions:
Java 8 with Lambda expressions, introduces a totally new way for iterating over collections - it’s the forEach method.What’s the biggest difference between the forEach method and the previous ones?Well, in the previous methods (classic for loop, iterator and enhanced for loop), the programmers control how the collection is iterated. The iteration code is not part of the collection itself - it’s written by programmers - hence the term external iteration.In contrast, the new method encapsulates the iteration code in the collection itself, thus the programmers do not have to write code for iterating collections. Instead, the programmers specify what-to-do in each iteration - this is the big difference! Hence the term internal iteration: the collections handle the iteration itself, whereas the programmers pass the action - what needs to do in each iteration.The following example helps you understand the concepts:listNames.forEach(name -> System.out.println(name));Amazing! This code looks even more compact and more readable than the enhanced for loop version. As we can read the above line like this: for each element in the listNames, print the name to the console.Since Java 8, each collection has a forEach() method that implements the iteration internally. Note that this method takes a Lambda expression or in other words, the programmers can pass their code - or function - into this method. As shown in the above example, the code to print each element is passed into the method.If you are new to Lambda expressions, check this tutorial:
Lambda Expressions - The Java Tutorials
To help you understand more. Suppose that we have some code to deal with each student name like this:class StudentHelper { public static void process(String name) { System.out.println("processing the student " + name); } }Then we can pass this code into the forEach() method like this:
listNames.forEach(StudentHelper::process);As you can see, this is the power of using Lambda expressions with the internal iteration method. The code is highly compact, more readable and more flexible.Similarly, we can use the forEach method to iterate over the Set above like this:
numbers.forEach(number -> System.out.println(number));Or even more compact:
numbers.forEach(System.out::println);And code to iterate over the Map above using the forEach method:
mapAscii.forEach((key, value) -> System.out.println(key + " -> " + value));WOW! Incredible simple, right?
5. Using Java Stream API
Since Java 8, programmers can use Stream API to iterate and process elements in collections in convenient and flexible manner. The following code example shows how to iterate over each name in the listNames collection and convert each element to upper case, and then use forEach with Lambda expressio to print out uppercase form of each name:listNames.stream().map(e -> e.toUpperCase()).forEach(System.out::println);To learn more about Java Stream API, check this tutorial. So far I have walked you through the five different ways for iterating over collections in the Java programming language: classic for loop, iterator, enhanced for loop, for each and Java Stream API. The later is always better than the former, that’s how the language evolves over time. Using which one is depending on your need and personal style.Nowadays, the forEach method has been being adopted and preferred as it is deadly simple, convenient and flexible.
Related Tutorials:
- How to use for keyword in Java
- How to use do-while construct in Java
- Java Collections Looping Example
- Using Java 8 Lambda expressions for collections internal iteration
Other Java Collections Tutorials:
- What is Java Collections Framework?
- Java Queue Tutorial
- Java List Tutorial
- Java Set Tutorial
- Java Map Tutorial
- Understand equals and hashCode
- Understand object ordering
- 18 Java Collections and Generics Best Practices
Comments