使用流API修改传递的参数

时间:2018-07-26 19:24:34

标签: java java-stream

我对范围,流和重新分配有疑问。

我想知道是否有一种方法可以使用流式api而不重新分配列表。重新分配参数的问题是它破坏了范围,因此测试看不到新值。

我知道还有其他方法(迭代器,向后迭代等)可以解决问题。这个问题只是出于好奇。

测试代码:

@Test
void testAllNegativesByIterator() {
    List<Integer> values = new ArrayList<>(Arrays.asList(-1, -2, -3, -4, -5, -6, -7, -8, -9));
    p.removeNegativesByIterator(values);
    checkNonNegativeSize(0, values);
}

正在测试的代码:

public void removeNegativesByStream(List<Integer> values) {
    values = values.stream().filter(v -> v > 0).collect(Collectors.toList());
}

编辑:

我也知道我可以返回一个值。就像我在问题中所说的那样,我特别想问一种出于好奇而使用流的方法。

3 个答案:

答案 0 :(得分:6)

首先,在方法调用为java doesn't support pass by reference之后,流查询的结果重新分配回values不会持续。

关于这个问题:

您可以使用Collection::removeIf方法来删除源集合中满足给定谓词的所有元素:

values.removeIf(v -> v <= 0);

否则,您别无选择,只能创建一个新列表,因为流不会修改源。

答案 1 :(得分:0)

您希望Stream API对基础集合进行突变,这与Streams的功能本质背道而驰。纯函数没有副作用。您可以在方法中更改列表,从而避免重新分配,但不使用流。

  public void removeNegativesByStream(List<Integer> values) {
    List<Integer> original = new ArrayList<>(values);
    values.clear();
    values.addAll(original.stream().filter(v -> v > 0).collect(Collectors.toList()));
  }

答案 2 :(得分:0)

首先,除了是否使用Streams API之外,您在做什么都是错误的。

在Java中,您不能为方法参数重新分配新引用,因为Java不支持按引用传递。

您的未引入流管道的代码段完全等同于以下示例:

public void removeNegativesByStream(List<Integer> values) {
    values = null;
}

values重新分配给null仅在方法范围内可见,它永远不会泄漏出去,并且无论是否使用Streams API都适用。

当您面对使用新的Streams API对源集合进行变异时,您根本无法这样做,因为流管道只是对数据源的一次一次运行传递(在您的示例values)。

您可以做的是将管道的结果收集到仅包含正数的新List<Integer>中,但这不会影响您的values变量和下一个测试(checkNonNegativeSize(0, values);)只会失败。

现在,您剩下其他解决方案了,其中包括通过列表的迭代器手动删除负数,或使用声明性包装器Collection#removeIf描述要从集合中删除哪些元素。

我想到的最有效,最易读的解决方案是Aomine's solution