In Java, a Spliterator (splitable iterator) is an interface in the ‘java.util‘ package and is used for partitioning and traversing the elements of a collection in parallel. Unlike traditional iterators, Spliterator is designed with parallelism in mind and mainly helps in parallel processing when the collection or stream has a large number of elements.
Under normal conditions, the Spliterator will behave exactly same as an Iterator.
Spliterator<T> spliterator = list.spliterator();
1. Features of Spliterator
Following is a list of features provided by Spliterator in Java.
- Spliterator has been introduced in Java 8.
- It provides support for parallel processing of a stream of elements for any collection.
- It provides tryAdvance() method to iterate elements individually in different threads. It helps in parallel processing.
- To iterate elements sequentially in a single Thread, use forEachRemaining() method.
- The trySplit() method is used to partition the spliterator if it is possible.
- It helps in combining the
hasNext()
andnext()
operations into one method.
2. Spliterator Methods
Method Name | Description |
---|---|
characteristics() | Returns the list of characteristics of the spliterator. It can be any of ORDERED, DISTINCT, SORTED, SIZED, NONNULL, IMMUTABLE, CONCURRENT, and SUBSIZED. |
estimateSize() | Returns an estimate of the number of elements that would be encountered by a forEachRemaining() traversal, or returns Long.MAX_VALUE if infinite, unknown, or too expensive to compute. |
forEachRemaining(Consumer action) | Performs the given action for each remaining element, sequentially in the current thread, until all elements have been processed or the action throws an exception. |
getComparator() | If the spliterator’s source is SORTED by a Comparator, returns that Comparator. |
getExactSizeIfKnown() | Returns estimateSize() if this Spliterator is SIZED, else -1. |
tryAdvance(Consumer action) | If a remaining element exists then perform the given action on it, returning true; else returns false. |
trySplit() | If the spliterator can be partitioned, returns a Spliterator covering elements, that will, upon return from this method, not be covered by this Spliterator. |
3. Spliterator with Stream
The Java collection framework provides default stream() and parallelStream() methods which internally use the Spliterator through the call to the spliterator(). It helps in processing the collection the data in parallel.
default Stream<E> stream() {
return StreamSupport.stream(spliterator, false);
}
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator, true);
}
4. Java Spliterator Example
4.1. Spliterator characteristics() Example
Java example to verify the characteristics of Spliterator obtained for ArrayList.
ArrayList<String> list = new ArrayList<>();
Spliterator<String> spliterator = list.spliterator();
int expected = Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
System.out.println(spliterator.characteristics() == expected); //true
if (spliterator.hasCharacteristics(Spliterator.ORDERED)) {
System.out.println("ORDERED");
}
if (spliterator.hasCharacteristics(Spliterator.DISTINCT)) {
System.out.println("DISTINCT");
}
if (spliterator.hasCharacteristics(Spliterator.SORTED)) {
System.out.println("SORTED");
}
if (spliterator.hasCharacteristics(Spliterator.SIZED)) {
System.out.println("SIZED");
}
if (spliterator.hasCharacteristics(Spliterator.CONCURRENT)) {
System.out.println("CONCURRENT");
}
if (spliterator.hasCharacteristics(Spliterator.IMMUTABLE)) {
System.out.println("IMMUTABLE");
}
if (spliterator.hasCharacteristics(Spliterator.NONNULL)) {
System.out.println("NONNULL");
}
if (spliterator.hasCharacteristics(Spliterator.SUBSIZED)) {
System.out.println("SUBSIZED");
}
Program Output.
true
ORDERED
SIZED
SUBSIZED
4.2. Spliterator estimateSize() and getExactSizeIfKnown()
Java example to get the size of backing collection i.e. number of elements to iterate by spliterator.
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
Spliterator<String> spliterator = list.spliterator();
System.out.println(spliterator.estimateSize());
System.out.println(spliterator.getExactSizeIfKnown());
Program Output.
4
4
4.3. Spliterator getComparator()
Java example to find the comparator used by spliterator.
SortedSet<String> set = new TreeSet<>( Collections.reverseOrder() );
set.add("A");
set.add("D");
set.add("C");
set.add("B");
System.out.println(set);
System.out.println(set.spliterator().getComparator());
Program Output.
[D, C, B, A]
java.util.Collections$ReverseComparator@7852e922
4.4. Spliterator trySplit() example
Java example to split the elements to two groups and iterate independently.
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
list.add("F");
Spliterator<String> spliterator1 = list.spliterator();
Spliterator<String> spliterator2 = spliterator1.trySplit();
spliterator1.forEachRemaining(System.out::println);
System.out.println("========");
spliterator2.forEachRemaining(System.out::println);
Program Output.
D
E
F
========
A
B
C
4.5. Spliterator forEachRemaining() example
Java example to perform hasNext() and next() operations in single statement using forEachRemaining() method.
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
Spliterator<String> spliterator = list.spliterator();
spliterator.forEachRemaining(System.out::println);
Program Output.
A
B
C
D
5. Conclusion
In this tutorial, we learned the Java Spliterator interface. We learned the Spliterator methods and simple examples to iterate over collections elements and streams apart from other useful methods in Spliterator.
Drop me your questions in comments section.
Happy Learning !!
References: Spliterator Interface Java Docs
Comments