Java流(forEach)从一个列表中获取属性并应用于另一个列表



我有一个简单的类:

public class Thing {
Long id;
String color;
String size;
}

我有两个List<Thing>对象,看起来像这样:

List<Thing> colors = [{2, red}, {3, blue}];
List<Thing> sizes = [{2, small}, {3, large}];

使用Java streams/forEach;流";一个进入另一个到达:

List<Thing> things = [{2, red, small}, {3, blue, large}]

这个概念(将两个长度相等的流混合在一起,这样你就可以从每个流中获得一个元素,它们都传递给一个函数,然后将组合映射到其他函数(被称为zipping

Java的流类不包括对该操作的任何支持。除非你能以某种方式保证两者的"id"概念以完全相同的顺序发生(即,如果你的sizes[{3, large}, {2, small}],我们不再谈论zip操作(,否则你在这里所拥有的也不是可以有意义地压缩在一起的东西。

在前一种情况下(这不是关于"组合red和small,因为它们都有id2,而是关于将colors中第一个元素的2redsizes中第一个元件的small组合起来,而不考虑id(,您可以从另一个库中找到zip支持,也可以破解它:

if (colors.size() != sizes.size()) throw new IllegalStateException();
IntStream.range(0, colors.size())
.mapToObj(i -> new Thing(colors.get(i).getId(), colors.get(i).getColor(), sizes.get(i).getSize()))
.collect(Collectors.toList());

它看起来很难看,如果列表不是随机访问的话,它的性能糟糕得离谱,在我所能理解的几乎所有方面,与只制作2个迭代器并并行迭代它们相比,这真是令人失望:

if (colors.size() != sizes.size()) throw new IllegalStateException();
var itColors = colors.iterator();
var itSizes = sizes.iterator();
var out = new ArrayList<Thing>();
while (itColors.hasNext()) {
Thing a = itColors.next();
out.add(new Thing(a.getId(), a.getColor(), itSizes.next().getSize());
}

如果你想这样做,你一开始就绝对不应该使用流。

不,是关于身份证的

在这种情况下,流似乎很像你用一把非常闪亮的花式锤子把果酱涂在三明治上:流只是。。。在这里毫无意义。完全你可以尝试一些古怪的东西,好吧,让这一切发生,并使用流,但这将是一个古怪的代码:它看起来很奇怪,不地道,包括大量的警告(假设,如果不是真的,意味着代码没有做好工作,或者在某些情况下具有极其糟糕的性能特征(,通常情况下会更糟。

解决方案是地图:

var out = new HashMap<Long, Thing>();
for (Thing c : colors) out.put(c.getId(), c);
for (Thing s : sizes) out.merge(c.getId(), s,
(a, b) -> new Thing(a.getId(), a.getColor(), b.getSize());

看看它有多干净,它还处理输入之间的任何不匹配(大小包含id 87,但颜色不包含(。

我会创建一个从idThingMap<Long, Thing>,并首先放置有颜色的东西,然后我会为地图上的东西设置大小,前提是它们存在:

Map<Long, Thing> map = new LinkedHashMap<>();
colors.forEach(t -> map.put(
t.getId(), 
new Thing(t.getId(), t.getColor(), null))); // assumes constructor from attributes
sizes.forEach(t -> {
Thing thing = map.get(t.getId());
if (thing != null) thing.setSize(t.getSize());
});

这使原始Thing保持不变。

最新更新