Java 9: filtering and flatmapping - Two new collectors for your Streams
If you've worked with streams you've probably played around with the
In earlier posts I've looked at how you can accumulate elements of a stream using Collectors as well as looking at how you can create a custom collector.
In this post we're going to take a look at two new collectors that have been introduced in Java 9 — the
filtering method and the
Filtering elements using
Collectors.filtering method is quite simple. It allows us to filter out elements of a stream.
All you need to provide is the predicate you want to filter by and a succeeding collector that should be used to accumulate the filtered elements.
To see how this is done, say we got a stream of articles and we want to extract the ones that contain the tag "Java". We also want to get the final result as a Set.
getArticleStream() .collect(Collectors.filtering(article -> article.getTags().contains("Java"), Collectors.toSet()));
That's it! All we do is to provide our predicate followed by the
Collectors.toSet() method when creating the filtering collector.
Now when that's said, it doesn't really make sense to use the
Collectors.filtering in such a simple case. We could instead use Stream's own filter method.
Collectors.filtering really starts to shine when it becomes part of another Collector.
As an example, say we first want to group the articles by publisher year, then use the
filtering method to keep only Java articles.
getArticleStream().collect( Collectors.groupingBy( Article::getPublishYear, Collectors.filtering(article -> article.getTags().contains("Java"), Collectors.toSet())));
Another new method is the
It behaves as a normal flatmap, allowing you to flatten the stream.
Say we want to collect all tags that are found in our articles and return them as a Set.
getArticleStream() .collect(Collectors.flatMapping(article -> article.getTags().stream(), Collectors.toSet()));
There we go — our tags are extracted. The first thing we provide to
Collectors.flatMapping is the flattening function that defines how to extract the tags and make them into a stream. The second thing we provide is the succeeding Collector, which in our case is
toSet. The reason for making it into a Set is that it'll remove duplicate tags.
As with the filtering, this first example is a bit pointless since the Stream API offer a
flatMap function as well.
Now, if we use it as part of another Collector, we see the real benefit of the
Again, let's make the flatMapping collector a part of the
Say we want to figure out what tags have been used in the different publishing years.
getArticleStream().collect( Collectors.groupingBy( Article::getPublishYear, Collectors.flatMapping(article -> article.getTags().stream(), Collectors.toSet())));
As with the filtering method, we first group the articles by publishing year, then we use the flatMapping method to flatten the articles to tags.
As you can see, the Stream API continues to be strengthened, and I find it refreshing to see the commitment to make these functional aspects even better.