列出使用并行流设置空值



>我有以下代码

final String arr[] = {"A", "B", "C", "D"};
final List<String> list1 = new ArrayList<>();
final List<String> list2 = Arrays.asList(arr).parallelStream()
.peek(s -> list1.add(s + s))
.map(s -> s + s)
.collect(Collectors.toList());
System.out.println(list1);
System.out.println(list2);

我得到以下结果:

[null, AA, DD, null]
[AA, BB, CC, DD]

为什么某些元素在 list1 中显示null? 我知道我应该将SynchronizedListparallelStream一起使用,但null值让我感到惊讶。 一旦您向列表中添加了某些内容,就应该设置该插槽,并且下一次执行应该为其添加另一个值。

ArrayList不是一个线程安全的集合,您尝试使用parallelStream从众多线程更新它,您看到的是resizingArrayList的内部数组的结果 - 该操作也不是线程安全的,您首先增加数组,然后将元素移动到其中:可能是元素尚未移动,您尝试访问它。

为了使它更明确,当调整大小时,会创建一个大小增加的新数组 - 只有在复制发生后,这个新数组才会充满null

会发生什么真的是不可预测的,只是不要依赖这些。

编辑

我不能将其作为评论发布,但这里有一些代码证明可以看到null

List<Integer> result = IntStream.iterate(0, i -> i + 1)
.takeWhile(i -> {
String arr[] = { "A", "B", "C", "D", "E", "F", "G", "H", "R", "T" };
List<String> list = new ArrayList<>();
Arrays.stream(arr)
.parallel()
.peek(list::add)
.forEach(x -> {
});
if (list.contains(null)) {
System.out.println("It took " + i + " steps to see a null");
return false;
}
return true;
})
.boxed()
.collect(Collectors.toList());

最新更新