问题
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.
回答1:
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>>
.
回答2:
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.
来源:https://stackoverflow.com/questions/40826431/whats-the-difference-between-groupingby-and-mapping-in-collectors-java