Iteration is one of the basic operations carried on a collection. Basically, an iteration takes elements from a collection one after another, from the first element to the last one.

For example, you may want to go through all students in a class to print their names or to find who have high scores in the recent exam. Or you may want to traverse through a list of numbers in order to calculate the sum and average. Such kinds of operations are very common in programming.

The Java programming language provides 5 different ways for iterating over elements in collections, including for loops, iterator and forEach (since Java 8). In this article, I will share with you the following methods which you can use for collection iteration:

1. Using Classic For Loop

2. Using Iterator

3. Using Enhanced For Loop

4. Using forEach method with Lambda Expressions

5. Using Java Stream API

 

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:



This iteration method is very familiar in programming in which a counter variable runs from the first element to the last one in the collection. Here’s the code that iterates over the listNames collection above:

for (int i = 0; i < listNames.size(); i++) {
	String aName = listNames.get(i);
	System.out.println(aName);
}
Output:

Tom
Mary
Peter
John
Kim
Here 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.
And here are the cons:

  • 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.
Here’s another example that illustrates how to iterate over a Set using an Iterator:

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
89
 

And 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 -> D
Because 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.

 

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:

 

Other Java Collections Tutorials:


About the Author:

is certified Java programmer (SCJP and SCWCD). He started programming with Java in the time of Java 1.4 and has been falling in love with Java since then. Make friend with him on Facebook and watch his Java videos you YouTube.



Add comment

   


Comments 

#2melik yunus2019-12-12 05:22
i like it man. thank you so much
Quote
#1akshay singh nayal2019-12-05 23:52
Very nice article .great explanation with good examples.
Quote