Konstantin Yovkov
Konstantin Yovkov

Reputation: 62874

How can we avoid nested Collection.stream() calls?

Let's say we have the following Map

Map<String, List<String>> peopleByCity = new TreeMap<>();

with the following content:

{ "London" : [ "Steve", "John"],
  "Paris"  : [ "Thierry" ],
  "Sofia"  : [ "Peter", "Konstantin", "Ivan"] }

With the tools of the Stream API, for each pair of type [City ; Person], I would like to apply some operation, lets say printing:

 London : Steve
 London : John
 Paris  : Thierry
 Sofia  : Peter
 Sofia  : Konstantin
 Sofia  : Ivan

A possible (but not really neat) solution would be :

peopleByCity.entrySet()
            .stream()
            .forEach( entry -> {
                 String city = entry.getKey();
                 entry.getValue().
                      .stream()   <-- the nested Collection.stream() call
                      .forEach(
                         person -> System.out.println(city + ";" + person));
            });

How can we avoid the nested call to Collection.stream() by creating some chain of calls to other Stream/Collector features?

Upvotes: 0

Views: 977

Answers (1)

assylias
assylias

Reputation: 328913

One way would be to "flatMap" the lists:

peopleByCity.entrySet().stream()
        .flatMap(e -> e.getValue().stream().map(p -> e.getKey() + ";" + p))
        .forEach(System.out::println);

Another way would be to use two forEach:

peopleByCity.forEach((city, people) -> 
        people.forEach(person -> System.out.println(city + ";" + person)));

But in the end I don't think there is a simple way around streaming the lists, unless you write a custom collector (but then the nested stream will be in the collector).

Upvotes: 4

Related Questions