我是Java 8的初学者。


  非干扰对于保持一致的Java流行为很重要。
  假设我们正在处理大量数据,并且在此过程中
  源已更改。结果将是不可预测的。这是
  无论并行或并行流的处理模式如何
  顺序的。
  
  可以修改源,直到语句终端操作为
  调用。除此之外,在流之前不要修改源
  执行完成。因此在流中处理并发修改
  源对于确保一致的流性能至关重要。


以上引用来自here

有人可以做一些简单的例子来说明为什么改变流源会带来这么大的问题吗?

最佳答案

好吧,oracle example在这里是不言自明的。第一个是:

List<String> l = new ArrayList<>(Arrays.asList("one", "two"));
 Stream<String> sl = l.stream();
 l.add("three");
 String s = l.collect(Collectors.joining(" "));


如果在调用终端操作(l)之前通过添加一个或多个元素来更改Collectors.joining,则可以;但请注意,Stream由三个元素组成,而不是两个;在通过l.stream()创建流时。

另一方面,这样做:

  List<String> list = new ArrayList<>();
  list.add("test");
  list.forEach(x -> list.add(x));


由于您无法更改来源,因此会抛出ConcurrentModificationException

现在,假设您有一个可以处理并发添加的基础源:

ConcurrentHashMap<String, Integer> cMap = new ConcurrentHashMap<>();
cMap.put("one", 1);
cMap.forEach((key, value) -> cMap.put(key + key, value + value));
System.out.println(cMap);


输出应该在这里什么?当我运行它是:

 {oneoneoneoneoneoneoneone=8, one=1, oneone=2, oneoneoneone=4}


将密钥更改为zxcMap.put("zx", 1)),现在的结果是:

{zxzx=2, zx=1}


结果不一致。

09-30 22:59