且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

迭代时在 Java8 中修改流中的对象

更新时间:2022-02-17 02:39:42

是的,您可以修改流中对象的状态,但大多数情况下您应该避免修改源代码 流.来自 非干扰 流包文档的一部分,我们可以阅读:

Yes, you can modify state of objects inside your stream, but most often you should avoid modifying state of source of stream. From non-interference section of stream package documentation we can read that:

对于大多数数据源来说,防止干扰意味着确保数据源在流管道的执行过程中完全不被修改.一个显着的例外是其源是并发集合的流,这些流是专门为处理并发修改而设计的.并发流源是那些 Spliterator 报告 CONCURRENT 特性的源.

For most data sources, preventing interference means ensuring that the data source is not modified at all during the execution of the stream pipeline. The notable exception to this are streams whose sources are concurrent collections, which are specifically designed to handle concurrent modification. Concurrent stream sources are those whose Spliterator reports the CONCURRENT characteristic.

所以没问题

  List<User> users = getUsers();
  users.stream().forEach(u -> u.setProperty(value));
//                       ^    ^^^^^^^^^^^^^
//                        \__/

但这在大多数情况下不是

but this in most cases is not

  users.stream().forEach(u -> users.remove(u));
//^^^^^                       ^^^^^^^^^^^^
//     \_____________________/

并且可能会抛出 ConcurrentModificationException 甚至其他像 NPE 这样的意外异常:

and may throw ConcurrentModificationException or even other unexpected exceptions like NPE:

List<Integer> list = IntStream.range(0, 10).boxed().collect(Collectors.toList());

list.stream()
    .filter(i -> i > 5)
    .forEach(i -> list.remove(i));  //throws NullPointerException