|
Another frequent operation on a data set you may do in your day-to-day job is grouping items in a set, based on the values of one or more of their properties. As you saw in the earlier transactions currency–grouping example, this operation can be cumbersome, verbose, and error prone when implemented with an imperative style, but it can be easily translated in a single, very readable statement by rewriting it in a more functional style as encouraged by Java 8. To give a second example of how this feature works, suppose you want to classify the dishes in the menu according to their respective type, putting the ones containing meat in a group, the ones with fish in another group, and all others in a third group. You can easily
perform this task using a Collector created with the Collectors.groupingBy factory method as follows:
Map<Dish.Type, List<Dish>> dishesByType = menu.stream().collect(groupingBy(Dish::getType));
This will result in the following Map:
{FISH=[prawns, salmon], OTHER=[french fries, rice, season fruit, pizza],
MEAT=[pork, beef, chicken]}
Here, you pass to the groupingBy method a Function (expressed in the form of a method reference) extracting from each Dish in the Stream the corresponding Dish.Type. We call this Function a classification function because it’s used to classify the elements of the Stream in different groups. More in general, you have to create a Collector that passes to the groupingBy method a classification Function that transforms each item in the Stream into the value under which the item itself will be classified. The result of this grouping operation, shown in figure 5.4, is a Map, having as key the value returned by the classification Function and as a corresponding value a List of all the items in the Stream for which the application of the classification Function on that item returns that value. In the menu-classification example a key is the type of dish, and its value is a List containing all the dishes of that type. |
|