Monday 8 May 2023

Introduction to Spliterator interface in Java

Spliterator instance is used to traverse and partition the elements of a source. Array, Collection, IOChannel etc., come under spliterator source.

 

Example 1: Traverse the List elements using spliterator.

List<Integer> primesList = Arrays.asList(2, 3, 5, 7, 11);
primesList.spliterator().forEachRemaining(System.out::println);

Example 2: Partition the elements of spliterator.

'trySplit' method splits the current spliterator’s elements into two parts if possible and returns a new Spliterator object covering some portion of the elements, or null if this spliterator cannot be split.

 

SpliteratorPartition.java

package com.sample.app;

import java.util.Arrays;
import java.util.Spliterator;

public class SpliteratorPartition {

	public static void main(String[] args) {

		Spliterator<Integer> spliterator1 = Arrays.asList(2, 3, 5, 7, 11, 13).spliterator();
		Spliterator<Integer> spliterator2 = spliterator1.trySplit();

		System.out.println("Elements in spliterator 1");
		spliterator1.forEachRemaining(System.out::println);

		System.out.println("\nElements in spliterator 2");
		spliterator2.forEachRemaining(System.out::println);
	}

}

Output

Elements in spliterator 1
7
11
13

Elements in spliterator 2
2
3
5

As you see above output, spliterator1 is initially hold 6 elements (2, 3, 5, 7, 11, 13). After the split, spliterator1 holds (7, 11, 13) and spliterator 2 holds (2, 3, 5).

 

Spliterator traversal

You can traverse the spliterator in two ways.

a. Traverse individually using tryAdvance method

b. Traverse sequentially in bulk using forEachRemaining method

 

Traverse individually using tryAdvance method

while (spliterator1.tryAdvance(element -> System.out.println(element))) {}

 

Find the below working application.

 

SpliteratorTraverseOneByOne.java

package com.sample.app;

import java.util.Arrays;
import java.util.Spliterator;

public class SpliteratorTraverseOneByOne {

	public static void main(String[] args) {

		Spliterator<Integer> spliterator1 = Arrays.asList(2, 3, 5, 7, 11, 13).spliterator();

		while (spliterator1.tryAdvance(element -> System.out.println(element))) {
			
		}
			
	}

}

Output

2
3
5
7
11
13

Traverse sequentially in bulk using forEachRemaining method

Example

spliterator1.forEachRemaining(System.out::println);

SpliteratorTraverseInBulk.java

package com.sample.app;

import java.util.Arrays;
import java.util.Spliterator;

public class SpliteratorTraverseInBulk {
	
	public static void main(String[] args) {

		Spliterator<Integer> spliterator1 = Arrays.asList(2, 3, 5, 7, 11, 13).spliterator();

		spliterator1.forEachRemaining(System.out::println);

	}
}

Output

2
3
5
7
11
13

Split the data using trySplit method

'trySplit' method splits the current spliterator’s elements into two parts if possible and returns a new Spliterator object covering some portion of the elements, or null if this spliterator cannot be split. You can depict the same from below figure.




Find the below working application.

 

SpliteratorTrySplit.java


package com.sample.app;

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

public class SpliteratorTrySplit {

	private static List<Integer> nElements(int noOfElements) {
		List<Integer> result = new ArrayList<>();

		for (int i = 1; i < noOfElements + 1; i++) {
			result.add(i);
		}

		return result;

	}

	private static void printElements(Spliterator<?> spliterator, String message) {
		System.out.println(message);
		spliterator.forEachRemaining(ele -> System.out.print(ele + " "));
		System.out.println();
	}

