gpt4 book ai didi

java - 列表的奇怪行为

转载 作者:搜寻专家 更新时间:2023-10-30 19:44:47 25 4
gpt4 key购买 nike

我定义了 0-9(Integer) 的列表如下:

List<Integer> list = 
IntStream.range(0, 10)
.boxed()
.collect(Collectors.toCollection(ArrayList::new));

当我尝试使用以下代码删除元素时:

list.stream()
.peek(list::remove)
.forEach(System.out::println);

它应该抛出 ConcurrentModificationException 但有趣的是它适用于某些元素并给出以下输出(最后抛出异常并删除了一些元素):

0
2
4
6
8
null
null
null
null
null
Exception in thread "main" java.util.ConcurrentModificationException

但是如果我像下面这样添加了sorted():

list.stream()
.sorted()
.peek(list::remove)
.forEach(System.out::println);

这工作得很好并删除了所有元素,我很困惑为什么 stream 会这样。

最佳答案

您看过源代码这些类是如何实现的吗?

sorted() 方法将生成一个副本 用于排序的列表。

因此它的行为不同:您正在迭代排序的 copy 然后,但仅从 first 列表中删除。

不鼓励 peek()

不鼓励使用方法peek;来自 JavaDoc:

This method exists mainly to support debugging

可以出于开发目的将 System::println 放在那里或类似的地方,但这不是您应该在最终程序中使用的功能。

永远不要尝试修改当前流

阅读流包API规范:

https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#NonInterference

For most data sources, preventing interference means ensuring that the data source is not modified at all during the execution of the stream pipeline.

因此,换句话说:您不能从当前正在流式传输的列表中删除,不能保证它会起作用。

发生了什么

您的初始列表是

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]        pos = 0

您打印 0 并将其删除,然后前进到下一个位置。那么新的数组就是

[1, 2, 3, 4, 5, 6, 7, 8, 9, null]     pos = 1

下一个位置,值现在是2,所以打印并删除2:

[1, 3, 4, 5, 6, 7, 8, 9, null, null]  pos = 2

等等。问题是,由于您的并发删除,列表的其余部分继续向前移动。

ConcurrentModificationException 在流的末尾 被抛出。这似乎是仅针对 forEachRemaining 的性能决策(仅检查一次并发修改,而不是每次迭代都检查),因此此流不是快速失败

关于java - 列表的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31963579/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com