Java 8-带对象和原始包装的流

时间:2018-11-01 09:50:41

标签: java java-8 java-stream

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

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

代码段如下:

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对象的装箱操作,但不确定该更改是否不会反映在列表中。

2 个答案:

答案 0 :(得分:3)

您正在将新值分配给局部变量(a),因此这对第二个Stream(您的List<Integer>)的源没有影响。请注意,这与您在List<Employee>上执行的操作不同,在这里您要调用setter方法来对List的元素进行变异。

由于Integer是不可变的,因此您无法更改输入List<Integer>的元素。

相反,您可以创建一个新的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));

答案 1 :(得分:3)

您使用的不是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添加两个步骤,然后向{{1} }或 START 使用finalize创建的流。