gpt4 book ai didi

java - Collection.stream().forEach() 和 Collection.forEach() 有什么区别?

转载 作者:行者123 更新时间:2023-12-02 08:55:22 25 4
gpt4 key购买 nike

据我了解,通过 .stream(),我可以使用 .filter() 等链式操作或使用并行流。但是如果我需要执行小操作(例如,打印列表的元素),它们之间有什么区别?

collection.stream().forEach(System.out::println);
collection.forEach(System.out::println);

最佳答案

对于如图所示的简单情况,它们大多是相同的。但是,存在一些可能很重要的细微差别。

其中一个问题是订购。对于Stream.forEach,顺序是未定义。对于顺序流来说,这种情况不太可能发生,但它仍然符合 Stream.forEach 以某种任意顺序执行的规范。这在并行流中经常发生。相比之下,如果指定的话,Iterable.forEach 始终按照 Iterable 的迭代顺序执行。

另一个问题是副作用。 Stream.forEach 中指定的操作必须是非干扰。 (请参阅 java.util.stream package doc 。)Iterable.forEach 可能具有较少的限制。对于java.util中的集合,Iterable.forEach通常会使用该集合的Iterator,其中大部分被设计为 fail-fast如果集合在迭代期间发生结构性修改,则会抛出 ConcurrentModificationException。但是,在迭代过程中允许进行非结构性的修改。例如,ArrayList class documentation说“仅仅设置元素的值不是结构修改。”因此,ArrayList.forEach 的操作可以毫无问题地在底层 ArrayList 中设置值。

并发集合又有所不同。它们不是快速失败,而是被设计为 weakly consistent 。完整的定义位于该链接。不过,简单地考虑一下ConcurrentLinkedDeque。传递给其 forEach 方法的操作允许修改底层双端队列,甚至是结构上的修改,并且永远不会抛出 ConcurrentModificationException 。但是,发生的修改在此迭代中可能可见,也可能不可见。 (因此是“弱”一致性。)

如果 Iterable.forEach 迭代同步集合,则还可以看到另一个差异。在这样的集合上,Iterable.forEach takes the collection's lock一次并在对操作方法的所有调用中保留它。 Stream.forEach 调用使用集合的 spliterator,它不锁定,并且依赖于不干扰的普遍规则。支持流的集合可能会在迭代期间被修改,如果是这样,可能会导致 ConcurrentModificationException 或不一致的行为。

关于java - Collection.stream().forEach() 和 Collection.forEach() 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25854555/

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