User problem: I want to take all the melons that are heavier than 2,000 g and group them by their type. For each type, add them to the proper container (there is a container for each type – just check the container's labels).
By using filtering(Predicate<? super T> predicate, Collector<? super T,A,R> downstream), we apply a predicate to each element of the current collector and accumulate the output in the downstream collector.
So, to group the melons that are heavier than 2,000 g by type, we can write the following stream pipeline:
Map<String, Set<Melon>> melonsFiltering = melons.stream()
.collect(groupingBy(Melon::getType,
filtering(m -> m.getWeight() > 2000, toSet())));
The output will be as follows (each Set<Melon> is a container):
{Crenshaw=[], Gac=[Gac(3000g)], Hemi=[Hemi(2600g)]}
Notice that there is no Crenshaw heavier than 2,000 g, so filtering() has mapped this type to an empty set (container). Now, let's rewrite this via filter():
Map<String, Set<Melon>> melonsFiltering = melons.stream()
.filter(m -> m.getWeight() > 2000)
.collect(groupingBy(Melon::getType, toSet()));
Because filter() doesn't perform mappings for elements that fail its predicate, the output will look as follows:
{Gac=[Gac(3000g)], Hemi=[Hemi(2600g)]}
User problem: This time, I am interested only in the melons of the Hemi type. There are two containers: one for Hemi melons lighter than (or equal to) 2,000 g and one for Hemi melons heavier than 2,000 g.
Filtering can be used with partitioningBy() as well. To partition melons heavier than 2,000 g and filter them by a certain type (in this case, Hemi), we have the following:
Map<Boolean, Set<Melon>> melonsFiltering = melons.stream()
.collect(partitioningBy(m -> m.getWeight() > 2000,
filtering(m -> m.getType().equals("Hemi"), toSet())));
The output is as follows:
{false=[Hemi(1600g), Hemi(2000g)], true=[Hemi(2600g)]}
Applying filter() will lead to the same result:
Map<Boolean, Set<Melon>> melonsFiltering = melons.stream()
.filter(m -> m.getType().equals("Hemi"))
.collect(partitioningBy(m -> m.getWeight() > 2000, toSet()));
The output is as follows:
{false=[Hemi(1600g), Hemi(2000g)], true=[Hemi(2600g)]}