March 28, 2022

Java Spliterator With Examples

Spliterator in Java, just like Iterator and ListIterator, is used for traversing the elements of a source. How it differs from other iterator implementation is that the Spliterator API is designed to support efficient parallel traversal in addition to sequential traversal. Using Spliterator elements can be partitioned and iterated in parallel.

Important points about Java Spliterator

  1. Spliterator API is defined using Spliterator interface which is part of java.util package.
  2. Spliterator interface was added in Java 8.
  3. Source for a Spliterator could be an array, a Collection, an IO channel, or a generator function.
  4. Spliterator can be used for both parallel and sequential traversal.
  5. When you use Iterator for traversal you have to use two methods-

    a. hasNext() to ensure that there is next element

    b. next() method to use that element.

    Methods in Java Spliterator combine these two methods into one making it more convenient to use.

Java Spliterator methods

Spliterator API defines the following methods.
  1. characteristics()- Returns a set of characteristics of this Spliterator and its elements.
  2. estimateSize()- Returns an estimate of the number of elements or returns Long.MAX_VALUE if infinite, unknown, or too expensive to compute.
  3. forEachRemaining(Consumer<? super T> 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.
  4. getComparator()- If this Spliterator's source is SORTED by a Comparator, returns that Comparator.
  5. getExactSizeIfKnown()- Convenience method that returns estimateSize() if this Spliterator is SIZED, else -1.
  6. hasCharacteristics(int characteristics)- Returns true if this Spliterator's characteristics() contain all of the given characteristics.
  7. tryAdvance(Consumer<? super T> action)- If a remaining element exists, performs the given action on it, returning true; else returns false.
  8. trySplit()- Using this method spliterator can be partitioned into two. Returns a new Spliterator covering elements, that will, upon return from this method, not be covered by the current Spliterator.

Java Spliterator Characteristics

Spliterator also defines following characteristics which are constant int values.

  1. CONCURRENT- Characteristic value signifying that the element source may be safely concurrently modified by multiple threads without external synchronization.
  2. DISTINCT- Characteristic value signifying that for each pair of encountered elements x, y, !x.equals(y).
  3. IMMUTABLE- Characteristic value signifying that the element source cannot be structurally modified.
  4. NONNULL- Characteristic value signifying that the source guarantees that encountered elements will not be null.
  5. ORDERED- Characteristic value signifying that an encounter order is defined for elements.
  6. SIZED- Characteristic value signifying that the value returned from estimateSize() is the exact count of elements.
  7. SORTED- Characteristic value signifying that encounter order follows a defined sort order.
  8. SUBSIZED- Characteristic value signifying that all Spliterators resulting from trySplit() will be both SIZED and SUBSIZED.

Java Spliterator example

Let’s see some examples to understand how traversal is done using Spliterator and how to use its methods.

Traversing using Spliterator's tryAdvance() method
public class SpliteratorTraversal {
  public static void main(String[] args) {
    List<String> listOfNames = Arrays.asList("Clint", "Gregory", "James", "John", "Humphrey", "Cary", "Kirk");		
    Spliterator<String> spliterator = listOfNames.spliterator();
    System.out.println("--- Names in the list ---");
    while(spliterator.tryAdvance(System.out::println));
    spliterator = listOfNames.spliterator();
    System.out.println("--- Names in the list in upper case ---");
    while(spliterator.tryAdvance(n -> System.out.println(n.toUpperCase())));
  }
}
Output
--- Names in the list ---
Clint
Gregory
James
John
Humphrey
Cary
Kirk
--- Names in the list in upper case ---
CLINT
GREGORY
JAMES
JOHN
HUMPHREY
CARY
KIRK
Example using estimateSize(), getExactSizeIfKnown(), forEachRemaining() methods
public class SpliteratorTraversal {
  public static void main(String[] args) {
    List<String> listOfNames = Arrays.asList("Clint", "Gregory", "James", "John", "Humphrey", 
				                   "Cary", "Kirk");		
    Spliterator<String> spliterator = listOfNames.spliterator();
    System.out.println("Estimated Size of source- " + spliterator.estimateSize());	     
    System.out.println("Exact Size of source- " + spliterator.getExactSizeIfKnown());	     
    System.out.println("--- Names in the list in upper case ---");
    spliterator.forEachRemaining(n -> System.out.println(n.toUpperCase()));
  }
}
Output
Estimated Size of source- 7
Exact Size of source- 7
--- Names in the list in upper case ---
CLINT
GREGORY
JAMES
JOHN
HUMPHREY
CARY
KIRK
Splitting using trySplit() Java example
public class SpliteratorTraversal {
  public static void main(String[] args) {
    List<String> listOfNames = Arrays.asList("Clint", "Gregory", "James", "John", "Humphrey", 
				                   "Cary", "Kirk");		
    Spliterator<String> split1 = listOfNames.spliterator();
    Spliterator<String> split2 = split1.trySplit();
    // checking if spliterator is actually split
    if(split2 != null) {
     System.out.println("Partition- ");
     while(split2.tryAdvance((n) -> System.out.println(n)));
    }
    System.out.println("Partition- ");
    while(split1.tryAdvance((n) -> System.out.println(n)));
  }
}
Output
Partition- 
Clint
Gregory
James
Partition- 
John
Humphrey
Cary
Kirk

That's all for the topic Java Spliterator With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment