42

我在学习时才知道这ParallelismSpliterator.

这可能是一个基本问题,但任何人都可以向我解释和之间的主要区别Iterator并举Spliterator一些例子吗?

4

2 回答 2

40

对我来说,这些名字几乎是不言自明的。Spliterator== Splittable Iterator:它可以拆分一些源,它也可以迭代它。它具有与 大致相同的功能Iterator,但有一个额外的东西,它可能会分成多个部分:这就是trySplit它的用途。并行处理需要拆分。

AnIterator总是有一个未知的大小:你只能通过hasNext/next;遍历元素。aSpliterator可以提供大小(从而在内部也改进其他操作);一个精确的 viagetExactSizeIfKnown或一个近似的 via estimateSize

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

Spliterator 也是一个“更智能”的迭代器,通过它的内部属性,如DISTINCTorSORTED等​​(在实现自己的时需要正确提供Spliterator)。这些标志在内部用于禁用不必要的操作;例如看这个优化:

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

因为在流的情况下大小不会改变,所以map可以完全跳过,因为我们所做的只是计数。

如果需要,可以通过以下方式在 Iterator 周围创建 Spliterator:

Spliterators.spliteratorUnknownSize(yourIterator, properties)
于 2018-07-21T19:42:58.663 回答
39

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

例如:

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

#output
Banana
Orange

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

接口中有2个主要方法Spliterator

- tryAdvance() 和 forEachRemaining()

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

对于顺序批量遍历,我们可以使用 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

- 拆分器 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 方法应该将其元素精确地分成两半,从而实现平衡的并行计算。

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

于 2018-07-21T08:51:53.893 回答