看起来我可以直接在我的集合上调用 list.forEach(a -> a.stuff())
,而不是 list.stream().forEach(a -> a.stuff())
。除了使用 parallelStream()
之外,我应该在什么情况下使用其中之一?
看起来我可以直接在我的集合上调用 list.forEach(a -> a.stuff())
,而不是 list.stream().forEach(a -> a.stuff())
。除了使用 parallelStream()
之外,我应该在什么情况下使用其中之一?
有一些不同之处:
Iterable.forEach
保证按迭代顺序处理,如果定义了 Iterable。(对于列表,迭代顺序通常是明确定义的。) Stream.forEach
不行;必须使用 Stream.forEachOrdered
代替。
Iterable.forEach
可能允许在底层数据结构上产生副作用。虽然许多集合的迭代器在迭代期间修改集合会抛出ConcurrentModificationException
,但某些集合的迭代器明确允许它。例如,请参阅 CopyOnWriteArrayList
。相比之下,流操作通常不能干扰流源。
如果 Iterable 是同步包装集合,例如来自 Collections.synchronizedList()
,对其调用 forEach
将在整个迭代期间保持其锁定。这将防止其他线程在迭代期间修改集合,确保迭代看到集合的一致视图,并防止 ConcurrentModificationException
。这也将防止其他线程在迭代期间读取集合。但是,这不适用于流。没有什么可以防止集合在流操作期间被修改,如果发生修改,则结果是未定义的。
Stream.forEach
与Iterable.forEach
相比允许修改流源。我怀疑你是否想这样暗示! - Maurice Naftalin