flatMapping()

For a quick reminder about flattening a stream, it is advisable to read the Map a stream section.

Now, let's assume that we have the following list of Melon (notice that we've added the names of pests as well):

List<Melon> melonsGrown = Arrays.asList(
new Melon("Honeydew", 5600,
Arrays.asList("Spider Mites", "Melon Aphids", "Squash Bugs")),
new Melon("Crenshaw", 2000,
Arrays.asList("Pickleworms")),
new Melon("Crenshaw", 1000,
Arrays.asList("Cucumber Beetles", "Melon Aphids")),
new Melon("Gac", 4000,
Arrays.asList("Spider Mites", "Cucumber Beetles")),
new Melon("Gac", 1000,
Arrays.asList("Squash Bugs", "Squash Vine Borers")));

User problem: For each type of melon, I want a list of their pests.

So, let's group melons by type and collect their pests. Each melon has none, one, or multiple pests, and so we expect an output of the Map<String, List<String>> type. The first attempt will rely on mapping():

Map<String, List<List<String>>> pests = melonsGrown.stream()
.collect(groupingBy(Melon::getType,
mapping(m -> m.getPests(), toList())));

Obviously, this is not a good approach since the returned type is Map<String, List<List<String>>>.

Another naive approach that relies on mapping is as follows:

Map<String, List<List<String>>> pests = melonsGrown.stream()
.collect(groupingBy(Melon::getType,
mapping(m -> m.getPests().stream(), toList())));

Obviously, this is not a good approach either since the returned type is Map<String, List<Stream<String>>>.

It's time to introduce flatMapping(). By using flatMapping​(Function<? super T,​? extends Stream<? extends U>> mapper, Collector<? super U,​A,​R> downstream), we apply the flatMapping function to each element of the current collector and accumulate the output in the downstream collector:

Map<String, Set<String>> pestsFlatMapping = melonsGrown.stream()
.collect(groupingBy(Melon::getType,
flatMapping(m -> m.getPests().stream(), toSet())));

This time, the type looks fine and the output is as follows:

{
Crenshaw = [Cucumber Beetles, Pickleworms, Melon Aphids],
Gac = [Cucumber Beetles, Squash Bugs, Spider Mites,
Squash Vine Borers],
Honeydew = [Squash Bugs, Spider Mites, Melon Aphids]
}

User problem: I want two lists. One should contain the pests of melons lighter than 2,000 g, and the other should contain the pests of the rest of melons.

Partitioning melons heavier than 2,000 g and collecting the pests can be done as follows:

Map<Boolean, Set<String>> pestsFlatMapping = melonsGrown.stream()
.collect(partitioningBy(m -> m.getWeight() > 2000,
flatMapping(m -> m.getPests().stream(), toSet())));

The output is as follows:

{
false = [Cucumber Beetles, Squash Bugs, Pickleworms, Melon Aphids,
Squash Vine Borers],
true = [Squash Bugs, Cucumber Beetles, Spider Mites, Melon Aphids]
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset