Java8中的迭代器和拆分器之间的区别

时间:2018-07-21 07:25:17

标签: parallel-processing java-8 iterator spliterator

在学习ParallelismSpliterator的主要优势时,我才知道。

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

2 个答案:

答案 0 :(得分:10)

对我来说,名字几乎是不言而喻的。 Spliterator == 可拆分迭代器:它可以拆分某些源,也可以对其进行迭代。它具有与Iterator相同的功能,但是它有可能分割成多个片段,这是trySplit的目的。并行处理需要拆分。

Iterator的大小始终未知,您只能通过hasNext/next遍历元素; Spliterator可以提供大小(从而在内部改善其他操作);可以是通过getExactSizeIfKnown的精确值,也可以是estimateSize的近似值。

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

通过它的内部属性,例如DISTINCTSORTED等(您需要在实现自己的Spliterator时正确提供),拆分器也是“更智能”的迭代器。这些标志在内部用于禁用不必要的操作,也称为优化,例如以下示例:

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

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

如果需要,您可以通过以下方式在迭代器周围创建一个拆分器:

Spliterators.spliteratorUnknownSize(yourIterator, properties)

答案 1 :(得分:7)

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

例如:

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

#output
Banana
Orange

Spliterator可用于将给定的元素集分成多个集合,以便我们可以在并行线程中对每个集合分别在不同线程中独立执行某种运算/计算。它被设计为Iterator的并行模拟。除集合外,分隔器覆盖的元素的来源可以是例如数组,IO通道或生成器函数。

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

-tryAdvance()和forEachRemaining()

使用tryAdvance(),我们可以一一遍历基础元素(就像Iterator.next()一样)。如果存在剩余元素,则此方法对其执行消费者操作,返回true;否则,返回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

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

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