我们说我有一个Foo对象列表。 Foo上有一个属性,我必须使用它从数据源中获取Bar对象。然后我必须将每个bar对象映射回我为Bar获取的原始Foo对象。
public class Foo {
int barId;
}
public class Bar {
int barId;
}
Set<Foo> inputFoo;
Map<Bar, Foo> barToFoo;
public Bar getBar(int barId);
我的尝试如下:
List<Bar> allBarsInFoo = inputFoos.stream()
.map(Foo::barId)
.forEach(b -> getBar(b))
我不知道如何在没有做更多沉重和不必要的操作之后获取Bar to Foo的地图。
编辑:为了使我的问题更加通用,有没有办法保持对原始对象的引用,在原始对象列表中的流中执行一堆过滤器/映射操作,然后映射结果过滤/映射作为键,将原始对象作为结果映射的值?
答案 0 :(得分:2)
我认为Collectors.toMap()
是您正在寻找的:
Map<Bar, Foo> barToFoo = inputFoo.stream()
.collect(Collectors.toMap(f -> getBar(f.barId), Function.identity()));
答案 1 :(得分:1)
您似乎想要一张反向地图或一张地图,其中每个值都指向它的关键字。这有一些问题,第一个是数学地图(有时表示为函数)不能保证是一个数学身份(这是一种说明函数具有反函数的奇特方式)。
因此,获取A的键并提供B的值的地图看起来像
f(A) -> B
但是有很多地图,人们不能写它反向并且反转仍然是函数
f'(B) -> A (only exists for some functions)
例如
f(x) = x*x
让我们使用输入
f(0) = 0
f(1) = 1
f(2) = 4
以及
f(-1) = 1
f(-2) = 4
所以反函数必须要做
f'(0) = 0 (the zero's are swapped compared to the above example)
f'(1) = 1 or -1 (sorry, but that's not valid output for a function)
f'(4) = 2 or -2 (ditto)
这意味着地图通常不可逆。但是,如果您将键入放宽到几乎相反的位置,则可以生成广义逆:
Map<Foo, Bar> x
(back maps to)
Map<Bar, Collection<Foo>> y;
流式传输API是一件好事,但在这种情况下,它可能无法为您提供最简单的解决方案。
Map <Bar, Set<Foo>> backmap = new HashMap<>();
for (Map.Entry<Foo, Bar> entry : barToFoo.entrySet()) {
if (backmap.contains(entry.getValue()) {
backmap.get(entry.getValue()).add(entry.getKey());
} else {
backmap.put(entry.getValue(), new HashSet<Foo>(entry.getKey));
}
}