Collection.stream()。forEach()和Collection.forEach()之间有什么区别? [英] What is difference between Collection.stream().forEach() and Collection.forEach()?

查看:940
本文介绍了Collection.stream()。forEach()和Collection.forEach()之间有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道使用 .stream(),我可以使用 .filter()平行流。但是如果我需要执行小的操作(例如,打印列表的元素),它们之间的区别是什么?

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


解决方案

对于如图所示的简单情况,大部分是一样的。但是,有一些细微的差异可能很重要。



一个问题是订购。使用 Stream.forEach ,订单为未定义。它不可能发生在顺序流中,但仍然在 Stream.forEach 的规范中以某种任意顺序执行。这在并行流中经常发生。相反,如果指定 Iterable ,则 Iterable.forEach 总是以 Iterable 的迭代顺序执行。 p>

另一个问题是副作用。 Stream.forEach 中指定的操作必须为非干扰。 (请参阅 java.util.stream包doc < a>。) Iterable.forEach 可能有较少的限制。对于 java.util 中的集合, Iterable.forEach 通常使用该集合的 Iterator ,其中大部分设计为 fail-fast ,如果在迭代期间结构上修改了集合,它将抛出 ConcurrentModificationException 。但是,在迭代过程中允许不是结构的修改。例如, ArrayList类文档说仅设置一个元素不是结构修改。因此,允许 ArrayList.forEach 的操作在底层 ArrayList 中设置值,而不会出现问题。



并发集合又是不同的。不是故障快速,它们设计为弱一致。完整的定义是在那个链接。简而言之,考虑 ConcurrentLinkedDeque 。传递给其 forEach 方法的操作允许修改底层deque,即使是结构化, ConcurrentModificationException 永远不会抛出。但是,发生的修改可能会或可能不会在此迭代中可见。 (因此弱一致性。)



还有另一个区别是,如果 Iterable.forEach 同步收集。在这样的集合中, Iterable.forEach 使用集合的一次锁定,并将其保存在对action方法的所有调用中。 Stream.forEach 调用使用集合的分割器,它不锁定,它依赖于主要的不干扰规则。可以在迭代期间修改支持流的集合,如果是,则可能会导致 ConcurrentModificationException 或不一致的行为。


I understand that with .stream(), I can use chain operations like .filter() or use parallel stream. But what is difference between them if I need to execute small operations (for example, printing the elements of the list)?

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

解决方案

For simple cases such as the one illustrated, they are mostly the same. However, there are a number of subtle differences that might be significant.

One issue is with ordering. With Stream.forEach, the order is undefined. It's unlikely to occur with sequential streams, still, it's within the specification for Stream.forEach to execute in some arbitrary order. This does occur frequently in parallel streams. By contrast, Iterable.forEach is always executed in the iteration order of the Iterable, if one is specified.

Another issue is with side effects. The action specified in Stream.forEach is required to be non-interfering. (See the java.util.stream package doc.) Iterable.forEach potentially has fewer restrictions. For the collections in java.util, Iterable.forEach will generally use that collection's Iterator, most of which are designed to be fail-fast and which will throw ConcurrentModificationException if the collection is structurally modified during the iteration. However, modifications that aren't structural are allowed during iteration. For example, the ArrayList class documentation says "merely setting the value of an element is not a structural modification." Thus, the action for ArrayList.forEach is allowed to set values in the underlying ArrayList without problems.

The concurrent collections are yet again different. Instead of fail-fast, they are designed to be weakly consistent. The full definition is at that link. Briefly, though, consider ConcurrentLinkedDeque. The action passed to its forEach method is allowed to modify the underlying deque, even structurally, and ConcurrentModificationException is never thrown. However, the modification that occurs might or might not be visible in this iteration. (Hence the "weak" consistency.)

Still another difference is visible if Iterable.forEach is iterating over a synchronized collection. On such a collection, Iterable.forEach takes the collection's lock once and holds it across all the calls to the action method. The Stream.forEach call uses the collection's spliterator, which does not lock, and which relies on the prevailing rule of non-interference. The collection backing the stream could be modified during iteration, and if it is, a ConcurrentModificationException or inconsistent behavior could result.

这篇关于Collection.stream()。forEach()和Collection.forEach()之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