我有这样的结构:
Map<Long, List<Foo>>
其中类Foo
公开方法:
Class Foo {
public List<Bar> getBars();
public void setBars(List<Bar> bars);
}
现在我想将此地图转换为List
参数化Foo
类,其中此列表中的每个项目都是Foo
实例,其中包含给定长值的聚合条形列表。例如,使用map:
{1: [Foo1, Foo2],
2: [Foo3]}
其中
Foo1.bars = [Bar1, Bar2]
Foo2.bars = [Bar3]
Foo3.bars = [Bar4, Bar5]
我希望得到结果:
[FooA, FooB]
,其中
FooA.bars = [Bar1, Bar2, Bar3]
FooB.bars = [Bar4, Bar5]
Java 8中最优雅的解决方案是什么?
如果需要,可以重复使用map中的一些Foo
实例,因为在此操作之后它们不再被使用。
答案 0 :(得分: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());
我们获取原始地图值的流(我们不关心密钥),它们是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());
如果您不想创建新的Foo
对象(例如,您希望保留其他属性),最好不要引入setBars
,而是addBars
方法(为现有的添加新的条形图),如下所示:
public class Foo {
...
public Foo addBars(List<Bar> bars) {
this.bars.addAll(bars);
return this;
}
}
现在您可以使用reduce
终端操作来组合foos:
List<Foo> result = map.values()
.stream()
.map(foos -> foos.stream()
.reduce((foo1, foo2) -> foo1.addBars(foo2.getBars())).get())
.collect(toList());