使用Java8流处理嵌套对象

3

我刚接触Java8。 我读过关于流的内容,但大多数例子都很基础。我想知道如何在嵌套对象中使用它。这是我的代码示例:

for (Gas gas : gases) {
  resourceNodes.add(gas.getRefinery().unit());
}

似乎我应该使用流一行代码完成这个问题,但我还无法完全找到解决方案。 能否提供使用流的答案?是否有一种方法可以在嵌套方法中使用::语法呢?
编辑: 为了澄清例子,getRefinery()返回类型为UnitInPool的对象,其方法unit()返回类型为Unit的对象。resourceNodes是Unit的ArrayList。
5个回答

3
你所指的::语法被称为方法引用
假设在 for 循环之前,resourceNodes 是未分配的(或为空,在这种情况下可以删除任何先前的分配),那么你首先需要 map每个 Gasunit() 返回的任何类型,然后 collect Stream 到一个 List 中:
resourceNodes = gases.stream()
                     .map(Gas::getRefinery)
                     .map(GasRefinery::unit)
                     .collect(Collectors.toList());

否则,如果您的目标只是要添加到resourceNodes,那么它会非常相似:
resourceNodes.addAll(gases.stream()
                          .map(Gas::getRefinery)
                          .map(GasRefinery::unit)
                          .collect(Collectors.toList()));

2
您需要提供更多的代码才能得到一个合理的答案,但我猜您可以通过以下方式获取一系列单位流(无论这些是什么,以及getRefinery返回的是什么):
gases.stream().map(Gas::getRefinery).map(???::unit)

然后你可以使用 collect(Collectors.toList()) 收集结果,并将收集的结果作为参数调用 resourceNodes.addAll


1

欢迎来到SO社区。我希望下面的内容能对您有所帮助。

List<Unit> resourceNodes = gases.stream() // open a stream
.map(gas -> gas.getRefinery()) // convert to UnitInPool
.filter(unitInPool -> Objects.nonNull(unitInPool)) // null check to avoid NPE
.map(unip -> unip.getUnit()) // convert to Unit
.collect(Collectors.toList()) // collect all the values in a List

1
resourceNodes = gases.stream().map(gas -> gas.getRefinery().unit()).collect(Collectors.toList());

1
如果您只需要方法引用,您可以使用以下内容:
gases.stream().map(Gas::getRefinery).map(UnitInPool::unit).map(resourceNodes::add);
or
gases.stream().map(Gas::getRefinery).map(UnitInPool::unit).forEach(resourceNodes::add);

否则,使用lambda可能更好,因为它更短、更易读,并且在你需要传递多个参数或需要执行多个复杂操作的方法时有效。
gases.stream().forEach(g -> resourceNodes.add(g.getRefinery().unit()));

这基本上与您之前的代码相同,但我建议使用for循环。

最后一个 map 只有在 resourceNodes::add 不是一个返回 void 的方法时才能正常工作。这是一个合理的假设,因为它 可能 是一个 java.util.List,但仍然存在不返回 void 的方法,将映射用作仅向外部集合添加元素的手段会让人感到不自然。 - pafau k.
@pafauk。你说得对,但其他答案也做出了同样的假设。此外,如果我在那里使用了forEach,那么它将复制Andy Turner最初发布的答案。不过我会进行更改。 - user

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接