Learnitweb

Spliterator in Java

1. Introduction

In this tutorial, we’ll discuss Spliterator interface. This is one of the items added in Java 8 for parallel processing.

The Spliterator interface was added in Java 8. Its name stands for “splitable iterator”. Spliterators, like Iterators, are for traversing the elements of a source. Spliterators can traverse the elements of a source in parallel. Java 8 provides a default Spliterator implementation for all data structures of Collections Framework. The Spliterator can work with an array, a Collection, an IO channel, or a generator function.

A Spliterator may traverse elements individually using method tryAdvance() or sequentially in bulk using method forEachRemaining(). However, one method trySplit() is of particular interest which may partition some of its elements as another Spliterator to do possible-parellel operations.

A Spliterator should, on a best-effort basis, throw ConcurrentModificationException if structural interference is detected after binding.

Spliterators can provide an estimate of the number of remaining elements via the estimateSize() method. Spliterators are commonly used in parallel processing of elements but spliterators are not expected to be thread-safe. So we have to ensure that the spliterator is only used by one thread at a time. The behaviour of splitting and traversal is undefined if two or more threads operate concurrently on the same spliterator. Primitive subtype specializations of Spliterator are provided for int, long, and double values, for example, Spliterator.OfInt.tryAdvance(java.util.function.IntConsumer).

2. Methods of Spliterator

  • int characteristics()
  • long estimateSize()
  • default void forEachRemaining(Consumer action)
  • default Comparator getComparator()
  • default long getExactSizeIfKnown()
  • default boolean hasCharacteristics(int characteristics)
  • boolean tryAdvance(Consumer action)
  • Spliterator trySplit()

3. The Spliterator characteristics

The Spliterator can be better controlled and its usage can be optimized by using characteristics. The int characteristics() method returns a set of characteristics of this Spliterator and its elements.

Following are the characteristics of the Spliterator interface:

static int CONCURRENTCharacteristic value signifying that the element source may be safely concurrently modified (allowing additions, replacements, and/or removals) by multiple threads without external synchronization.
static int DISTINCTCharacteristic value signifying that, for each pair of encountered elements x, y, !x.equals(y).
static int IMMUTABLECharacteristic value signifying that the element source cannot be structurally modified; that is, elements cannot be added, replaced, or removed, so such changes cannot occur during traversal.
static int NONNULLCharacteristic value signifying that the source guarantees that encountered elements will not be null.
static int ORDEREDCharacteristic value signifying that an encounter order is defined for elements.
static int SIZEDCharacteristic value signifying that the value returned from estimateSize() prior to traversal or splitting represents a finite size that, in the absence of structural source modification, represents an exact count of the number of elements that would be encountered by a complete traversal.
static int SORTEDCharacteristic value signifying that encounter order follows a defined sort order.
static int SUBSIZEDCharacteristic value signifying that all Spliterators resulting from trySplit() will be both SIZED and SUBSIZED.

3. Example of Spliterator

Following is an example of Spliterator:

ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
numbers.add(5);

// Create a Spliterator from the ArrayList
Spliterator<Integer> spliterator = numbers.spliterator();

// Process the first half of the elements
Spliterator<Integer> firstHalf = spliterator.trySplit();
firstHalf.forEachRemaining(System.out::println);

// Process the second half of the elements
Spliterator<Integer> secondHalf = spliterator;
secondHalf.forEachRemaining(System.out::println);

4. Conclusion

The Spliterator introduced in Java 8 is one of the key things to know in Java 8 which can help in parallel processing of elements of a collection. However, it is less popular feature but it is important for interview point of view.