package lambdasinaction.chap6; import java.util.*; import static java.util.stream.Collectors.*; import static lambdasinaction.chap6.Dish.dishTags; import static lambdasinaction.chap6.Dish.menu; public class Grouping { enum CaloricLevel { DIET, NORMAL, FAT }; public static void main(String ... args) { System.out.println("Dishes grouped by type: " + groupDishesByType()); System.out.println("Dish names grouped by type: " + groupDishNamesByType()); System.out.println("Dish tags grouped by type: " + groupDishTagsByType()); System.out.println("Caloric dishes grouped by type: " + groupCaloricDishesByType()); System.out.println("Dishes grouped by caloric level: " + groupDishesByCaloricLevel()); System.out.println("Dishes grouped by type and caloric level: " + groupDishedByTypeAndCaloricLevel()); System.out.println("Count dishes in groups: " + countDishesInGroups()); System.out.println("Most caloric dishes by type: " + mostCaloricDishesByType()); System.out.println("Most caloric dishes by type: " + mostCaloricDishesByTypeWithoutOprionals()); System.out.println("Sum calories by type: " + sumCaloriesByType()); System.out.println("Caloric levels by type: " + caloricLevelsByType()); } private static Map<Dish.Type, List<Dish>> groupDishesByType() { return menu.stream().collect(groupingBy(Dish::getType)); } private static Map<Dish.Type, List<String>> groupDishNamesByType() { return menu.stream().collect(groupingBy(Dish::getType, mapping(Dish::getName, toList()))); } private static Map<Dish.Type, Set<String>> groupDishTagsByType() { return menu.stream().collect(groupingBy(Dish::getType, flatMapping(dish -> dishTags.get( dish.getName() ).stream(), toSet()))); } private static Map<Dish.Type, List<Dish>> groupCaloricDishesByType() { // return menu.stream().filter(dish -> dish.getCalories() > 500).collect(groupingBy(Dish::getType)); return menu.stream().collect(groupingBy(Dish::getType, filtering(dish -> dish.getCalories() > 500, toList()))); } private static Map<CaloricLevel, List<Dish>> groupDishesByCaloricLevel() { return menu.stream().collect( groupingBy(dish -> { if (dish.getCalories() <= 400) return CaloricLevel.DIET; else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL; else return CaloricLevel.FAT; } )); } private static Map<Dish.Type, Map<CaloricLevel, List<Dish>>> groupDishedByTypeAndCaloricLevel() { return menu.stream().collect( groupingBy(Dish::getType, groupingBy((Dish dish) -> { if (dish.getCalories() <= 400) return CaloricLevel.DIET; else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL; else return CaloricLevel.FAT; } ) ) ); } private static Map<Dish.Type, Long> countDishesInGroups() { return menu.stream().collect(groupingBy(Dish::getType, counting())); } private static Map<Dish.Type, Optional<Dish>> mostCaloricDishesByType() { return menu.stream().collect( groupingBy(Dish::getType, reducing((Dish d1, Dish d2) -> d1.getCalories() > d2.getCalories() ? d1 : d2))); } private static Map<Dish.Type, Dish> mostCaloricDishesByTypeWithoutOprionals() { return menu.stream().collect( groupingBy(Dish::getType, collectingAndThen( reducing((d1, d2) -> d1.getCalories() > d2.getCalories() ? d1 : d2), Optional::get))); } private static Map<Dish.Type, Integer> sumCaloriesByType() { return menu.stream().collect(groupingBy(Dish::getType, summingInt(Dish::getCalories))); } private static Map<Dish.Type, Set<CaloricLevel>> caloricLevelsByType() { return 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() ))); } }