Spliterator in Java


JavaViews 1341

Java Spliterator is another type of Iterator interface to navigate through individual elements. As the name suggests, it supports Split and iteration together. This means we can perform parallel programming using Spliterator.

Java Spliterator

Spliterator was available from Java8 onwards. We can use it to iterate over both Collections and Stream API apart from Map implementation. Using Java Spliterator, we can split the list and then iterate to retrieve each element. We can also perform a sequential iteration similar to Iterator. It has 1 single method that performs the combined operation of the hasNext() and next() methods of the Iterator interface.

The main usage of Java Spliterator is to split the input into different parts and then process each part separately in parallel. It is useful to process large amounts of data through parallel programming.

Java Spliterator methods

Below are the commonly used methods in the Java Spliterator interface:

MethodsDescriptionParameter
int characteristics()Returns the characteristics of the spliterator and its elements.
long estimateSize()Returns the estimate of the number of elements that will be encountered by the forEachRemaining traversal
void forEachRemaining(Consumer action)Performs the given action for each elementaction - action to be performed
Comparator getComparator()If the source is SORTED by a comparator, then it returns the comparator, if sorted in natural order returns null, else it throws IllegalStateException
long getExactSizeIfKnown()Returns the exact size if source is SIZED, else returns by default value -1
boolean hasCharacteristics(int characteristics)Returns true if the spliterator contains all the characteristicscharacteristics - the characteristics that has to be checked
boolean tryAdvance(Consumer action)If remaining element exists, it performs the action on it and returns true else it returns false.action - action to be performed
Spliterator trysplit()If the spliterator can be partitioned, returns the spliterator covering the elements else returns null if it cannot be split

Exceptions in Java Spliterator

Java Spliterator can throw the below exceptions while using its methods:

  • NullPointerException – If the action is null in the forEachRemaining method and tryAdvance method.
  • IllegalStateException – If the spliterator does not report a characteristic of SORTED

Example: Characteristics and hasCharacteristics

Characteristics() method returns a set of characteristics of the java spliterator and its elements. It may be one of the below 8 static final integer values:

  • ORDERED – This denotes that the spliterator elements are defined in an order
  • DISTINCT – This means each value is distinct to each other even if we create a spliterator from the set.
  • IMMUTABLE – This means we can modify the source of the elements.
  • NONNULL – The spliterator element cannot be null.
  • SIZED – The value returned by estimateSize() represents a finite size.
  • SORTED – The elements are in a sorted order
  • SUBSIZED – This means all spliterator returned by trySplit() will be SIZED or SUBSIZED.
  • CONCURRENT – This denotes that we can modify the source concurrently which means we can add, remove elements concurrently using multiple threads.

hasCharacteristics() method checks if the spliterator has all the above characteristics. If it contains all the characteristics, it returns true else it returns false.

Below is an example to demonstrate the above two methods of the spliterator. The first output is true since the spliterator has all the characteristics. We have then initialized a variable with spliterator characteristics. Hence it will print the statements where the conditions matches these defined values. That is the reason it prints SIZED and ORDERED and does not print IMMUTABLE.

import java.util.ArrayList;
import java.util.Spliterator;

public class SplitIteratorExample {

  public static void main(String[] args) {
    ArrayList<String> cars = new ArrayList<String>();
    cars.add("Maruthi");
    cars.add("BMW");
    cars.add("Benz");
    cars.add("Creta");
    cars.add("Nissan");
    
    
    Spliterator<String> s = cars.spliterator();
    int values = Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SIZED;
    
    System.out.println("Output of hasCharacteristics: " + s.hasCharacteristics(s.characteristics()));
    
    if(s.hasCharacteristics(Spliterator.ORDERED))
      System.out.println("Characteristic is Ordered");
    if(s.hasCharacteristics(Spliterator.SIZED))
      System.out.println("Characteristic is Sized");
    if(s.hasCharacteristics(Spliterator.IMMUTABLE))
      System.out.println("Characteristic is Immutable");
    
  }

}
Output of hasCharacteristics: true
Characteristic is Ordered
Characteristic is Sized

Example: estimateSize and getExactSizeIfKnown

estimateSize() method returns the size of the elements in the java spliterator. getExactSizeIfKnown() method returns the size if present else it returns -1.

import java.util.ArrayList;
import java.util.Spliterator;

public class SplitIteratorExample {

  public static void main(String[] args) {
    ArrayList<String> cars = new ArrayList<String>();
    cars.add("Maruthi");
    cars.add("BMW");
    cars.add("Benz");
    cars.add("Creta");
    cars.add("Nissan");
    
    
    Spliterator<String> s = cars.spliterator();
    System.out.println("Estimated size: " + s.estimateSize());
    System.out.println("getExactSizeIfKnown: " + s.getExactSizeIfKnown());
    
  }

}
Estimated size: 5
getExactSizeIfKnown: 5

