Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between groupingby and mapping in Collectors (Java)?

Tags:

Take a look at this piece of code.

// group by price, uses 'mapping' to convert List<Item> to Set<String>
    Map<BigDecimal, Set<String>> result =
            items.stream().collect(
                    Collectors.groupingBy(Item::getPrice,
                            Collectors.mapping(Item::getName, Collectors.toSet())
                    )
            );

Is groupingBy and Mapping interchangeable? What is their differences?

For the third parameter in collect(), would I get the same output type Map if I used Collectors.toList() instead of Collectors.toSet()? I heard that toList() is a more popular option.

like image 779
NoMoreErrors Avatar asked Nov 27 '16 06:11

NoMoreErrors


People also ask

What is groupingBy in Java?

The groupingBy() method of Collectors class in Java are used for grouping objects by some property and storing results in a Map instance.

What does collectors toList do in Java?

The toList() method of Collectors Class is a static (class) method. It returns a Collector Interface that gathers the input data onto a new list. This method never guarantees type, mutability, serializability, or thread-safety of the returned list but for more control toCollection(Supplier) method can be used.

How does Groupby work in Java 8?

In Java 8, you retrieve the stream from the list and use a Collector to group them in one line of code. It's as simple as passing the grouping condition to the collector and it is complete. By simply modifying the grouping condition, you can create multiple groups.

What is flat map?

flatMap , as it can be guessed by its name, is the combination of a map and a flat operation. That means that you first apply a function to your elements, and then flatten it. Stream. map only applies a function to the stream without flattening the stream.


2 Answers

No, the two are completely different.

Collectors.groupingBy takes a function which creates keys and returns a collector which returns a map from keys to collections of objects in the stream which have that same key.

Collectors.mapping, on the other hand, takes a function and another collector, and creates a new collector which first applies the function and then collects the mapped elements using the given collectors. Thus, the following are equivalent:

items.stream().map(f).collect(c);
items.stream().collect(Collectors.mapping(f, c));

Collectors.mapping is most useful in situations where you do not have a stream, but you need to pass a collector directly. An example of such a situation is when using Collectors.groupingBy.

items.stream().collect(Collectors.groupingBy(Item::getPrice, Collectors.toSet()))

yields a Map<BigDecimal,Set<Item>> (assuming getPrice() returns a BigDecimal). However,

items.stream().collect(Collectors.groupingBy(Item::getPrice,
    Collectors.mapping(Item::getName, Collectors.toSet())))

returns a Map<BigDecimal,Set<String>>. Before collecting the items, it first applies Item.getName to them.

like image 177
Hoopje Avatar answered Oct 04 '22 02:10

Hoopje


Is groupingBy and Mapping interchangeable?

No, they are completely different. groupingBy lets you create a Map where the key is the first argument passed to groupingBy and the value is a List of the element type of the Stream.

Collectors.groupingBy(Item::getPrice) would generate a Map<BigDecimal, List<Item>> (assuming Item::getPrice returns a BigDecimal. Passing the mapping Collector as an argument to Collectors.groupingBy() allows you to change the value of the output map (in your example, you change it to Set<String>).

For the third parameter in collect(), would I get the same output type Map if I used Collectors.toList() instead of Collectors.toSet()?

No, you would get a Map<BigDecimal, List<String>>.

like image 44
Eran Avatar answered Oct 04 '22 03:10

Eran