Java8 中的Java.util 接口拆分器
先决条件: Java中的迭代器
与其他迭代器一样,拆分器用于遍历源的元素。源可以是 Collection、IO 通道或生成器函数。
- 它包含在 JDK 8 中,用于支持除了顺序遍历之外的高效并行遍历(并行编程)。
- 但是,即使您不使用并行执行,也可以使用 Spliterator。您可能想要这样做的一个原因是因为它将hasNext和next操作组合到一个方法中。
对于集合,可以通过调用 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 个方法:
- 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.
- 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.
- 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.
- 默认比较器 super T> getComparator( ) :如果此 Spliterator 的源由 Comparator 排序,则返回该 Comparator。如果源按自然顺序排序,则返回 null。否则,如果源未排序,则抛出 IllegalStateException。
Syntax : default Comparator super T> 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.
- 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.
- boolean tryAdvance(Consumer super T> action) :如果存在剩余元素,则对其执行给定的操作,返回 true;否则返回假。如果此 Spliterator 是 ORDERED,则按遇到顺序对下一个元素执行操作。操作引发的异常将转发给调用者。
Syntax : boolean tryAdvance(Consumer super T> 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
- default void forEachRemaining(Consumer super T>action) :在当前线程中按顺序对每个剩余元素执行给定的操作,直到所有元素都已处理完毕或该操作引发异常。如果此 Spliterator 是 ORDERED,则按遇到顺序执行操作。操作引发的异常将转发给调用者。
Syntax : default void forEachRemaining(Consumer super T>action) Parameters : action - The action Returns : NA Throws : NullPointerException - if the specified action is null
- 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 super T> 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() 方法,它通常用于涉及流的情况。此方法将操作应用于每个未处理的元素,然后返回。