Example: forEachRemaining

The forEachRemaining() method performs the specified action for every element in the java spliterator. This method is equivalent to the hasNext() and the next() method in the Iterator.

In the below example, the forEachRemaining() method performs the print action for each element in the spliterator. In other words, it prints each and every element present in the spliterator.

import java.util.ArrayList;
import java.util.Spliterator;

public class SplitIteratorExample {

  public static void main(String[] args) {
    ArrayList<String> cars = new ArrayList<String>();
    cars.add("Maruthi");
    cars.add("BMW");
    cars.add("Benz");
    cars.add("Creta");
    cars.add("Nissan");
    
    Spliterator<String> s = cars.spliterator();
    
    s.forEachRemaining(System.out::println);
  }

}
Maruthi
BMW
Benz
Creta
Nissan

Example: tryAdvance

tryAdvance() is another method in the Java spliterator that performs the action on the next element in the iteration. It combines the operation of hasNext() and next() in the Iterator interface. This method has a parameter action of the Consumer interface. The Consumer interface has an abstract accept method. Hence we use the lambda operation to implement this action.

In the below example, the action “print” is performed for every element in the spliterator. Since we have given this method within while loop, it prints all the elements in the spliterator.

import java.util.ArrayList;
import java.util.Spliterator;

public class SplitIteratorExample {

  public static void main(String[] args) {
    ArrayList<String> cars = new ArrayList<String>();
    cars.add("Maruthi");
    cars.add("BMW");
    cars.add("Benz");
    cars.add("Creta");
    cars.add("Nissan");
    
    Spliterator<String> s = cars.spliterator();
    while(s.tryAdvance((n) -> System.out.println(n)));
    
  }

}
Maruthi
BMW
Benz
Creta
Nissan

We can also print individual values of the spliterator based on our requirement as in the below example. Here we are printing only the first 2 values.

import java.util.ArrayList;
import java.util.Spliterator;

public class SplitIteratorExample {

  public static void main(String[] args) {
    ArrayList<String> cars = new ArrayList<String>();
    cars.add("Maruthi");
    cars.add("BMW");
    cars.add("Benz");
    cars.add("Creta");
    cars.add("Nissan");
    
    Spliterator<String> s = cars.spliterator();
    s.tryAdvance(a -> System.out.println("First Value: " + a));
    s.tryAdvance(a -> System.out.println("Second value: " + a));
    
  }

}
First Value: Maruthi
Second value: BMW

Example: trySplit

We can use the trySplit() method to split the spliterator into equal parts and then process them. We mainly use this to process a large amount of data in parallel. This is the main method of the Java spliterator that supports parallel processing.

In the below example, we use the trysplit() method to split the spliterator. Now the spliterator contains 2 parts, the first of length 3 and the second of length 2. Using forEachRemaining() method, we can print each element of both the split elements.

import java.util.ArrayList;
import java.util.Spliterator;

public class SpliteratorDemo {

  public static void main(String[] args) {
    ArrayList<String> cars = new ArrayList<String>();
    cars.add("Maruthi");
    cars.add("BMW");
    cars.add("Benz");
    cars.add("Creta");
    cars.add("Nissan");
    
    Spliterator<String> s1 = cars.spliterator();
    Spliterator<String> s2 = s1.trySplit();
    
    System.out.println("Number of elements in SplitList1: " + s1.getExactSizeIfKnown());
    System.out.println("Values in SplitList1: ");
    s1.forEachRemaining(System.out::println);

    System.out.println("*****************");
    
    System.out.println("Number of elements in SplitList2: " + s2.getExactSizeIfKnown());
    System.out.println("Values in SplitList2: ");
    s2.forEachRemaining(System.out::println);
    
  }

}
Number of elements in SplitList1: 3
Values in SplitList1: 
Benz
Creta
Nissan
*****************
Number of elements in SplitList2: 2
Values in SplitList2: 
Maruthi
BMW

Advantages of Java Spliterator

  • It supports parallel processing of iteration
  • It provides better performance

Difference between Iterator and Spliterator

Below are the differences between Java Iterator and Java spliterator.

IteratorSpliterator
Available from JDK 1.2Available from JDK 1.8
It is a universal iteratorIt is not a universal iterator
It does not support parallel processingIt supports parallel processing
It can be used as iterator for whole Collection APIIt can be used as iterator for Collection and Stream API except Map implementation classes.

Reference

Translate ยป