问题
I'm trying to do a groupingBy on two attributes of an object with Java streams. That's easy enough as has been documented by some answers:
products.stream().collect(
Collectors.groupingBy(Product::getUpc,
Collectors.groupingBy(Product::getChannelIdentifier)));
for example, the above snippet will produce a Map of Maps in the form
Map<String, Map<String, List<Product>>>
Where a map has keys of UPC codes and its values are maps that have keys of Channel Identifiers which reference a list of products.
That's cool, but what if I don't need the nested value to be a map? That is to say, I want to organize the nested collection by ChannelIdentifier, but I only care about the .values() of the map, not the map itself. Is there a way to get a result that matches the following?
Map<String, List<List<Product>>
Lists or collections... it doesn't matter. Thanks!
回答1:
The grouping operation unavoidably needs to maintain a Map
as it has to track the key values for the grouping. But you can use the values()
view directly:
Map<String, Collection<List<Product>>> m=products.stream().collect(
Collectors.groupingBy(Product::getUpc, Collectors.collectingAndThen(
Collectors.groupingBy(Product::getChannelIdentifier), Map::values)));
If the resulting map will have a longer lifetime and you want to reduce the required storage space, or if you need a List
, you may copy the view into a list during that step:
Map<String, List<List<Product>>> map=products.stream().collect(
Collectors.groupingBy(Product::getUpc, Collectors.collectingAndThen(
Collectors.groupingBy(Product::getChannelIdentifier),
m -> new ArrayList<>(m.values()) )));
来源:https://stackoverflow.com/questions/33425107/java-8-multiple-group-by-into-map-of-collection