Java 8-按集合映射的多个组

Ice*_*nte 5 java-8 java-stream

我正在尝试使用Java流对一个对象的两个属性进行分组.这很容易,正如一些答案所记录的那样:

products.stream().collect(
        Collectors.groupingBy(Product::getUpc, 
        Collectors.groupingBy(Product::getChannelIdentifier)));
Run Code Online (Sandbox Code Playgroud)

例如,上面的代码片段将在表单中生成地图地图

Map<String, Map<String, List<Product>>>
Run Code Online (Sandbox Code Playgroud)

如果地图具有UPC代码的键,则其值是具有引用产品列表的通道标识符的键的映射.

这很酷,但是如果我不需要嵌套值作为地图呢?也就是说,我想通过ChannelIdentifier组织嵌套集合,但我只关心地图的.values(),而不是地图本身.有没有办法得到符合以下条件的结果?

Map<String, List<List<Product>>
Run Code Online (Sandbox Code Playgroud)

列表或集合......没关系.谢谢!

Hol*_*ger 11

分组操作不可避免地需要维护,Map因为它必须跟踪分组的关键值.但您可以values()直接使用该视图:

Map<String, Collection<List<Product>>> m=products.stream().collect(
    Collectors.groupingBy(Product::getUpc, Collectors.collectingAndThen(
        Collectors.groupingBy(Product::getChannelIdentifier), Map::values)));
Run Code Online (Sandbox Code Playgroud)

如果生成的地图的生命周期更长,并且您希望减少所需的存储空间,或者如果需要List,则可以在该步骤中将视图复制到列表中:

Map<String, List<List<Product>>> map=products.stream().collect(
    Collectors.groupingBy(Product::getUpc, Collectors.collectingAndThen(
        Collectors.groupingBy(Product::getChannelIdentifier),
        m -> new ArrayList<>(m.values()) )));
Run Code Online (Sandbox Code Playgroud)

  • 我通过回答SO问题和阅读其他[相关答案]来记住[API](http://docs.oracle.com/javase/8/docs/api/?java/util/stream/Collectors.html)(http: //stackoverflow.com/search?q=%5Bjava-8%5D+collectors+is%3Aanswer).训练是一个很好的副作用. (4认同)