将Map <Long,List <Foo >>转换为List <Foo>

sla*_*omy 3 java algorithm java-8

我有这样的结构:

Map<Long, List<Foo>>
Run Code Online (Sandbox Code Playgroud)

class Foo暴露方法的地方:

Class Foo {
     public List<Bar> getBars();
     public void setBars(List<Bar> bars);
}
Run Code Online (Sandbox Code Playgroud)

现在我想将此映射转换为List使用Foo类进行参数化,其中此列表中的每个项都是Foo具有给定长值的聚合条列表的实例.例如,使用地图:

{1: [Foo1, Foo2],
 2: [Foo3]}
Run Code Online (Sandbox Code Playgroud)

哪里

Foo1.bars = [Bar1, Bar2]
Foo2.bars = [Bar3]
Foo3.bars = [Bar4, Bar5]
Run Code Online (Sandbox Code Playgroud)

我想得到的结果是:

[FooA, FooB]
Run Code Online (Sandbox Code Playgroud)

哪里

FooA.bars = [Bar1, Bar2, Bar3]
FooB.bars = [Bar4, Bar5]
Run Code Online (Sandbox Code Playgroud)

在Java 8中,最优雅的解决方案是什么?Foo如果需要,可以重复使用map中的某些实例,因为在此操作之后它们不再使用.

Tag*_*eev 5

假设你有一个Foo(List<Bar> bars)构造函数,它很容易:

import static java.util.stream.Collectors.*;

List<Foo> result = map.values()
    .stream()
    .map(
        foos -> new Foo(foos.stream()
                    .flatMap(foo -> foo.getBars().stream())
                    .collect(toList())))
    .collect(toList());
Run Code Online (Sandbox Code Playgroud)

我们采用原始地图值的流(我们不关心密钥),它们是列表Foo.我们将每个这样的列表展平以获取流Bar,将它们收集到列表中并将此列表传递给Foo(List<Bar>)构造函数,以便我们获得新Foo对象.最后我们将它们收集到List.

如果你没有Foo(List<Bar>),只有setter,你应该先创建一个空Foo,然后使用setter并返回创建的Foo:

List<Foo> result = map.values()
    .stream()
    .map(foos -> {
            Foo f = new Foo();
            f.setBars(foos.stream().flatMap(
                foo -> foo.getBars().stream()).collect(toList()));
            return f;
        })
    .collect(toList());
Run Code Online (Sandbox Code Playgroud)

如果你不想创建新Foo对象(例如,你想要保留其他属性),最好不要引入setBars,而是引入addBars方法(为现有的方法添加新的条形图),如下所示:

public class Foo {
    ...
    public Foo addBars(List<Bar> bars) {
        this.bars.addAll(bars);
        return this;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以使用reduce终端操作来组合foos:

List<Foo> result = map.values()
        .stream()
        .map(foos -> foos.stream()
             .reduce((foo1, foo2) -> foo1.addBars(foo2.getBars())).get())
        .collect(toList());
Run Code Online (Sandbox Code Playgroud)