Java8中Iterator和Spliterator的区别

问题描述 投票:0回答:2

我在学习中了解到

Parallelism
Spliterator
的主要优点。

这可能是一个基本问题,但有人可以向我解释

Iterator
Spliterator
之间的主要区别并举一些例子吗?

parallel-processing java-8 iterator spliterator
2个回答
56
投票

Iterator
是一系列可以迭代的元素的简单表示。

例如:

List<String> list = Arrays.asList("Apple", "Banana", "Orange");
Iterator<String> i = list.iterator();
i.next();
i.forEachRemaining(System.out::println);

输出:

Banana
Orange

A

Spliterator
可用于将给定的元素集拆分为多个集合,以便我们可以在不同线程中独立地对每个集合执行某种操作/计算,可能会利用并行性。它被设计为迭代器的并行类似物。除了集合之外,Spliterator 所覆盖的元素源还可以是数组、IO 通道或生成器函数等。

Spliterator
界面中有2个主要方法。

- tryAdvance() 和 forEachRemaining()

通过tryAdvance(),我们可以一一遍历底层元素(就像Iterator.next()一样)。如果存在剩余元素,则此方法对其执行消费者操作,返回 true;否则返回 false。

对于顺序批量遍历,我们可以使用 forEachRemaining():

List<String> list = Arrays.asList("Apple", "Banana", "Orange");
Spliterator<String> s = list.spliterator();
s.tryAdvance(System.out::println);
System.out.println(" --- bulk traversal");
s.forEachRemaining(System.out::println);

System.out.println(" --- attempting tryAdvance again");
boolean b = s.tryAdvance(System.out::println);
System.out.println("Element exists: "+b);

输出:

Apple
 --- bulk traversal
Banana
Orange
 --- attempting tryAdvance again
Element exists: false

- Spliterator trySplit()

将此分割器一分为二并返回新的:

List<String> list = Arrays.asList("Apple", "Banana", "Orange");

Spliterator<String> s = list.spliterator();
Spliterator<String> s1 = s.trySplit();

s.forEachRemaining(System.out::println);
System.out.println("-- traversing the other half of the spliterator --- ");
s1.forEachRemaining(System.out::println);

输出:

Banana
Orange
-- traversing the other half of the spliterator ---
Apple

理想的 trySplit 方法应该将其元素精确地分成两半,从而允许平衡的并行计算。

分裂过程也称为“分区”或“分解”。


50
投票

对我来说,这些名字几乎是不言自明的。

Spliterator
== Splittable Iterator :它可以分割一些源,也可以迭代它。它大致具有与
Iterator
相同的功能,但还有一个额外的功能,它可以将 split 分成多个部分:这就是
trySplit
的用途。并行处理需要拆分。

Iterator
始终具有未知的大小:只能通过
hasNext/next
遍历元素; a
Spliterator
可以提供大小(从而在内部改进其他操作);通过
getExactSizeIfKnown
获得精确值,或通过
estimateSize
获得近似值。

另一方面,

tryAdvance
hasNext/next
来自
Iterator
,但它是单一方法,更容易推理,IMO。与此相关的是
forEachRemaining
,它在默认实现中委托给
tryAdvance
,但它不必总是这样(例如参见
ArrayList
)。

Spliterator 也是一个“更智能”的迭代器,通过其内部属性如

DISTINCT
SORTED
等(您需要在实现自己的
Spliterator
时正确提供)。这些标志在内部使用来禁用不必要的操作;例如,请参阅此优化:

 someStream().map(x -> y).count();

因为在流的情况下大小不会改变,所以可以完全跳过

map
,因为我们所做的只是计数。

如果需要,您可以通过以下方式围绕迭代器创建 Spliterator:

Spliterators.spliteratorUnknownSize(yourIterator, properties)
© www.soinside.com 2019 - 2024. All rights reserved.