【问题标题】:Difference between Iterator and Spliterator in Java8Java8中迭代器和拆分器的区别
【发布时间】:2018-12-29 10:23:17
【问题描述】:

我在学习时了解到ParallelismSpliterator 的主要优势。

这可能是一个基本问题,但谁能解释一下IteratorSpliterator 之间的主要区别并举一些例子?

【问题讨论】:

    标签: parallel-processing java-8 iterator spliterator


    【解决方案1】:

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

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

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

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

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

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

    如果需要,您可以在 Iterator 周围创建 Spliterator,方法是:

    Spliterators.spliteratorUnknownSize(yourIterator, properties)
    

    【讨论】:

      【解决方案2】:

      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 可用于将给定元素集拆分为多个集合,以便我们可以在不同线程中独立地对每个集合执行某种操作/计算,这可能会利用并行性。它被设计为迭代器的并行模拟。除了集合之外,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
      

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

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

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-14
      • 1970-01-01
      • 2010-11-20
      • 2014-05-08
      • 2010-10-31
      • 1970-01-01
      • 2014-12-05
      • 2020-03-27
      相关资源
      最近更新 更多