Java Reference
In-Depth Information
The reduction operation on the substreams is then performed by the reducing collector, but the
collectingAndThen collector containing it applies the Optional::get transformation function to its
result.
The three transformed values, being the highest-calorie Dish es for a given type (resulting from the
execution of this process on each of the three substreams), will be the values associated with the
respective classification keys, the types of Dish es, in the Map returned by the groupingBy collector.
Other examples of collectors used in conjunction with groupingBy
More generally, the collector passed as second argument to the groupingBy factory method will
be used to perform a further reduction operation on all the elements in the stream classified into
the same group. For example, you could also reuse the collector created to sum the calories of all
the dishes in the menu to obtain a similar result, but this time for each group of Dishes:
Map<Dish.Type, Integer> totalCaloriesByType =
menu.stream().collect(groupingBy(Dish::getType,
summingInt(Dish::getCalories)));
Yet another collector, commonly used in conjunction with groupingBy, is one generated by the
mapping method. This method takes two arguments: a function transforming the elements in a
stream and a further collector accumulating the objects resulting from this transformation. Its
purpose is to adapt a collector accepting elements of a given type to one working on objects of a
different type, by applying a mapping function to each input element before accumulating them.
To see a practical example of using this collector, suppose you want to know which CaloricLevels
are available in the menu for each type of Dish. You could achieve this result combining a
groupingBy and a mapping collector as follows:
Map<Dish.Type, Set<CaloricLevel>> caloricLevelsByType =
menu.stream().collect(
groupingBy(Dish::getType, mapping(
dish -> { if (dish.getCalories() <= 400) return CaloricLevel.DIET;
else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
else return CaloricLevel.FAT; },
toSet() )));
Here the transformation function passed to the mapping method maps a Dish into its
CaloricLevel, as you've seen before. The resulting stream of CaloricLevels is then passed to a
toSet collector, analogous to the toList one, but accumulating the elements of a stream into a Set
instead of into a List, to keep only the distinct values. As in earlier examples, this mapping
 
Search WWH ::




Custom Search