📜  Java8 中的Java.util 接口拆分器

📅  最后修改于: 2022-05-13 01:54:49.170000             🧑  作者: Mango

Java8 中的Java.util 接口拆分器

先决条件: Java中的迭代器

与其他迭代器一样,拆分器用于遍历源的元素。源可以是 Collection、IO 通道或生成器函数。

  • 它包含在 JDK 8 中,用于支持除了顺序遍历之外的高效并行遍历(并行编程)。
  • 但是,即使您不使用并行执行,也可以使用 Spliterator。您可能想要这样做的一个原因是因为它将hasNextnext操作组合到一个方法中。

对于集合,可以通过调用 Collection 接口中的 spliterator() 方法来创建 Spliterator 对象。

// Here "c" is any Collection object. splitr is of
// type Spliterator interface and refers to "c"
Spliterator splitr = c.spliterator();

Spliterator 接口定义了 8 个方法:

  1. int features() :返回此 Spliterator 及其元素的一组特征。结果来自 ORDERED(0x00000010)、DISTINCT(0x00000001)、SORTED(0x00000004)、SIZED(0x00000040)、NONNULL(0x00000100)、IMMUTABLE(0x00000400)、CONCURRENT(0x000010000)、SUBSIZED(0x0000)4。
    Syntax : 
    int characteristics()
    Parameters : 
    NA
    Returns :
    Returns the characteristics of the invoking spliterator,
    encoded into an integer.
    
  2. long estimateSize( ) :它返回一个估计的剩余元素数,如果无限、未知或计算太昂贵,则返回 Long.MAX_VALUE。
    Syntax : 
    long estimateSize( )
    Parameters : 
    NA
    Returns :
    Estimates the number of elements left to iterate and
    returns the result. Returns Long.MAX_VALUE if the
    count cannot be obtained for any reason.
    
  3. default long getExactSizeIfKnown( ) :如果此 Spliterator 是 SIZED 则返回estimateSize() 的便捷方法,否则返回-1。
    Syntax : 
    default long getExactSizeIfKnown( )
    Parameters : 
    NA
    Returns :
    If the invoking spliterator is SIZED, returns the number of
    elements left to iterate. Returns –1 otherwise.
    
  4. 默认比较器 getComparator( ) :如果此 Spliterator 的源由 Comparator 排序,则返回该 Comparator。如果源按自然顺序排序,则返回 null。否则,如果源未排序,则抛出 IllegalStateException。
    Syntax : 
    default Comparator getComparator( )
    Parameters : 
    NA
    Returns :
    Returns the comparator used by the invoking spliterator
    or null if natural ordering is used. 
    Throws:
    IllegalStateException - If the sequence is unordered, 
    IllegalStateException is thrown.
    
  5. default boolean hasCharacteristics(int val) :如果此 Spliterator 的特性 () 包含所有给定特性,则返回 true。
    Syntax : 
    default boolean hasCharacteristics(int val)
    Parameters : 
    characteristics - the characteristics to check for
    Returns :
    Returns true if the invoking spliterator has the
    characteristics passed in val. Returns false otherwise.
    
  6. boolean tryAdvance(Consumer action) :如果存在剩余元素,则对其执行给定的操作,返回 true;否则返回假。如果此 Spliterator 是 ORDERED,则按遇到顺序对下一个元素执行操作。操作引发的异常将转发给调用者。
    Syntax : 
    boolean tryAdvance(Consumer action) 
    Parameters : 
    action - The action
    Returns :
    Returns true if there is a next element. Returns false if no
    elements remain.
    Throws :
    NullPointerException - if the specified action is null
    
  7. default void forEachRemaining(Consumeraction) :在当前线程中按顺序对每个剩余元素执行给定的操作,直到所有元素都已处理完毕或该操作引发异常。如果此 Spliterator 是 ORDERED,则按遇到顺序执行操作。操作引发的异常将转发给调用者。
    Syntax : 
    default void forEachRemaining(Consumeraction)
    Parameters : 
    action - The action
    Returns :
    NA
    Throws :
    NullPointerException - if the specified action is null
    
  8. Spliterator trySplit( ) :如果可能,拆分调用拆分器,返回对分区的新拆分器的引用。否则,返回 null。因此,如果成功,则原始拆分器迭代序列的一部分,返回的拆分器迭代另一部分。
    Syntax : 
    Spliterator trySplit( )
    Parameters : 
    NA
    Returns :
    a Spliterator covering some portion of the elements, 
    or null if this spliterator cannot be split
    

    下面的示例演示 Spliterator 的方法。

    // Java program to demonstrate
    // methods of Spliterator
      
    import java.util.ArrayList;
    import java.util.Spliterator;
    import java.util.stream.Stream;
          
    public class SpliteratorDemo 
    {
        public static void main(String[] args) 
        {
            // Create an array list for doubles.
            ArrayList al = new ArrayList<>();
                  
            // Add values to the array list.
            al.add(1);
            al.add(2);
            al.add(-3);
            al.add(-4);
            al.add(5);
                  
            // Obtain a Stream to the array list.
            Stream str = al.stream();
                  
            // getting Spliterator object on al
            Spliterator splitr1 = str.spliterator();
              
            // estimateSize method
            System.out.println("estimate size : " + splitr1.estimateSize());
                      
            // getExactSizeIfKnown method
            System.out.println("exact size : " + splitr1.getExactSizeIfKnown());
              
            // hasCharacteristics and characteristics method
            System.out.println(splitr1.hasCharacteristics(splitr1.characteristics()));
              
            System.out.println("Content of arraylist :");
            // forEachRemaining method    
            splitr1.forEachRemaining((n) -> System.out.println(n));
              
            // Obtaining another  Stream to the array list.
            Stream str1 = al.stream();
            splitr1 = str1.spliterator();
              
            // trySplit() method
            Spliterator splitr2 = splitr1.trySplit();
              
            // If splitr1 could be split, use splitr2 first.
            if(splitr2 != null) {
            System.out.println("Output from splitr2: ");
            splitr2.forEachRemaining((n) -> System.out.println(n));
            }
      
            // Now, use the splitr
            System.out.println("\nOutput from splitr1: ");
            splitr1.forEachRemaining((n) -> System.out.println(n));
                  
        }
    }
    

    输出:

    estimate size : 5
    exact size : 5
    true
    Content of arraylist :
    1
    2
    -3
    -4
    5
    Output from splitr2: 
    1
    2
    
    Output from splitr1: 
    -3
    -4
    5
    

