【问题标题】:Java 8 - Stream with Objects and primitive wrappersJava 8 - 带有对象和原始包装器的流
【发布时间】:2018-11-01 09:50:41
【问题描述】:

我正在使用 java 8 流并尝试在 forEach 终端操作中修改对象内容。

我在这里面临的问题是我可以修改List<Employee> 对象的内容,但不能修改List<Integer> 的内容

sn-p代码如下:

public static void streamExample() {

    List<Employee> listEmp = Arrays.asList(new Employee());
    listEmp.stream().forEach(a -> a.setEmptName("John Doe"));
    listEmp.stream().forEach(System.out::println);
    List<Integer> listInteger = Arrays.asList(2, 4, 6, 8, 12,17, 1234);
    listInteger.stream().filter(v -> v % 2 == 0).forEach(a -> a=a+1);
    listInteger.stream().forEach(System.out::println);

}

我想知道更改没有反映在列表中,因为在执行 a=a+1 操作时取消装箱 Integer 对象但不确定。

【问题讨论】:

  • 这与元素类型无关。像forEach(a -&gt; a=a+1) 这样的操作永远不会有意义,因为您只是在修改参数 a。在 Java 中,修改参数变量对调用者没有影响。此原则也称为“按值传递”。

标签: java java-8 java-stream


【解决方案1】:

您使用的不是Stream 的最佳方法。将Stream 中的每一步都视为修改现有(或创建新)元素并将其返回给Stream。最后您收到final 结果,您可以使用final 方法之一来完成(并实际运行整个流工作)Stream

List<Integer> listInteger = Arrays.asList(2, 4, 6, 8, 12, 17, 1234);
listInteger.stream().filter(v -> v % 2 == 0).forEach(a -> a = a + 1);
listInteger.stream().forEach(System.out::println);

这里有初始数组。您想要执行以下操作:

  1. 过滤掉一些元素(这不是final步骤);
  2. 将过滤后的元素打印出来(这是final 步骤)。

为此,您不必创建Streams 两次。使用一个:

Stream.of(2, 4, 6, 8, 12, 17, 1234)    // create stream (there're many way to do it)
      .filter(v -> v % 2 == 0)         // filter out required elements
      .map(v -> v + 1)                 // transform elements using given rule
      .forEach(System.out::println);   // finalize stream with printing out each element separately

注意:Stream.of(...) 创建一个Stream,然后我们向流filtermap 添加两个步骤,然后finalizeSTART使用forEach 创建流。

【讨论】:

    【解决方案2】:

    您正在为局部变量 (a) 分配一个新值,因此这不会影响第二个 Stream (您的 List&lt;Integer&gt;) 的源。请注意,这不是您对 List&lt;Employee&gt; 所做的事情,您正在调用 setter 方法来改变 List 的元素。

    由于Integers 是不可变的,因此您不能改变输入List&lt;Integer&gt; 的元素。

    相反,您可以创建一个新的List

    List<Integer> newList = 
        listInteger.stream()
                   .map(v -> v % 2 == 0 ? v + 1 : v)
                   .collect(Collectors.toList());
    

    或者您可以通过List 的索引进行流式传输,并替换该List 的一些元素:

    IntStream.range(0,listInteger.size())
             .filter(i -> listInteger.get(i) % 2 == 0)
             .forEach(i -> listInteger.set(i, listInteger.get(i + 1));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-13
      • 1970-01-01
      • 2012-07-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多