Java8 中 Iterator 和 Spliterator 的区别
Difference between Iterator and Spliterator in Java8
我在学习中了解到 Parallelism
是 Spliterator
的主要优点。
这可能是一个基本问题,但谁能向我解释 Iterator
和 Spliterator
之间的主要区别并举一些例子?
Iterator
是一系列可以迭代的元素的简单表示。
例如:
List<String> list = Arrays.asList("Apple", "Banana", "Orange");
Iterator<String> i = list.iterator();
i.next();
i.forEachRemaining(System.out::println);
#output
Banana
Orange
A Spliterator
可用于将给定元素集拆分为多个集,以便我们可以在不同线程中对每个集独立执行某种 operations/calculations,可能会利用并行性。它被设计为 Iterator 的并行模拟。除了集合之外,Spliterator 涵盖的元素源可以是数组、IO 通道或生成器函数。
Spliterator
接口中有2个主要方法。
- tryAdvance() 和 forEachRemaining()
使用tryAdvance(),我们可以一个一个遍历底层元素(就像Iterator.next())。如果存在剩余元素,则此方法对其执行消费者操作,返回 true;否则 returns 错误。
对于顺序批量遍历,我们可以使用 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()
将此拆分器拆分为两个,returns 拆分为新拆分器:
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 方法应该将它的元素精确地分成两半,从而允许平衡的并行计算。
拆分过程也称为'partitioning'或'decomposition'。
对我来说,这些名称几乎是不言自明的。 Spliterator
== Splittable Iterator : 它可以拆分一些源,也可以迭代它。它大致具有与 Iterator
相同的功能,但还有一个额外的东西,它可能 将 分成多个部分:这就是 trySplit
的用途。并行处理需要拆分。
一个Iterator
总是有一个未知的大小:你只能通过hasNext/next
遍历元素; a Spliterator
可以提供大小(从而在内部改进其他操作);通过 getExactSizeIfKnown
的精确值或通过 estimateSize
.
的近似值
另一方面,tryAdvance
是 hasNext/next
来自 Iterator
,但它是一种单一方法,更容易推理,IMO。与此相关的是 forEachRemaining
,它在默认实现中委托给 tryAdvance
,但它不必总是这样(例如参见 [=25=])。
Spliterator 也是一个 "smarter" 迭代器,通过其内部属性,如 DISTINCT
或 SORTED
等(在实现自己的 [=12= 时需要正确提供) ]).这些标志在内部用于禁用不必要的操作;例如,请参阅此优化:
someStream().map(x -> y).count();
因为在流的情况下大小不会改变,所以 map
可以完全跳过,因为我们所做的只是计数。
如果需要,您可以通过以下方式围绕迭代器创建拆分器:
Spliterators.spliteratorUnknownSize(yourIterator, properties)
我在学习中了解到 Parallelism
是 Spliterator
的主要优点。
这可能是一个基本问题,但谁能向我解释 Iterator
和 Spliterator
之间的主要区别并举一些例子?
Iterator
是一系列可以迭代的元素的简单表示。
例如:
List<String> list = Arrays.asList("Apple", "Banana", "Orange");
Iterator<String> i = list.iterator();
i.next();
i.forEachRemaining(System.out::println);
#output
Banana
Orange
A Spliterator
可用于将给定元素集拆分为多个集,以便我们可以在不同线程中对每个集独立执行某种 operations/calculations,可能会利用并行性。它被设计为 Iterator 的并行模拟。除了集合之外,Spliterator 涵盖的元素源可以是数组、IO 通道或生成器函数。
Spliterator
接口中有2个主要方法。
- tryAdvance() 和 forEachRemaining()
使用tryAdvance(),我们可以一个一个遍历底层元素(就像Iterator.next())。如果存在剩余元素,则此方法对其执行消费者操作,返回 true;否则 returns 错误。
对于顺序批量遍历,我们可以使用 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()
将此拆分器拆分为两个,returns 拆分为新拆分器:
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 方法应该将它的元素精确地分成两半,从而允许平衡的并行计算。
拆分过程也称为'partitioning'或'decomposition'。
对我来说,这些名称几乎是不言自明的。 Spliterator
== Splittable Iterator : 它可以拆分一些源,也可以迭代它。它大致具有与 Iterator
相同的功能,但还有一个额外的东西,它可能 将 分成多个部分:这就是 trySplit
的用途。并行处理需要拆分。
一个Iterator
总是有一个未知的大小:你只能通过hasNext/next
遍历元素; a Spliterator
可以提供大小(从而在内部改进其他操作);通过 getExactSizeIfKnown
的精确值或通过 estimateSize
.
另一方面,tryAdvance
是 hasNext/next
来自 Iterator
,但它是一种单一方法,更容易推理,IMO。与此相关的是 forEachRemaining
,它在默认实现中委托给 tryAdvance
,但它不必总是这样(例如参见 [=25=])。
Spliterator 也是一个 "smarter" 迭代器,通过其内部属性,如 DISTINCT
或 SORTED
等(在实现自己的 [=12= 时需要正确提供) ]).这些标志在内部用于禁用不必要的操作;例如,请参阅此优化:
someStream().map(x -> y).count();
因为在流的情况下大小不会改变,所以 map
可以完全跳过,因为我们所做的只是计数。
如果需要,您可以通过以下方式围绕迭代器创建拆分器:
Spliterators.spliteratorUnknownSize(yourIterator, properties)