Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Iterating over collections

Almost any work with a collection comes down to going through its elements: print them, count them, filter them. Java has several ways to do this, and each has its place.

The for-each loop

The simplest way is the for-each loop. It works with any collection: a list, a set, a queue:

void main() {
    List<String> names = List.of("Anna", "Oleg", "Ira");
    for (String name : names) {
        IO.println("Hello, " + name);
    }
}

Output:

Hello, Anna
Hello, Oleg
Hello, Ira

It reads like this: "for each name in names".

Iterating by index

If you need the element's number, use an ordinary for loop with an index. This works only for lists — a set has no indexes:

void main() {
    List<String> places = List.of("Anna", "Oleg", "Ira");
    for (int i = 0; i < places.size(); i++) {
        IO.println("Place " + (i + 1) + ": " + places.get(i));
    }
}

Output:

Place 1: Anna
Place 2: Oleg
Place 3: Ira

The forEach() method

Every collection has a forEach() method. You pass it an action in the form of a lambda — a short way to write a function: the parameter on the left of the arrow, what to do with it on the right:

void main() {
    List<Integer> prices = List.of(10, 25, 7);
    prices.forEach(price -> IO.println(price + " €"));
}

Output:

10 €
25 €
7 €

Lambdas are covered in detail in the next chapter; for now this form is enough.

Iterating a map

A map is not a collection of elements but a set of pairs. You can go through only the keys (keySet()), only the values (values()) or whole pairs. The most convenient way is forEach() with two parameters:

void main() {
    Map<String, Integer> scores = new TreeMap<>(Map.of("Oleg", 75, "Anna", 90));
 
    for (String name : scores.keySet()) {
        IO.println(name);
    }
    scores.forEach((name, score) -> IO.println(name + " → " + score));
}

Output:

Anna
Oleg
Anna → 90
Oleg → 75

Removing while iterating

To remove elements by a condition, collections have the removeIf() method. It takes a condition and removes all matching elements by itself:

void main() {
    List<Integer> numbers = new ArrayList<>(List.of(1, 2, 3, 4, 5, 6));
    numbers.removeIf(n -> n % 2 == 0);
    IO.println(numbers);
}

Output:

[1, 3, 5]

An older way is an Iterator object: its hasNext() and next() methods go through the elements, and remove() safely deletes the current one. How to write your own iterator so that for-each can loop over your class is shown in the your own Iterable lesson.

Common mistake

Inside a for-each loop you cannot remove elements from the same collection. The list notices that it was changed during iteration and throws an exception:

void main() {
    List<String> items = new ArrayList<>(List.of("bread", "milk", "cheese", "tea"));
    for (String item : items) {
        if (item.equals("milk")) {
            items.remove(item);
        }
    }
}

Output:

Exception in thread "main" java.util.ConcurrentModificationException

Use items.removeIf(item -> item.equals("milk")) or an Iterator with its remove() method.

Thanks for reading!

Donate to the site — we work hard for you.