【问题标题】:How to collect a List<Foo> to a Map<Bar, List<Baz>> using Java lambdas?如何使用 Java lambda 将 List<Foo> 收集到 Map<Bar, List<Baz>>?
【发布时间】:2018-12-11 21:50:19
【问题描述】:

我有一个对象Foo 引用了BarBaz 对象:

public class Foo {
    private Bar bar;
    private Baz baz;

    public Foo(Bar bar, Baz baz) {
       this.bar = bar;
       this.baz = baz;
    }
}

我有一个List&lt;Foo&gt;,我想将其转换为Map。我希望键是Bar,值是List&lt;Baz&gt;

我可以创建一个Map,其中Bar 是键,值是List&lt;Foo&gt;

Map<Bar, List<Foo>> mapBarToFoos = foos.stream().collect(Collectors.groupingBy(Foo::getBar));

我不知道如何采取最后一步并将值 List 转换为 List&lt;Baz&gt;。我没有看到的值是否存在 lambda 转换?

【问题讨论】:

    标签: java lambda java-stream collectors


    【解决方案1】:

    我想你想要

    list.stream().collect(groupingBy(Foo::getBar, 
        mapping(Foo::getBaz, toList())));
    

    getBaz 是“下游收集器”,它转换分组的Foos,然后是另一个创建列表的收集器。

    【讨论】:

    • 正确的想法,您只需将下游收集器传递给mapping
    • 终于试了一下——效果很好。其他人的建议也同样精明,但你是第一个。谢谢!
    【解决方案2】:

    您已经接近了,您需要提供一个“下游”收集器来进一步完善您的标准。在这种情况下,groupingBy 方法和 mapping 下游收集器是惯用的方法,即

    list.stream().collect(groupingBy(Foo::getBar, mapping(Foo::getBaz, toList())));
    

    这实质上是通过将mapping 下游收集器应用于分类 (Foo::getBar) 函数的结果来实现的。 基本上我们所做的是将每个Foo 对象映射到Baz 并将其放入列表中。


    只是想在这里展示另一个变体,虽然不如groupingBy 方法可读:

    foos.stream()
        .collect(toMap(Foo::getBar, v -> new ArrayList<>(singletonList(v.getBaz())),
                (l, r) -> {l.addAll(r); return l;}));
    
    • Foo::getBarkeyMapper 函数,用于提取映射键。
    • v -&gt; new ArrayList&lt;&gt;(singletonList(v))valueMapper 提取地图值的函数。
    • (l, r) -&gt; {l.addAll(r); return l;} 是用于合并的函数 合并两个恰好具有相同 getBar 值的列表。

    【讨论】:

      【解决方案3】:

      要将经典的grouping 更改为Map&lt;Bar, List&lt;Foo&gt;&gt;,您需要使用允许更改地图值的方法:

      //Use the import to reduce the Collectors. redundancy
      //import static java.util.stream.Collectors.*;
      
      Map<Bar, List<Baz>> mapBarToFoos = 
               foos.stream().collect(groupingBy(Foo::getBar, mapping(Foo::getBaz, toList())));
      
      //without you'll get
      Map<Bar, List<Baz>> mapBarToFoos = 
               foos.stream().collect(Collectors.groupingBy(Foo::getBar, Collectors.mapping(Foo::getBaz, Collectors.toList())));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多