	public static void main(String[] args) {
		List<Integer> list1 = nElements(16);

		Spliterator<Integer> spliterator1 = list1.spliterator();
		printElements(spliterator1, "spliterator1 elements");

		System.out.println("\nSplit the spliterator once");
		spliterator1 = list1.spliterator();
		Spliterator<Integer> spliterator2 = spliterator1.trySplit();
		printElements(spliterator1, "spliterator1 elements");
		printElements(spliterator2, "spliterator2 elements");

		System.out.println("\nSplit the spliterator1 twice and spliterator2 twice");
		spliterator1 = list1.spliterator();
		spliterator2 = spliterator1.trySplit();
		Spliterator<Integer> spliterator3 = spliterator1.trySplit();
		Spliterator<Integer> spliterator4 = spliterator2.trySplit();
		printElements(spliterator1, "spliterator1 elements");
		printElements(spliterator2, "spliterator2 elements");
		printElements(spliterator3, "spliterator3 elements");
		printElements(spliterator4, "spliterator4 elements");

	}

}

Output

spliterator1 elements
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 

Split the spliterator once
spliterator1 elements
9 10 11 12 13 14 15 16 
spliterator2 elements
1 2 3 4 5 6 7 8 

Split the spliterator1 twice and spliterator2 twice
spliterator1 elements
13 14 15 16 
spliterator2 elements
5 6 7 8 
spliterator3 elements
9 10 11 12 
spliterator4 elements
1 2 3 4

Spliterator Characteristics

A Spliterator reports a set of characteristics of its structure, source, and elements. Following table summarizes the characteristics of the spliterator.

 

Characteristic

Description

ORDERED

Iterate over the elements in order.

DISTINCT

For each pair of encountered elements x, y, !x.equals(y). This applies for example, to a Spliterator based on a Set.

SORTED

Characteristic value signifying that encounter order follows a defined sort order.

SIZED

Characteristic 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.

NONNULL

Characteristic value signifying that the source guarantees that encountered elements will not be null. (This applies, for example, to most concurrent collections, queues, and maps.)

IMMUTABLE

Characteristic 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. A Spliterator that does not report IMMUTABLE or CONCURRENT is expected to have a documented policy (for example throwing ConcurrentModificationException) concerning structural interference detected during traversal.

CONCURRENT

Characteristic value signifying that the element source may be safely concurrently modified (allowing additions, replacements, and/or removals) by multiple threads without external synchronization. If so, the Spliterator is expected to have a documented policy concerning the impact of modifications during traversal.

SUBSIZED

Characteristic value signifying that all Spliterators resulting from trySplit() will be both SIZED and SUBSIZED. This means that all child Spliterators, whether direct or indirect, will be SIZED.

 

 

Find the below working application to get the characteristics of a spliterator.

 

SpliteratorCharacterstics.java

package com.sample.app.streams;

import java.util.Arrays;
import java.util.List;
import java.util.Spliterator;

public class SpliteratorCharacterstics {

	public static void main(String[] args) {
		List<Integer> primesList = Arrays.asList(2, 3, 5, 7, 11);
		Spliterator<Integer> spliterator = primesList.spliterator();

		System.out.println("is ORDERED ? " + spliterator.hasCharacteristics(Spliterator.ORDERED));
		System.out.println("is DISTINCT ? " + spliterator.hasCharacteristics(Spliterator.DISTINCT));
		System.out.println("is SORTED ? " + spliterator.hasCharacteristics(Spliterator.SORTED));
		System.out.println("is SIZED ? " + spliterator.hasCharacteristics(Spliterator.SIZED));
		System.out.println("is NONNULL ? " + spliterator.hasCharacteristics(Spliterator.NONNULL));
		System.out.println("is IMMUTABLE ? " + spliterator.hasCharacteristics(Spliterator.IMMUTABLE));
		System.out.println("is CONCURRENT ? " + spliterator.hasCharacteristics(Spliterator.CONCURRENT));
		System.out.println("is SUBSIZED ? " + spliterator.hasCharacteristics(Spliterator.SUBSIZED));

	}

}

Output

is ORDERED ? true
is DISTINCT ? false
is SORTED ? false
is SIZED ? true
is NONNULL ? false
is IMMUTABLE ? false
is CONCURRENT ? false
is SUBSIZED ? true


 

Previous                                                 Next                                                 Home

No comments:

Post a Comment