@Eran已经explained如何解决这个问题更好。我将解释为什么ConcurrentModificationException
发生。由于您正在修改流源,因此发生ConcurrentModificationException
。您的Map
很可能是HashMap
或TreeMap
或其他非并发地图。我们假设这是一个HashMap
。每个流都支持Spliterator
。如果spliterator没有IMMUTABLE
和CONCURRENT
特征,那么,作为文档说:
结合Spliterator后应,尽最大努力的基础上,如果检测到结构的干扰扔ConcurrentModificationException
。这样做的Spliterators被称为失效快速。
所以HashMap.keySet().spliterator()
不IMMUTABLE
(因为这Set
可以修改),而不是CONCURRENT
(并发更新是不安全的HashMap
)。因此,它只是检测到并发更改,并在spliterator文档规定的情况下抛出ConcurrentModificationException
。
另外值得援引HashMap
文件:所有的此类的“collection视图方法”返回
的迭代器都是快速失败的:如果地图随时迭代后结构修饰除了通过迭代器自己的remove方法以外的任何方式创建,迭代器都会抛出ConcurrentModificationException
。因此,面对并发修改,迭代器快速而干净地失败,而不是在将来未定的时间冒着任意的,非确定性的行为冒险。
请注意,迭代器的故障快速行为无法得到保证,因为一般来说,在出现非同步并发修改时不可能做出任何硬性保证。失败快速迭代器在尽力而为的基础上抛出ConcurrentModificationException
。因此,编写一个依赖于此异常的程序是正确的:迭代器的故障快速行为应仅用于检测错误。
虽然它只说了迭代器,但我相信这对于分割器来说也是一样的。
我认为这是最好的答案,但您可以编辑它以添加@Eran提到的解决方案。对于将来有同样问题的人来说,这将是100%满意的。 – jaskmar
@MariuszJaskółka,伊兰的答案也在这里,其他人也可能会看到它。这是正确的,我赞成它。我可以添加对他的解决方案的参考。 –