Java 8 streams collector groupingBy

Suppose we have a List of strings and want to group them by length.
We can use Collectors.groupingBy() for this task.

List persons = Arrays.asList("Bob", "Natali", "Alice", "Tom");
Map<Integer, List> map = persons.stream()
    .collect(Collectors.groupingBy(String::length));
System.out.println(map);

//output
{3=[Bob, Tom], 5=[Alice], 6=[Natali]}

If we want to collect into Set or have sorted order, we can use overloaded methods of groupingBy

List persons = Arrays.asList("Bob", "Natali", "Alice", "Tom");
Map<Integer, Set> map = persons.stream()
    .collect(Collectors.groupingBy(String::length, TreeMap::new, Collectors.toSet()));
System.out.println(map);

//output
{3=[Tom, Bob], 5=[Alice], 6=[Natali]}

Let’s see another examples of groupingBy. Say we have a store and want to categorize the products by their type

Map<String, List> productsByType = store.stream().collect(groupingBy(Product::getType));

//output
{Fruit=[Orange, Apple], Vegetable=[Potato, Carrot], Meat=[Beef, Pork]}

[addToAppearHere]

We can pass groupingBy other collectors as a second parameter. For example if we want to count the number of products per category, we could do

Map<String, Long> productsByType = store.stream()
        .collect(groupingBy(Product::getType, counting()));

//output
{Fruit=2, Vegetable=2, Meat=2}

Or if we cant to calculate the average price per category, we could do

Map<String, Double> productsPriceByType = store.stream()
    .collect(groupingBy(Product::getType, averagingInt(Product::getPrice)));

//output
{Fruit=5.0, Vegetable=3.0, Meat=9.0}