如何收集清单 到地图 >使用Java lambdas?

问题描述 投票:1回答:3

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

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

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

我有一个List<Foo>,我想转换成Map。我想关键是Bar和价值是List<Baz>

我可以创建一个Map,其中Bar是关键,值为List<Foo>

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

我不知道如何采取最后一步并将值List转换为List<Baz>。我没有看到的值是否有lambda转换?

java lambda java-stream collectors
3个回答
3
投票

我想你想要的

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

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


3
投票

你很接近,你需要提供一个“下游”收集器来进一步完善你的标准。在这种情况下,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::getBar是用于提取地图键的keyMapper函数。
  • v -> new ArrayList<>(singletonList(v))是用于提取地图值的valueMapper函数。
  • (l, r) -> {l.addAll(r); return l;}是合并函数,用于组合碰巧具有相同getBar值的两个列表。

2
投票

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

//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())));
© www.soinside.com 2019 - 2024. All rights reserved.