用于 tryadvance 方法的Java程序

看一下tryAdvance()方法。它对下一个元素执行操作,然后推进迭代器。它显示在这里:

boolean tryAdvance(Consumer action)

在这里, action指定了在迭代中的下一个元素上执行的操作,而 Consumer 是将操作应用于对象的功能接口。它是在Java.util 中声明的通用功能接口。函数。它只有一个抽象方法, accept() ,即
此处显示:

void accept(T objRef)

这里 T 是对象引用的类型。

为了实现我们的动作,我们必须实现accept方法。要实现accept方法,这里我们使用lambda表达式。这将在下面的示例中更加清楚。

如何将 Spliterator 与 Collections 一起使用:将 Spliterator 用于基本的迭代任务非常简单,只需调用tryAdvance()直到它返回 false。

// Java program to demonstrate simple Spliterator
// using tryAdvance method
  
import java.util.ArrayList;
import java.util.Spliterator;
      
public class SpliteratorDemo 
{
    public static void main(String[] args) 
    {
        // Create an array list for doubles.
        ArrayList al1 = new ArrayList<>();
              
        // Add values to the array list.
        al1.add(1);
        al1.add(2);
        al1.add(-3);
        al1.add(-4);
        al1.add(5);
              
              
        // Use tryAdvance() to display(action) contents of arraylist.
              
        System.out.print("Contents of arraylist:\n");
              
        // getting Spliterator object on al1
        Spliterator splitr = al1.spliterator();
              
        // Use tryAdvance() to display(action) contents of arraylist.
        // Notice how lambda expression is used to implement accept method
        // of Consumer interface
              
        while(splitr.tryAdvance((n) -> System.out.println(n)));
              
        // Use tryAdvance() for getting absolute values(action) of contents of arraylist.
              
              
        // Create new list that contains absolute values.
        ArrayList al2 = new ArrayList<>();
              
              
              
        splitr = al1.spliterator();
              
        // Here our action is to get absolute values
        // Notice how lambda expression is used to implement accept method
        // of Consumer interface
        while(splitr.tryAdvance((n) -> al2.add(Math.abs(n))));
              
        System.out.print("Absolute values of contents of arraylist:\n");
              
        // getting Spliterator object on al2
        splitr = al2.spliterator();
              
              
        while(splitr.tryAdvance((n) -> System.out.println(n)));
              
    }
}

输出:

Contents of arraylist:
1
2
-3
-4
5
Absolute values of contents of arraylist:
1
2
3
4
5

注意 tryAdvance( ) 如何将 Iterator 提供的 hasNext( ) 和 next( ) 的目的合并到上面示例中的单个方法中。这提高了迭代过程的效率。

在某些情况下,您可能希望对每个元素共同执行一些操作,而不是一次一个。为了处理这种情况,Spliterator 提供了 forEachRemaining() 方法,它通常用于涉及流的情况。此方法将操作应用于每个未处理的元素,然后返回。