/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package java.util;
import java.util.function.
Consumer;
import java.util.function.
DoubleConsumer;
import java.util.function.
IntConsumer;
import java.util.function.
LongConsumer;
/**
* Static classes and methods for operating on or creating instances of
* {@link Spliterator} and its primitive specializations
* {@link Spliterator.OfInt}, {@link Spliterator.OfLong}, and
* {@link Spliterator.OfDouble}.
*
* @see Spliterator
* @since 1.8
*/
public final class
Spliterators {
// Suppresses default constructor, ensuring non-instantiability.
private
Spliterators() {}
// Empty spliterators
/**
* Creates an empty {@code Spliterator}
*
* <p>The empty spliterator reports {@link Spliterator#SIZED} and
* {@link Spliterator#SUBSIZED}. Calls to
* {@link java.util.Spliterator#trySplit()} always return {@code null}.
*
* @param <T> Type of elements
* @return An empty spliterator
*/
@
SuppressWarnings("unchecked")
public static <T>
Spliterator<T>
emptySpliterator() {
return (
Spliterator<T>)
EMPTY_SPLITERATOR;
}
private static final
Spliterator<
Object>
EMPTY_SPLITERATOR =
new
EmptySpliterator.
OfRef<>();
/**
* Creates an empty {@code Spliterator.OfInt}
*
* <p>The empty spliterator reports {@link Spliterator#SIZED} and
* {@link Spliterator#SUBSIZED}. Calls to
* {@link java.util.Spliterator#trySplit()} always return {@code null}.
*
* @return An empty spliterator
*/
public static
Spliterator.
OfInt emptyIntSpliterator() {
return
EMPTY_INT_SPLITERATOR;
}
private static final
Spliterator.
OfInt EMPTY_INT_SPLITERATOR =
new
EmptySpliterator.
OfInt();
/**
* Creates an empty {@code Spliterator.OfLong}
*
* <p>The empty spliterator reports {@link Spliterator#SIZED} and
* {@link Spliterator#SUBSIZED}. Calls to
* {@link java.util.Spliterator#trySplit()} always return {@code null}.
*
* @return An empty spliterator
*/
public static
Spliterator.
OfLong emptyLongSpliterator() {
return
EMPTY_LONG_SPLITERATOR;
}
private static final
Spliterator.
OfLong EMPTY_LONG_SPLITERATOR =
new
EmptySpliterator.
OfLong();
/**
* Creates an empty {@code Spliterator.OfDouble}
*
* <p>The empty spliterator reports {@link Spliterator#SIZED} and
* {@link Spliterator#SUBSIZED}. Calls to
* {@link java.util.Spliterator#trySplit()} always return {@code null}.
*
* @return An empty spliterator
*/
public static
Spliterator.
OfDouble emptyDoubleSpliterator() {
return
EMPTY_DOUBLE_SPLITERATOR;
}
private static final
Spliterator.
OfDouble EMPTY_DOUBLE_SPLITERATOR =
new
EmptySpliterator.
OfDouble();
// Array-based spliterators
/**
* Creates a {@code Spliterator} covering the elements of a given array,
* using a customized set of spliterator characteristics.
*
* <p>This method is provided as an implementation convenience for
* Spliterators which store portions of their elements in arrays, and need
* fine control over Spliterator characteristics. Most other situations in
* which a Spliterator for an array is needed should use
* {@link Arrays#spliterator(Object[])}.
*
* <p>The returned spliterator always reports the characteristics
* {@code SIZED} and {@code SUBSIZED}. The caller may provide additional
* characteristics for the spliterator to report; it is common to
* additionally specify {@code IMMUTABLE} and {@code ORDERED}.
*
* @param <T> Type of elements
* @param array The array, assumed to be unmodified during use
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
* @return A spliterator for an array
* @throws NullPointerException if the given array is {@code null}
* @see Arrays#spliterator(Object[])
*/
public static <T>
Spliterator<T>
spliterator(
Object[]
array,
int
additionalCharacteristics) {
return new
ArraySpliterator<>(
Objects.
requireNonNull(
array),
additionalCharacteristics);
}
/**
* Creates a {@code Spliterator} covering a range of elements of a given
* array, using a customized set of spliterator characteristics.
*
* <p>This method is provided as an implementation convenience for
* Spliterators which store portions of their elements in arrays, and need
* fine control over Spliterator characteristics. Most other situations in
* which a Spliterator for an array is needed should use
* {@link Arrays#spliterator(Object[])}.
*
* <p>The returned spliterator always reports the characteristics
* {@code SIZED} and {@code SUBSIZED}. The caller may provide additional
* characteristics for the spliterator to report; it is common to
* additionally specify {@code IMMUTABLE} and {@code ORDERED}.
*
* @param <T> Type of elements
* @param array The array, assumed to be unmodified during use
* @param fromIndex The least index (inclusive) to cover
* @param toIndex One past the greatest index to cover
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
* @return A spliterator for an array
* @throws NullPointerException if the given array is {@code null}
* @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
* {@code toIndex} is less than {@code fromIndex}, or
* {@code toIndex} is greater than the array size
* @see Arrays#spliterator(Object[], int, int)
*/
public static <T>
Spliterator<T>
spliterator(
Object[]
array, int
fromIndex, int
toIndex,
int
additionalCharacteristics) {
checkFromToBounds(
Objects.
requireNonNull(
array).length,
fromIndex,
toIndex);
return new
ArraySpliterator<>(
array,
fromIndex,
toIndex,
additionalCharacteristics);
}
/**
* Creates a {@code Spliterator.OfInt} covering the elements of a given array,
* using a customized set of spliterator characteristics.
*
* <p>This method is provided as an implementation convenience for
* Spliterators which store portions of their elements in arrays, and need
* fine control over Spliterator characteristics. Most other situations in
* which a Spliterator for an array is needed should use
* {@link Arrays#spliterator(int[])}.
*
* <p>The returned spliterator always reports the characteristics
* {@code SIZED} and {@code SUBSIZED}. The caller may provide additional
* characteristics for the spliterator to report; it is common to
* additionally specify {@code IMMUTABLE} and {@code ORDERED}.
*
* @param array The array, assumed to be unmodified during use
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
* @return A spliterator for an array
* @throws NullPointerException if the given array is {@code null}
* @see Arrays#spliterator(int[])
*/
public static
Spliterator.
OfInt spliterator(int[]
array,
int
additionalCharacteristics) {
return new
IntArraySpliterator(
Objects.
requireNonNull(
array),
additionalCharacteristics);
}
/**
* Creates a {@code Spliterator.OfInt} covering a range of elements of a
* given array, using a customized set of spliterator characteristics.
*
* <p>This method is provided as an implementation convenience for
* Spliterators which store portions of their elements in arrays, and need
* fine control over Spliterator characteristics. Most other situations in
* which a Spliterator for an array is needed should use
* {@link Arrays#spliterator(int[], int, int)}.
*
* <p>The returned spliterator always reports the characteristics
* {@code SIZED} and {@code SUBSIZED}. The caller may provide additional
* characteristics for the spliterator to report; it is common to
* additionally specify {@code IMMUTABLE} and {@code ORDERED}.
*
* @param array The array, assumed to be unmodified during use
* @param fromIndex The least index (inclusive) to cover
* @param toIndex One past the greatest index to cover
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
* @return A spliterator for an array
* @throws NullPointerException if the given array is {@code null}
* @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
* {@code toIndex} is less than {@code fromIndex}, or
* {@code toIndex} is greater than the array size
* @see Arrays#spliterator(int[], int, int)
*/
public static
Spliterator.
OfInt spliterator(int[]
array, int
fromIndex, int
toIndex,
int
additionalCharacteristics) {
checkFromToBounds(
Objects.
requireNonNull(
array).length,
fromIndex,
toIndex);
return new
IntArraySpliterator(
array,
fromIndex,
toIndex,
additionalCharacteristics);
}
/**
* Creates a {@code Spliterator.OfLong} covering the elements of a given array,
* using a customized set of spliterator characteristics.
*
* <p>This method is provided as an implementation convenience for
* Spliterators which store portions of their elements in arrays, and need
* fine control over Spliterator characteristics. Most other situations in
* which a Spliterator for an array is needed should use
* {@link Arrays#spliterator(long[])}.
*
* <p>The returned spliterator always reports the characteristics
* {@code SIZED} and {@code SUBSIZED}. The caller may provide additional
* characteristics for the spliterator to report; it is common to
* additionally specify {@code IMMUTABLE} and {@code ORDERED}.
*
* @param array The array, assumed to be unmodified during use
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
* @return A spliterator for an array
* @throws NullPointerException if the given array is {@code null}
* @see Arrays#spliterator(long[])
*/
public static
Spliterator.
OfLong spliterator(long[]
array,
int
additionalCharacteristics) {
return new
LongArraySpliterator(
Objects.
requireNonNull(
array),
additionalCharacteristics);
}
/**
* Creates a {@code Spliterator.OfLong} covering a range of elements of a
* given array, using a customized set of spliterator characteristics.
*
* <p>This method is provided as an implementation convenience for
* Spliterators which store portions of their elements in arrays, and need
* fine control over Spliterator characteristics. Most other situations in
* which a Spliterator for an array is needed should use
* {@link Arrays#spliterator(long[], int, int)}.
*
* <p>The returned spliterator always reports the characteristics
* {@code SIZED} and {@code SUBSIZED}. The caller may provide additional
* characteristics for the spliterator to report. (For example, if it is
* known the array will not be further modified, specify {@code IMMUTABLE};
* if the array data is considered to have an an encounter order, specify
* {@code ORDERED}). The method {@link Arrays#spliterator(long[], int, int)} can
* often be used instead, which returns a spliterator that reports
* {@code SIZED}, {@code SUBSIZED}, {@code IMMUTABLE}, and {@code ORDERED}.
*
* @param array The array, assumed to be unmodified during use
* @param fromIndex The least index (inclusive) to cover
* @param toIndex One past the greatest index to cover
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
* @return A spliterator for an array
* @throws NullPointerException if the given array is {@code null}
* @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
* {@code toIndex} is less than {@code fromIndex}, or
* {@code toIndex} is greater than the array size
* @see Arrays#spliterator(long[], int, int)
*/
public static
Spliterator.
OfLong spliterator(long[]
array, int
fromIndex, int
toIndex,
int
additionalCharacteristics) {
checkFromToBounds(
Objects.
requireNonNull(
array).length,
fromIndex,
toIndex);
return new
LongArraySpliterator(
array,
fromIndex,
toIndex,
additionalCharacteristics);
}
/**
* Creates a {@code Spliterator.OfDouble} covering the elements of a given array,
* using a customized set of spliterator characteristics.
*
* <p>This method is provided as an implementation convenience for
* Spliterators which store portions of their elements in arrays, and need
* fine control over Spliterator characteristics. Most other situations in
* which a Spliterator for an array is needed should use
* {@link Arrays#spliterator(double[])}.
*
* <p>The returned spliterator always reports the characteristics
* {@code SIZED} and {@code SUBSIZED}. The caller may provide additional
* characteristics for the spliterator to report; it is common to
* additionally specify {@code IMMUTABLE} and {@code ORDERED}.
*
* @param array The array, assumed to be unmodified during use
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
* @return A spliterator for an array
* @throws NullPointerException if the given array is {@code null}
* @see Arrays#spliterator(double[])
*/
public static
Spliterator.
OfDouble spliterator(double[]
array,
int
additionalCharacteristics) {
return new
DoubleArraySpliterator(
Objects.
requireNonNull(
array),
additionalCharacteristics);
}
/**
* Creates a {@code Spliterator.OfDouble} covering a range of elements of a
* given array, using a customized set of spliterator characteristics.
*
* <p>This method is provided as an implementation convenience for
* Spliterators which store portions of their elements in arrays, and need
* fine control over Spliterator characteristics. Most other situations in
* which a Spliterator for an array is needed should use
* {@link Arrays#spliterator(double[], int, int)}.
*
* <p>The returned spliterator always reports the characteristics
* {@code SIZED} and {@code SUBSIZED}. The caller may provide additional
* characteristics for the spliterator to report. (For example, if it is
* known the array will not be further modified, specify {@code IMMUTABLE};
* if the array data is considered to have an an encounter order, specify
* {@code ORDERED}). The method {@link Arrays#spliterator(long[], int, int)} can
* often be used instead, which returns a spliterator that reports
* {@code SIZED}, {@code SUBSIZED}, {@code IMMUTABLE}, and {@code ORDERED}.
*
* @param array The array, assumed to be unmodified during use
* @param fromIndex The least index (inclusive) to cover
* @param toIndex One past the greatest index to cover
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
* @return A spliterator for an array
* @throws NullPointerException if the given array is {@code null}
* @throws ArrayIndexOutOfBoundsException if {@code fromIndex} is negative,
* {@code toIndex} is less than {@code fromIndex}, or
* {@code toIndex} is greater than the array size
* @see Arrays#spliterator(double[], int, int)
*/
public static
Spliterator.
OfDouble spliterator(double[]
array, int
fromIndex, int
toIndex,
int
additionalCharacteristics) {
checkFromToBounds(
Objects.
requireNonNull(
array).length,
fromIndex,
toIndex);
return new
DoubleArraySpliterator(
array,
fromIndex,
toIndex,
additionalCharacteristics);
}
/**
* Validate inclusive start index and exclusive end index against the length
* of an array.
* @param arrayLength The length of the array
* @param origin The inclusive start index
* @param fence The exclusive end index
* @throws ArrayIndexOutOfBoundsException if the start index is greater than
* the end index, if the start index is negative, or the end index is
* greater than the array length
*/
private static void
checkFromToBounds(int
arrayLength, int
origin, int
fence) {
if (
origin >
fence) {
throw new
ArrayIndexOutOfBoundsException(
"origin(" +
origin + ") > fence(" +
fence + ")");
}
if (
origin < 0) {
throw new
ArrayIndexOutOfBoundsException(
origin);
}
if (
fence >
arrayLength) {
throw new
ArrayIndexOutOfBoundsException(
fence);
}
}
// Iterator-based spliterators
/**
* Creates a {@code Spliterator} using the given collection's
* {@link java.util.Collection#iterator()} as the source of elements, and
* reporting its {@link java.util.Collection#size()} as its initial size.
*
* <p>The spliterator is
* <em><a href="Spliterator.html#binding">late-binding</a></em>, inherits
* the <em>fail-fast</em> properties of the collection's iterator, and
* implements {@code trySplit} to permit limited parallelism.
*
* @param <T> Type of elements
* @param c The collection
* @param characteristics Characteristics of this spliterator's source or
* elements. The characteristics {@code SIZED} and {@code SUBSIZED}
* are additionally reported unless {@code CONCURRENT} is supplied.
* @return A spliterator from an iterator
* @throws NullPointerException if the given collection is {@code null}
*/
public static <T>
Spliterator<T>
spliterator(
Collection<? extends T>
c,
int
characteristics) {
return new
IteratorSpliterator<>(
Objects.
requireNonNull(
c),
characteristics);
}
/**
* Creates a {@code Spliterator} using a given {@code Iterator}
* as the source of elements, and with a given initially reported size.
*
* <p>The spliterator is not
* <em><a href="Spliterator.html#binding">late-binding</a></em>, inherits
* the <em>fail-fast</em> properties of the iterator, and implements
* {@code trySplit} to permit limited parallelism.
*
* <p>Traversal of elements should be accomplished through the spliterator.
* The behaviour of splitting and traversal is undefined if the iterator is
* operated on after the spliterator is returned, or the initially reported
* size is not equal to the actual number of elements in the source.
*
* @param <T> Type of elements
* @param iterator The iterator for the source
* @param size The number of elements in the source, to be reported as
* initial {@code estimateSize}
* @param characteristics Characteristics of this spliterator's source or
* elements. The characteristics {@code SIZED} and {@code SUBSIZED}
* are additionally reported unless {@code CONCURRENT} is supplied.
* @return A spliterator from an iterator
* @throws NullPointerException if the given iterator is {@code null}
*/
public static <T>
Spliterator<T>
spliterator(
Iterator<? extends T>
iterator,
long
size,
int
characteristics) {
return new
IteratorSpliterator<>(
Objects.
requireNonNull(
iterator),
size,
characteristics);
}
/**
* Creates a {@code Spliterator} using a given {@code Iterator}
* as the source of elements, with no initial size estimate.
*
* <p>The spliterator is not
* <em><a href="Spliterator.html#binding">late-binding</a></em>, inherits
* the <em>fail-fast</em> properties of the iterator, and implements
* {@code trySplit} to permit limited parallelism.
*
* <p>Traversal of elements should be accomplished through the spliterator.
* The behaviour of splitting and traversal is undefined if the iterator is
* operated on after the spliterator is returned.
*
* @param <T> Type of elements
* @param iterator The iterator for the source
* @param characteristics Characteristics of this spliterator's source
* or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are
* ignored and are not reported.)
* @return A spliterator from an iterator
* @throws NullPointerException if the given iterator is {@code null}
*/
public static <T>
Spliterator<T>
spliteratorUnknownSize(
Iterator<? extends T>
iterator,
int
characteristics) {
return new
IteratorSpliterator<>(
Objects.
requireNonNull(
iterator),
characteristics);
}
/**
* Creates a {@code Spliterator.OfInt} using a given
* {@code IntStream.IntIterator} as the source of elements, and with a given
* initially reported size.
*
* <p>The spliterator is not
* <em><a href="Spliterator.html#binding">late-binding</a></em>, inherits
* the <em>fail-fast</em> properties of the iterator, and implements
* {@code trySplit} to permit limited parallelism.
*
* <p>Traversal of elements should be accomplished through the spliterator.
* The behaviour of splitting and traversal is undefined if the iterator is
* operated on after the spliterator is returned, or the initially reported
* size is not equal to the actual number of elements in the source.
*
* @param iterator The iterator for the source
* @param size The number of elements in the source, to be reported as
* initial {@code estimateSize}.
* @param characteristics Characteristics of this spliterator's source or
* elements. The characteristics {@code SIZED} and {@code SUBSIZED}
* are additionally reported unless {@code CONCURRENT} is supplied.
* @return A spliterator from an iterator
* @throws NullPointerException if the given iterator is {@code null}
*/
public static
Spliterator.
OfInt spliterator(
PrimitiveIterator.
OfInt iterator,
long
size,
int
characteristics) {
return new
IntIteratorSpliterator(
Objects.
requireNonNull(
iterator),
size,
characteristics);
}
/**
* Creates a {@code Spliterator.OfInt} using a given
* {@code IntStream.IntIterator} as the source of elements, with no initial
* size estimate.
*
* <p>The spliterator is not
* <em><a href="Spliterator.html#binding">late-binding</a></em>, inherits
* the <em>fail-fast</em> properties of the iterator, and implements
* {@code trySplit} to permit limited parallelism.
*
* <p>Traversal of elements should be accomplished through the spliterator.
* The behaviour of splitting and traversal is undefined if the iterator is
* operated on after the spliterator is returned.
*
* @param iterator The iterator for the source
* @param characteristics Characteristics of this spliterator's source
* or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are
* ignored and are not reported.)
* @return A spliterator from an iterator
* @throws NullPointerException if the given iterator is {@code null}
*/
public static
Spliterator.
OfInt spliteratorUnknownSize(
PrimitiveIterator.
OfInt iterator,
int
characteristics) {
return new
IntIteratorSpliterator(
Objects.
requireNonNull(
iterator),
characteristics);
}
/**
* Creates a {@code Spliterator.OfLong} using a given
* {@code LongStream.LongIterator} as the source of elements, and with a
* given initially reported size.
*
* <p>The spliterator is not
* <em><a href="Spliterator.html#binding">late-binding</a></em>, inherits
* the <em>fail-fast</em> properties of the iterator, and implements
* {@code trySplit} to permit limited parallelism.
*
* <p>Traversal of elements should be accomplished through the spliterator.
* The behaviour of splitting and traversal is undefined if the iterator is
* operated on after the spliterator is returned, or the initially reported
* size is not equal to the actual number of elements in the source.
*
* @param iterator The iterator for the source
* @param size The number of elements in the source, to be reported as
* initial {@code estimateSize}.
* @param characteristics Characteristics of this spliterator's source or
* elements. The characteristics {@code SIZED} and {@code SUBSIZED}
* are additionally reported unless {@code CONCURRENT} is supplied.
* @return A spliterator from an iterator
* @throws NullPointerException if the given iterator is {@code null}
*/
public static
Spliterator.
OfLong spliterator(
PrimitiveIterator.
OfLong iterator,
long
size,
int
characteristics) {
return new
LongIteratorSpliterator(
Objects.
requireNonNull(
iterator),
size,
characteristics);
}
/**
* Creates a {@code Spliterator.OfLong} using a given
* {@code LongStream.LongIterator} as the source of elements, with no
* initial size estimate.
*
* <p>The spliterator is not
* <em><a href="Spliterator.html#binding">late-binding</a></em>, inherits
* the <em>fail-fast</em> properties of the iterator, and implements
* {@code trySplit} to permit limited parallelism.
*
* <p>Traversal of elements should be accomplished through the spliterator.
* The behaviour of splitting and traversal is undefined if the iterator is
* operated on after the spliterator is returned.
*
* @param iterator The iterator for the source
* @param characteristics Characteristics of this spliterator's source
* or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are
* ignored and are not reported.)
* @return A spliterator from an iterator
* @throws NullPointerException if the given iterator is {@code null}
*/
public static
Spliterator.
OfLong spliteratorUnknownSize(
PrimitiveIterator.
OfLong iterator,
int
characteristics) {
return new
LongIteratorSpliterator(
Objects.
requireNonNull(
iterator),
characteristics);
}
/**
* Creates a {@code Spliterator.OfDouble} using a given
* {@code DoubleStream.DoubleIterator} as the source of elements, and with a
* given initially reported size.
*
* <p>The spliterator is not
* <em><a href="Spliterator.html#binding">late-binding</a></em>, inherits
* the <em>fail-fast</em> properties of the iterator, and implements
* {@code trySplit} to permit limited parallelism.
*
* <p>Traversal of elements should be accomplished through the spliterator.
* The behaviour of splitting and traversal is undefined if the iterator is
* operated on after the spliterator is returned, or the initially reported
* size is not equal to the actual number of elements in the source.
*
* @param iterator The iterator for the source
* @param size The number of elements in the source, to be reported as
* initial {@code estimateSize}
* @param characteristics Characteristics of this spliterator's source or
* elements. The characteristics {@code SIZED} and {@code SUBSIZED}
* are additionally reported unless {@code CONCURRENT} is supplied.
* @return A spliterator from an iterator
* @throws NullPointerException if the given iterator is {@code null}
*/
public static
Spliterator.
OfDouble spliterator(
PrimitiveIterator.
OfDouble iterator,
long
size,
int
characteristics) {
return new
DoubleIteratorSpliterator(
Objects.
requireNonNull(
iterator),
size,
characteristics);
}
/**
* Creates a {@code Spliterator.OfDouble} using a given
* {@code DoubleStream.DoubleIterator} as the source of elements, with no
* initial size estimate.
*
* <p>The spliterator is not
* <em><a href="Spliterator.html#binding">late-binding</a></em>, inherits
* the <em>fail-fast</em> properties of the iterator, and implements
* {@code trySplit} to permit limited parallelism.
*
* <p>Traversal of elements should be accomplished through the spliterator.
* The behaviour of splitting and traversal is undefined if the iterator is
* operated on after the spliterator is returned.
*
* @param iterator The iterator for the source
* @param characteristics Characteristics of this spliterator's source
* or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are
* ignored and are not reported.)
* @return A spliterator from an iterator
* @throws NullPointerException if the given iterator is {@code null}
*/
public static
Spliterator.
OfDouble spliteratorUnknownSize(
PrimitiveIterator.
OfDouble iterator,
int
characteristics) {
return new
DoubleIteratorSpliterator(
Objects.
requireNonNull(
iterator),
characteristics);
}
// Iterators from Spliterators
/**
* Creates an {@code Iterator} from a {@code Spliterator}.
*
* <p>Traversal of elements should be accomplished through the iterator.
* The behaviour of traversal is undefined if the spliterator is operated
* after the iterator is returned.
*
* @param <T> Type of elements
* @param spliterator The spliterator
* @return An iterator
* @throws NullPointerException if the given spliterator is {@code null}
*/
public static<T>
Iterator<T>
iterator(
Spliterator<? extends T>
spliterator) {
Objects.
requireNonNull(
spliterator);
class
Adapter implements
Iterator<T>,
Consumer<T> {
boolean
valueReady = false;
T
nextElement;
@
Override
public void
accept(T
t) {
valueReady = true;
nextElement =
t;
}
@
Override
public boolean
hasNext() {
if (!
valueReady)
spliterator.
tryAdvance(this);
return
valueReady;
}
@
Override
public T
next() {
if (!
valueReady && !
hasNext())
throw new
NoSuchElementException();
else {
valueReady = false;
return
nextElement;
}
}
}
return new
Adapter();
}
/**
* Creates an {@code PrimitiveIterator.OfInt} from a
* {@code Spliterator.OfInt}.
*
* <p>Traversal of elements should be accomplished through the iterator.
* The behaviour of traversal is undefined if the spliterator is operated
* after the iterator is returned.
*
* @param spliterator The spliterator
* @return An iterator
* @throws NullPointerException if the given spliterator is {@code null}
*/
public static
PrimitiveIterator.
OfInt iterator(
Spliterator.
OfInt spliterator) {
Objects.
requireNonNull(
spliterator);
class
Adapter implements
PrimitiveIterator.
OfInt,
IntConsumer {
boolean
valueReady = false;
int
nextElement;
@
Override
public void
accept(int
t) {
valueReady = true;
nextElement =
t;
}
@
Override
public boolean
hasNext() {
if (!
valueReady)
spliterator.
tryAdvance(this);
return
valueReady;
}
@
Override
public int
nextInt() {
if (!
valueReady && !
hasNext())
throw new
NoSuchElementException();
else {
valueReady = false;
return
nextElement;
}
}
}
return new
Adapter();
}
/**
* Creates an {@code PrimitiveIterator.OfLong} from a
* {@code Spliterator.OfLong}.
*
* <p>Traversal of elements should be accomplished through the iterator.
* The behaviour of traversal is undefined if the spliterator is operated
* after the iterator is returned.
*
* @param spliterator The spliterator
* @return An iterator
* @throws NullPointerException if the given spliterator is {@code null}
*/
public static
PrimitiveIterator.
OfLong iterator(
Spliterator.
OfLong spliterator) {
Objects.
requireNonNull(
spliterator);
class
Adapter implements
PrimitiveIterator.
OfLong,
LongConsumer {
boolean
valueReady = false;
long
nextElement;
@
Override
public void
accept(long
t) {
valueReady = true;
nextElement =
t;
}
@
Override
public boolean
hasNext() {
if (!
valueReady)
spliterator.
tryAdvance(this);
return
valueReady;
}
@
Override
public long
nextLong() {
if (!
valueReady && !
hasNext())
throw new
NoSuchElementException();
else {
valueReady = false;
return
nextElement;
}
}
}
return new
Adapter();
}
/**
* Creates an {@code PrimitiveIterator.OfDouble} from a
* {@code Spliterator.OfDouble}.
*
* <p>Traversal of elements should be accomplished through the iterator.
* The behaviour of traversal is undefined if the spliterator is operated
* after the iterator is returned.
*
* @param spliterator The spliterator
* @return An iterator
* @throws NullPointerException if the given spliterator is {@code null}
*/
public static
PrimitiveIterator.
OfDouble iterator(
Spliterator.
OfDouble spliterator) {
Objects.
requireNonNull(
spliterator);
class
Adapter implements
PrimitiveIterator.
OfDouble,
DoubleConsumer {
boolean
valueReady = false;
double
nextElement;
@
Override
public void
accept(double
t) {
valueReady = true;
nextElement =
t;
}
@
Override
public boolean
hasNext() {
if (!
valueReady)
spliterator.
tryAdvance(this);
return
valueReady;
}
@
Override
public double
nextDouble() {
if (!
valueReady && !
hasNext())
throw new
NoSuchElementException();
else {
valueReady = false;
return
nextElement;
}
}
}
return new
Adapter();
}
// Implementations
private static abstract class
EmptySpliterator<T, S extends
Spliterator<T>, C> {
EmptySpliterator() { }
public S
trySplit() {
return null;
}
public boolean
tryAdvance(C
consumer) {
Objects.
requireNonNull(
consumer);
return false;
}
public void
forEachRemaining(C
consumer) {
Objects.
requireNonNull(
consumer);
}
public long
estimateSize() {
return 0;
}
public int
characteristics() {
return
Spliterator.
SIZED |
Spliterator.
SUBSIZED;
}
private static final class
OfRef<T>
extends
EmptySpliterator<T,
Spliterator<T>,
Consumer<? super T>>
implements
Spliterator<T> {
OfRef() { }
}
private static final class
OfInt
extends
EmptySpliterator<
Integer,
Spliterator.
OfInt,
IntConsumer>
implements
Spliterator.
OfInt {
OfInt() { }
}
private static final class
OfLong
extends
EmptySpliterator<
Long,
Spliterator.
OfLong,
LongConsumer>
implements
Spliterator.
OfLong {
OfLong() { }
}
private static final class
OfDouble
extends
EmptySpliterator<
Double,
Spliterator.
OfDouble,
DoubleConsumer>
implements
Spliterator.
OfDouble {
OfDouble() { }
}
}
// Array-based spliterators
/**
* A Spliterator designed for use by sources that traverse and split
* elements maintained in an unmodifiable {@code Object[]} array.
*/
static final class
ArraySpliterator<T> implements
Spliterator<T> {
/**
* The array, explicitly typed as Object[]. Unlike in some other
* classes (see for example CR 6260652), we do not need to
* screen arguments to ensure they are exactly of type Object[]
* so long as no methods write into the array or serialize it,
* which we ensure here by defining this class as final.
*/
private final
Object[]
array;
private int
index; // current index, modified on advance/split
private final int
fence; // one past last index
private final int
characteristics;
/**
* Creates a spliterator covering all of the given array.
* @param array the array, assumed to be unmodified during use
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
*/
public
ArraySpliterator(
Object[]
array, int
additionalCharacteristics) {
this(
array, 0,
array.length,
additionalCharacteristics);
}
/**
* Creates a spliterator covering the given array and range
* @param array the array, assumed to be unmodified during use
* @param origin the least index (inclusive) to cover
* @param fence one past the greatest index to cover
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
*/
public
ArraySpliterator(
Object[]
array, int
origin, int
fence, int
additionalCharacteristics) {
this.
array =
array;
this.
index =
origin;
this.
fence =
fence;
this.
characteristics =
additionalCharacteristics |
Spliterator.
SIZED |
Spliterator.
SUBSIZED;
}
@
Override
public
Spliterator<T>
trySplit() {
int
lo =
index,
mid = (
lo +
fence) >>> 1;
return (
lo >=
mid)
? null
: new
ArraySpliterator<>(
array,
lo,
index =
mid,
characteristics);
}
@
SuppressWarnings("unchecked")
@
Override
public void
forEachRemaining(
Consumer<? super T>
action) {
Object[]
a; int
i,
hi; // hoist accesses and checks from loop
if (
action == null)
throw new
NullPointerException();
if ((
a =
array).length >= (
hi =
fence) &&
(
i =
index) >= 0 &&
i < (
index =
hi)) {
do {
action.
accept((T)
a[
i]); } while (++
i <
hi);
}
}
@
Override
public boolean
tryAdvance(
Consumer<? super T>
action) {
if (
action == null)
throw new
NullPointerException();
if (
index >= 0 &&
index <
fence) {
@
SuppressWarnings("unchecked") T
e = (T)
array[
index++];
action.
accept(
e);
return true;
}
return false;
}
@
Override
public long
estimateSize() { return (long)(
fence -
index); }
@
Override
public int
characteristics() {
return
characteristics;
}
@
Override
public
Comparator<? super T>
getComparator() {
if (
hasCharacteristics(
Spliterator.
SORTED))
return null;
throw new
IllegalStateException();
}
}
/**
* A Spliterator.OfInt designed for use by sources that traverse and split
* elements maintained in an unmodifiable {@code int[]} array.
*/
static final class
IntArraySpliterator implements
Spliterator.
OfInt {
private final int[]
array;
private int
index; // current index, modified on advance/split
private final int
fence; // one past last index
private final int
characteristics;
/**
* Creates a spliterator covering all of the given array.
* @param array the array, assumed to be unmodified during use
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
*/
public
IntArraySpliterator(int[]
array, int
additionalCharacteristics) {
this(
array, 0,
array.length,
additionalCharacteristics);
}
/**
* Creates a spliterator covering the given array and range
* @param array the array, assumed to be unmodified during use
* @param origin the least index (inclusive) to cover
* @param fence one past the greatest index to cover
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
*/
public
IntArraySpliterator(int[]
array, int
origin, int
fence, int
additionalCharacteristics) {
this.
array =
array;
this.
index =
origin;
this.
fence =
fence;
this.
characteristics =
additionalCharacteristics |
Spliterator.
SIZED |
Spliterator.
SUBSIZED;
}
@
Override
public
OfInt trySplit() {
int
lo =
index,
mid = (
lo +
fence) >>> 1;
return (
lo >=
mid)
? null
: new
IntArraySpliterator(
array,
lo,
index =
mid,
characteristics);
}
@
Override
public void
forEachRemaining(
IntConsumer action) {
int[]
a; int
i,
hi; // hoist accesses and checks from loop
if (
action == null)
throw new
NullPointerException();
if ((
a =
array).length >= (
hi =
fence) &&
(
i =
index) >= 0 &&
i < (
index =
hi)) {
do {
action.
accept(
a[
i]); } while (++
i <
hi);
}
}
@
Override
public boolean
tryAdvance(
IntConsumer action) {
if (
action == null)
throw new
NullPointerException();
if (
index >= 0 &&
index <
fence) {
action.
accept(
array[
index++]);
return true;
}
return false;
}
@
Override
public long
estimateSize() { return (long)(
fence -
index); }
@
Override
public int
characteristics() {
return
characteristics;
}
@
Override
public
Comparator<? super
Integer>
getComparator() {
if (
hasCharacteristics(
Spliterator.
SORTED))
return null;
throw new
IllegalStateException();
}
}
/**
* A Spliterator.OfLong designed for use by sources that traverse and split
* elements maintained in an unmodifiable {@code int[]} array.
*/
static final class
LongArraySpliterator implements
Spliterator.
OfLong {
private final long[]
array;
private int
index; // current index, modified on advance/split
private final int
fence; // one past last index
private final int
characteristics;
/**
* Creates a spliterator covering all of the given array.
* @param array the array, assumed to be unmodified during use
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
*/
public
LongArraySpliterator(long[]
array, int
additionalCharacteristics) {
this(
array, 0,
array.length,
additionalCharacteristics);
}
/**
* Creates a spliterator covering the given array and range
* @param array the array, assumed to be unmodified during use
* @param origin the least index (inclusive) to cover
* @param fence one past the greatest index to cover
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
*/
public
LongArraySpliterator(long[]
array, int
origin, int
fence, int
additionalCharacteristics) {
this.
array =
array;
this.
index =
origin;
this.
fence =
fence;
this.
characteristics =
additionalCharacteristics |
Spliterator.
SIZED |
Spliterator.
SUBSIZED;
}
@
Override
public
OfLong trySplit() {
int
lo =
index,
mid = (
lo +
fence) >>> 1;
return (
lo >=
mid)
? null
: new
LongArraySpliterator(
array,
lo,
index =
mid,
characteristics);
}
@
Override
public void
forEachRemaining(
LongConsumer action) {
long[]
a; int
i,
hi; // hoist accesses and checks from loop
if (
action == null)
throw new
NullPointerException();
if ((
a =
array).length >= (
hi =
fence) &&
(
i =
index) >= 0 &&
i < (
index =
hi)) {
do {
action.
accept(
a[
i]); } while (++
i <
hi);
}
}
@
Override
public boolean
tryAdvance(
LongConsumer action) {
if (
action == null)
throw new
NullPointerException();
if (
index >= 0 &&
index <
fence) {
action.
accept(
array[
index++]);
return true;
}
return false;
}
@
Override
public long
estimateSize() { return (long)(
fence -
index); }
@
Override
public int
characteristics() {
return
characteristics;
}
@
Override
public
Comparator<? super
Long>
getComparator() {
if (
hasCharacteristics(
Spliterator.
SORTED))
return null;
throw new
IllegalStateException();
}
}
/**
* A Spliterator.OfDouble designed for use by sources that traverse and split
* elements maintained in an unmodifiable {@code int[]} array.
*/
static final class
DoubleArraySpliterator implements
Spliterator.
OfDouble {
private final double[]
array;
private int
index; // current index, modified on advance/split
private final int
fence; // one past last index
private final int
characteristics;
/**
* Creates a spliterator covering all of the given array.
* @param array the array, assumed to be unmodified during use
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
*/
public
DoubleArraySpliterator(double[]
array, int
additionalCharacteristics) {
this(
array, 0,
array.length,
additionalCharacteristics);
}
/**
* Creates a spliterator covering the given array and range
* @param array the array, assumed to be unmodified during use
* @param origin the least index (inclusive) to cover
* @param fence one past the greatest index to cover
* @param additionalCharacteristics Additional spliterator characteristics
* of this spliterator's source or elements beyond {@code SIZED} and
* {@code SUBSIZED} which are are always reported
*/
public
DoubleArraySpliterator(double[]
array, int
origin, int
fence, int
additionalCharacteristics) {
this.
array =
array;
this.
index =
origin;
this.
fence =
fence;
this.
characteristics =
additionalCharacteristics |
Spliterator.
SIZED |
Spliterator.
SUBSIZED;
}
@
Override
public
OfDouble trySplit() {
int
lo =
index,
mid = (
lo +
fence) >>> 1;
return (
lo >=
mid)
? null
: new
DoubleArraySpliterator(
array,
lo,
index =
mid,
characteristics);
}
@
Override
public void
forEachRemaining(
DoubleConsumer action) {
double[]
a; int
i,
hi; // hoist accesses and checks from loop
if (
action == null)
throw new
NullPointerException();
if ((
a =
array).length >= (
hi =
fence) &&
(
i =
index) >= 0 &&
i < (
index =
hi)) {
do {
action.
accept(
a[
i]); } while (++
i <
hi);
}
}
@
Override
public boolean
tryAdvance(
DoubleConsumer action) {
if (
action == null)
throw new
NullPointerException();
if (
index >= 0 &&
index <
fence) {
action.
accept(
array[
index++]);
return true;
}
return false;
}
@
Override
public long
estimateSize() { return (long)(
fence -
index); }
@
Override
public int
characteristics() {
return
characteristics;
}
@
Override
public
Comparator<? super
Double>
getComparator() {
if (
hasCharacteristics(
Spliterator.
SORTED))
return null;
throw new
IllegalStateException();
}
}
//
/**
* An abstract {@code Spliterator} that implements {@code trySplit} to
* permit limited parallelism.
*
* <p>An extending class need only
* implement {@link #tryAdvance(java.util.function.Consumer) tryAdvance}.
* The extending class should override
* {@link #forEachRemaining(java.util.function.Consumer) forEach} if it can
* provide a more performant implementation.
*
* @apiNote
* This class is a useful aid for creating a spliterator when it is not
* possible or difficult to efficiently partition elements in a manner
* allowing balanced parallel computation.
*
* <p>An alternative to using this class, that also permits limited
* parallelism, is to create a spliterator from an iterator
* (see {@link #spliterator(Iterator, long, int)}. Depending on the
* circumstances using an iterator may be easier or more convenient than
* extending this class, such as when there is already an iterator
* available to use.
*
* @see #spliterator(Iterator, long, int)
* @since 1.8
*/
public static abstract class
AbstractSpliterator<T> implements
Spliterator<T> {
static final int
BATCH_UNIT = 1 << 10; // batch array size increment
static final int
MAX_BATCH = 1 << 25; // max batch array size;
private final int
characteristics;
private long
est; // size estimate
private int
batch; // batch size for splits
/**
* Creates a spliterator reporting the given estimated size and
* additionalCharacteristics.
*
* @param est the estimated size of this spliterator if known, otherwise
* {@code Long.MAX_VALUE}.
* @param additionalCharacteristics properties of this spliterator's
* source or elements. If {@code SIZED} is reported then this
* spliterator will additionally report {@code SUBSIZED}.
*/
protected
AbstractSpliterator(long
est, int
additionalCharacteristics) {
this.
est =
est;
this.
characteristics = ((
additionalCharacteristics &
Spliterator.
SIZED) != 0)
?
additionalCharacteristics |
Spliterator.
SUBSIZED
:
additionalCharacteristics;
}
static final class
HoldingConsumer<T> implements
Consumer<T> {
Object value;
@
Override
public void
accept(T
value) {
this.
value =
value;
}
}
/**
* {@inheritDoc}
*
* This implementation permits limited parallelism.
*/
@
Override
public
Spliterator<T>
trySplit() {
/*
* Split into arrays of arithmetically increasing batch
* sizes. This will only improve parallel performance if
* per-element Consumer actions are more costly than
* transferring them into an array. The use of an
* arithmetic progression in split sizes provides overhead
* vs parallelism bounds that do not particularly favor or
* penalize cases of lightweight vs heavyweight element
* operations, across combinations of #elements vs #cores,
* whether or not either are known. We generate
* O(sqrt(#elements)) splits, allowing O(sqrt(#cores))
* potential speedup.
*/
HoldingConsumer<T>
holder = new
HoldingConsumer<>();
long
s =
est;
if (
s > 1 &&
tryAdvance(
holder)) {
int
n =
batch +
BATCH_UNIT;
if (
n >
s)
n = (int)
s;
if (
n >
MAX_BATCH)
n =
MAX_BATCH;
Object[]
a = new
Object[
n];
int
j = 0;
do {
a[
j] =
holder.
value; } while (++
j <
n &&
tryAdvance(
holder));
batch =
j;
if (
est !=
Long.
MAX_VALUE)
est -=
j;
return new
ArraySpliterator<>(
a, 0,
j,
characteristics());
}
return null;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns the estimated size as reported when
* created and, if the estimate size is known, decreases in size when
* split.
*/
@
Override
public long
estimateSize() {
return
est;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns the characteristics as reported when
* created.
*/
@
Override
public int
characteristics() {
return
characteristics;
}
}
/**
* An abstract {@code Spliterator.OfInt} that implements {@code trySplit} to
* permit limited parallelism.
*
* <p>To implement a spliterator an extending class need only
* implement {@link #tryAdvance(java.util.function.IntConsumer)}
* tryAdvance}. The extending class should override
* {@link #forEachRemaining(java.util.function.IntConsumer)} forEach} if it
* can provide a more performant implementation.
*
* @apiNote
* This class is a useful aid for creating a spliterator when it is not
* possible or difficult to efficiently partition elements in a manner
* allowing balanced parallel computation.
*
* <p>An alternative to using this class, that also permits limited
* parallelism, is to create a spliterator from an iterator
* (see {@link #spliterator(java.util.PrimitiveIterator.OfInt, long, int)}.
* Depending on the circumstances using an iterator may be easier or more
* convenient than extending this class. For example, if there is already an
* iterator available to use then there is no need to extend this class.
*
* @see #spliterator(java.util.PrimitiveIterator.OfInt, long, int)
* @since 1.8
*/
public static abstract class
AbstractIntSpliterator implements
Spliterator.
OfInt {
static final int
MAX_BATCH =
AbstractSpliterator.
MAX_BATCH;
static final int
BATCH_UNIT =
AbstractSpliterator.
BATCH_UNIT;
private final int
characteristics;
private long
est; // size estimate
private int
batch; // batch size for splits
/**
* Creates a spliterator reporting the given estimated size and
* characteristics.
*
* @param est the estimated size of this spliterator if known, otherwise
* {@code Long.MAX_VALUE}.
* @param additionalCharacteristics properties of this spliterator's
* source or elements. If {@code SIZED} is reported then this
* spliterator will additionally report {@code SUBSIZED}.
*/
protected
AbstractIntSpliterator(long
est, int
additionalCharacteristics) {
this.
est =
est;
this.
characteristics = ((
additionalCharacteristics &
Spliterator.
SIZED) != 0)
?
additionalCharacteristics |
Spliterator.
SUBSIZED
:
additionalCharacteristics;
}
static final class
HoldingIntConsumer implements
IntConsumer {
int
value;
@
Override
public void
accept(int
value) {
this.
value =
value;
}
}
/**
* {@inheritDoc}
*
* This implementation permits limited parallelism.
*/
@
Override
public
Spliterator.
OfInt trySplit() {
HoldingIntConsumer holder = new
HoldingIntConsumer();
long
s =
est;
if (
s > 1 &&
tryAdvance(
holder)) {
int
n =
batch +
BATCH_UNIT;
if (
n >
s)
n = (int)
s;
if (
n >
MAX_BATCH)
n =
MAX_BATCH;
int[]
a = new int[
n];
int
j = 0;
do {
a[
j] =
holder.
value; } while (++
j <
n &&
tryAdvance(
holder));
batch =
j;
if (
est !=
Long.
MAX_VALUE)
est -=
j;
return new
IntArraySpliterator(
a, 0,
j,
characteristics());
}
return null;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns the estimated size as reported when
* created and, if the estimate size is known, decreases in size when
* split.
*/
@
Override
public long
estimateSize() {
return
est;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns the characteristics as reported when
* created.
*/
@
Override
public int
characteristics() {
return
characteristics;
}
}
/**
* An abstract {@code Spliterator.OfLong} that implements {@code trySplit}
* to permit limited parallelism.
*
* <p>To implement a spliterator an extending class need only
* implement {@link #tryAdvance(java.util.function.LongConsumer)}
* tryAdvance}. The extending class should override
* {@link #forEachRemaining(java.util.function.LongConsumer)} forEach} if it
* can provide a more performant implementation.
*
* @apiNote
* This class is a useful aid for creating a spliterator when it is not
* possible or difficult to efficiently partition elements in a manner
* allowing balanced parallel computation.
*
* <p>An alternative to using this class, that also permits limited
* parallelism, is to create a spliterator from an iterator
* (see {@link #spliterator(java.util.PrimitiveIterator.OfLong, long, int)}.
* Depending on the circumstances using an iterator may be easier or more
* convenient than extending this class. For example, if there is already an
* iterator available to use then there is no need to extend this class.
*
* @see #spliterator(java.util.PrimitiveIterator.OfLong, long, int)
* @since 1.8
*/
public static abstract class
AbstractLongSpliterator implements
Spliterator.
OfLong {
static final int
MAX_BATCH =
AbstractSpliterator.
MAX_BATCH;
static final int
BATCH_UNIT =
AbstractSpliterator.
BATCH_UNIT;
private final int
characteristics;
private long
est; // size estimate
private int
batch; // batch size for splits
/**
* Creates a spliterator reporting the given estimated size and
* characteristics.
*
* @param est the estimated size of this spliterator if known, otherwise
* {@code Long.MAX_VALUE}.
* @param additionalCharacteristics properties of this spliterator's
* source or elements. If {@code SIZED} is reported then this
* spliterator will additionally report {@code SUBSIZED}.
*/
protected
AbstractLongSpliterator(long
est, int
additionalCharacteristics) {
this.
est =
est;
this.
characteristics = ((
additionalCharacteristics &
Spliterator.
SIZED) != 0)
?
additionalCharacteristics |
Spliterator.
SUBSIZED
:
additionalCharacteristics;
}
static final class
HoldingLongConsumer implements
LongConsumer {
long
value;
@
Override
public void
accept(long
value) {
this.
value =
value;
}
}
/**
* {@inheritDoc}
*
* This implementation permits limited parallelism.
*/
@
Override
public
Spliterator.
OfLong trySplit() {
HoldingLongConsumer holder = new
HoldingLongConsumer();
long
s =
est;
if (
s > 1 &&
tryAdvance(
holder)) {
int
n =
batch +
BATCH_UNIT;
if (
n >
s)
n = (int)
s;
if (
n >
MAX_BATCH)
n =
MAX_BATCH;
long[]
a = new long[
n];
int
j = 0;
do {
a[
j] =
holder.
value; } while (++
j <
n &&
tryAdvance(
holder));
batch =
j;
if (
est !=
Long.
MAX_VALUE)
est -=
j;
return new
LongArraySpliterator(
a, 0,
j,
characteristics());
}
return null;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns the estimated size as reported when
* created and, if the estimate size is known, decreases in size when
* split.
*/
@
Override
public long
estimateSize() {
return
est;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns the characteristics as reported when
* created.
*/
@
Override
public int
characteristics() {
return
characteristics;
}
}
/**
* An abstract {@code Spliterator.OfDouble} that implements
* {@code trySplit} to permit limited parallelism.
*
* <p>To implement a spliterator an extending class need only
* implement {@link #tryAdvance(java.util.function.DoubleConsumer)}
* tryAdvance}. The extending class should override
* {@link #forEachRemaining(java.util.function.DoubleConsumer)} forEach} if
* it can provide a more performant implementation.
*
* @apiNote
* This class is a useful aid for creating a spliterator when it is not
* possible or difficult to efficiently partition elements in a manner
* allowing balanced parallel computation.
*
* <p>An alternative to using this class, that also permits limited
* parallelism, is to create a spliterator from an iterator
* (see {@link #spliterator(java.util.PrimitiveIterator.OfDouble, long, int)}.
* Depending on the circumstances using an iterator may be easier or more
* convenient than extending this class. For example, if there is already an
* iterator available to use then there is no need to extend this class.
*
* @see #spliterator(java.util.PrimitiveIterator.OfDouble, long, int)
* @since 1.8
*/
public static abstract class
AbstractDoubleSpliterator implements
Spliterator.
OfDouble {
static final int
MAX_BATCH =
AbstractSpliterator.
MAX_BATCH;
static final int
BATCH_UNIT =
AbstractSpliterator.
BATCH_UNIT;
private final int
characteristics;
private long
est; // size estimate
private int
batch; // batch size for splits
/**
* Creates a spliterator reporting the given estimated size and
* characteristics.
*
* @param est the estimated size of this spliterator if known, otherwise
* {@code Long.MAX_VALUE}.
* @param additionalCharacteristics properties of this spliterator's
* source or elements. If {@code SIZED} is reported then this
* spliterator will additionally report {@code SUBSIZED}.
*/
protected
AbstractDoubleSpliterator(long
est, int
additionalCharacteristics) {
this.
est =
est;
this.
characteristics = ((
additionalCharacteristics &
Spliterator.
SIZED) != 0)
?
additionalCharacteristics |
Spliterator.
SUBSIZED
:
additionalCharacteristics;
}
static final class
HoldingDoubleConsumer implements
DoubleConsumer {
double
value;
@
Override
public void
accept(double
value) {
this.
value =
value;
}
}
/**
* {@inheritDoc}
*
* This implementation permits limited parallelism.
*/
@
Override
public
Spliterator.
OfDouble trySplit() {
HoldingDoubleConsumer holder = new
HoldingDoubleConsumer();
long
s =
est;
if (
s > 1 &&
tryAdvance(
holder)) {
int
n =
batch +
BATCH_UNIT;
if (
n >
s)
n = (int)
s;
if (
n >
MAX_BATCH)
n =
MAX_BATCH;
double[]
a = new double[
n];
int
j = 0;
do {
a[
j] =
holder.
value; } while (++
j <
n &&
tryAdvance(
holder));
batch =
j;
if (
est !=
Long.
MAX_VALUE)
est -=
j;
return new
DoubleArraySpliterator(
a, 0,
j,
characteristics());
}
return null;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns the estimated size as reported when
* created and, if the estimate size is known, decreases in size when
* split.
*/
@
Override
public long
estimateSize() {
return
est;
}
/**
* {@inheritDoc}
*
* @implSpec
* This implementation returns the characteristics as reported when
* created.
*/
@
Override
public int
characteristics() {
return
characteristics;
}
}
// Iterator-based Spliterators
/**
* A Spliterator using a given Iterator for element
* operations. The spliterator implements {@code trySplit} to
* permit limited parallelism.
*/
static class
IteratorSpliterator<T> implements
Spliterator<T> {
static final int
BATCH_UNIT = 1 << 10; // batch array size increment
static final int
MAX_BATCH = 1 << 25; // max batch array size;
private final
Collection<? extends T>
collection; // null OK
private
Iterator<? extends T>
it;
private final int
characteristics;
private long
est; // size estimate
private int
batch; // batch size for splits
/**
* Creates a spliterator using the given given
* collection's {@link java.util.Collection#iterator()) for traversal,
* and reporting its {@link java.util.Collection#size()) as its initial
* size.
*
* @param c the collection
* @param characteristics properties of this spliterator's
* source or elements.
*/
public
IteratorSpliterator(
Collection<? extends T>
collection, int
characteristics) {
this.
collection =
collection;
this.
it = null;
this.
characteristics = (
characteristics &
Spliterator.
CONCURRENT) == 0
?
characteristics |
Spliterator.
SIZED |
Spliterator.
SUBSIZED
:
characteristics;
}
/**
* Creates a spliterator using the given iterator
* for traversal, and reporting the given initial size
* and characteristics.
*
* @param iterator the iterator for the source
* @param size the number of elements in the source
* @param characteristics properties of this spliterator's
* source or elements.
*/
public
IteratorSpliterator(
Iterator<? extends T>
iterator, long
size, int
characteristics) {
this.
collection = null;
this.
it =
iterator;
this.
est =
size;
this.
characteristics = (
characteristics &
Spliterator.
CONCURRENT) == 0
?
characteristics |
Spliterator.
SIZED |
Spliterator.
SUBSIZED
:
characteristics;
}
/**
* Creates a spliterator using the given iterator
* for traversal, and reporting the given initial size
* and characteristics.
*
* @param iterator the iterator for the source
* @param characteristics properties of this spliterator's
* source or elements.
*/
public
IteratorSpliterator(
Iterator<? extends T>
iterator, int
characteristics) {
this.
collection = null;
this.
it =
iterator;
this.
est =
Long.
MAX_VALUE;
this.
characteristics =
characteristics & ~(
Spliterator.
SIZED |
Spliterator.
SUBSIZED);
}
@
Override
public
Spliterator<T>
trySplit() {
/*
* Split into arrays of arithmetically increasing batch
* sizes. This will only improve parallel performance if
* per-element Consumer actions are more costly than
* transferring them into an array. The use of an
* arithmetic progression in split sizes provides overhead
* vs parallelism bounds that do not particularly favor or
* penalize cases of lightweight vs heavyweight element
* operations, across combinations of #elements vs #cores,
* whether or not either are known. We generate
* O(sqrt(#elements)) splits, allowing O(sqrt(#cores))
* potential speedup.
*/
Iterator<? extends T>
i;
long
s;
if ((
i =
it) == null) {
i =
it =
collection.
iterator();
s =
est = (long)
collection.
size();
}
else
s =
est;
if (
s > 1 &&
i.
hasNext()) {
int
n =
batch +
BATCH_UNIT;
if (
n >
s)
n = (int)
s;
if (
n >
MAX_BATCH)
n =
MAX_BATCH;
Object[]
a = new
Object[
n];
int
j = 0;
do {
a[
j] =
i.
next(); } while (++
j <
n &&
i.
hasNext());
batch =
j;
if (
est !=
Long.
MAX_VALUE)
est -=
j;
return new
ArraySpliterator<>(
a, 0,
j,
characteristics);
}
return null;
}
@
Override
public void
forEachRemaining(
Consumer<? super T>
action) {
if (
action == null) throw new
NullPointerException();
Iterator<? extends T>
i;
if ((
i =
it) == null) {
i =
it =
collection.
iterator();
est = (long)
collection.
size();
}
i.
forEachRemaining(
action);
}
@
Override
public boolean
tryAdvance(
Consumer<? super T>
action) {
if (
action == null) throw new
NullPointerException();
if (
it == null) {
it =
collection.
iterator();
est = (long)
collection.
size();
}
if (
it.
hasNext()) {
action.
accept(
it.
next());
return true;
}
return false;
}
@
Override
public long
estimateSize() {
if (
it == null) {
it =
collection.
iterator();
return
est = (long)
collection.
size();
}
return
est;
}
@
Override
public int
characteristics() { return
characteristics; }
@
Override
public
Comparator<? super T>
getComparator() {
if (
hasCharacteristics(
Spliterator.
SORTED))
return null;
throw new
IllegalStateException();
}
}
/**
* A Spliterator.OfInt using a given IntStream.IntIterator for element
* operations. The spliterator implements {@code trySplit} to
* permit limited parallelism.
*/
static final class
IntIteratorSpliterator implements
Spliterator.
OfInt {
static final int
BATCH_UNIT =
IteratorSpliterator.
BATCH_UNIT;
static final int
MAX_BATCH =
IteratorSpliterator.
MAX_BATCH;
private
PrimitiveIterator.
OfInt it;
private final int
characteristics;
private long
est; // size estimate
private int
batch; // batch size for splits
/**
* Creates a spliterator using the given iterator
* for traversal, and reporting the given initial size
* and characteristics.
*
* @param iterator the iterator for the source
* @param size the number of elements in the source
* @param characteristics properties of this spliterator's
* source or elements.
*/
public
IntIteratorSpliterator(
PrimitiveIterator.
OfInt iterator, long
size, int
characteristics) {
this.
it =
iterator;
this.
est =
size;
this.
characteristics = (
characteristics &
Spliterator.
CONCURRENT) == 0
?
characteristics |
Spliterator.
SIZED |
Spliterator.
SUBSIZED
:
characteristics;
}
/**
* Creates a spliterator using the given iterator for a
* source of unknown size, reporting the given
* characteristics.
*
* @param iterator the iterator for the source
* @param characteristics properties of this spliterator's
* source or elements.
*/
public
IntIteratorSpliterator(
PrimitiveIterator.
OfInt iterator, int
characteristics) {
this.
it =
iterator;
this.
est =
Long.
MAX_VALUE;
this.
characteristics =
characteristics & ~(
Spliterator.
SIZED |
Spliterator.
SUBSIZED);
}
@
Override
public
OfInt trySplit() {
PrimitiveIterator.
OfInt i =
it;
long
s =
est;
if (
s > 1 &&
i.
hasNext()) {
int
n =
batch +
BATCH_UNIT;
if (
n >
s)
n = (int)
s;
if (
n >
MAX_BATCH)
n =
MAX_BATCH;
int[]
a = new int[
n];
int
j = 0;
do {
a[
j] =
i.
nextInt(); } while (++
j <
n &&
i.
hasNext());
batch =
j;
if (
est !=
Long.
MAX_VALUE)
est -=
j;
return new
IntArraySpliterator(
a, 0,
j,
characteristics);
}
return null;
}
@
Override
public void
forEachRemaining(
IntConsumer action) {
if (
action == null) throw new
NullPointerException();
it.
forEachRemaining(
action);
}
@
Override
public boolean
tryAdvance(
IntConsumer action) {
if (
action == null) throw new
NullPointerException();
if (
it.
hasNext()) {
action.
accept(
it.
nextInt());
return true;
}
return false;
}
@
Override
public long
estimateSize() {
return
est;
}
@
Override
public int
characteristics() { return
characteristics; }
@
Override
public
Comparator<? super
Integer>
getComparator() {
if (
hasCharacteristics(
Spliterator.
SORTED))
return null;
throw new
IllegalStateException();
}
}
static final class
LongIteratorSpliterator implements
Spliterator.
OfLong {
static final int
BATCH_UNIT =
IteratorSpliterator.
BATCH_UNIT;
static final int
MAX_BATCH =
IteratorSpliterator.
MAX_BATCH;
private
PrimitiveIterator.
OfLong it;
private final int
characteristics;
private long
est; // size estimate
private int
batch; // batch size for splits
/**
* Creates a spliterator using the given iterator
* for traversal, and reporting the given initial size
* and characteristics.
*
* @param iterator the iterator for the source
* @param size the number of elements in the source
* @param characteristics properties of this spliterator's
* source or elements.
*/
public
LongIteratorSpliterator(
PrimitiveIterator.
OfLong iterator, long
size, int
characteristics) {
this.
it =
iterator;
this.
est =
size;
this.
characteristics = (
characteristics &
Spliterator.
CONCURRENT) == 0
?
characteristics |
Spliterator.
SIZED |
Spliterator.
SUBSIZED
:
characteristics;
}
/**
* Creates a spliterator using the given iterator for a
* source of unknown size, reporting the given
* characteristics.
*
* @param iterator the iterator for the source
* @param characteristics properties of this spliterator's
* source or elements.
*/
public
LongIteratorSpliterator(
PrimitiveIterator.
OfLong iterator, int
characteristics) {
this.
it =
iterator;
this.
est =
Long.
MAX_VALUE;
this.
characteristics =
characteristics & ~(
Spliterator.
SIZED |
Spliterator.
SUBSIZED);
}
@
Override
public
OfLong trySplit() {
PrimitiveIterator.
OfLong i =
it;
long
s =
est;
if (
s > 1 &&
i.
hasNext()) {
int
n =
batch +
BATCH_UNIT;
if (
n >
s)
n = (int)
s;
if (
n >
MAX_BATCH)
n =
MAX_BATCH;
long[]
a = new long[
n];
int
j = 0;
do {
a[
j] =
i.
nextLong(); } while (++
j <
n &&
i.
hasNext());
batch =
j;
if (
est !=
Long.
MAX_VALUE)
est -=
j;
return new
LongArraySpliterator(
a, 0,
j,
characteristics);
}
return null;
}
@
Override
public void
forEachRemaining(
LongConsumer action) {
if (
action == null) throw new
NullPointerException();
it.
forEachRemaining(
action);
}
@
Override
public boolean
tryAdvance(
LongConsumer action) {
if (
action == null) throw new
NullPointerException();
if (
it.
hasNext()) {
action.
accept(
it.
nextLong());
return true;
}
return false;
}
@
Override
public long
estimateSize() {
return
est;
}
@
Override
public int
characteristics() { return
characteristics; }
@
Override
public
Comparator<? super
Long>
getComparator() {
if (
hasCharacteristics(
Spliterator.
SORTED))
return null;
throw new
IllegalStateException();
}
}
static final class
DoubleIteratorSpliterator implements
Spliterator.
OfDouble {
static final int
BATCH_UNIT =
IteratorSpliterator.
BATCH_UNIT;
static final int
MAX_BATCH =
IteratorSpliterator.
MAX_BATCH;
private
PrimitiveIterator.
OfDouble it;
private final int
characteristics;
private long
est; // size estimate
private int
batch; // batch size for splits
/**
* Creates a spliterator using the given iterator
* for traversal, and reporting the given initial size
* and characteristics.
*
* @param iterator the iterator for the source
* @param size the number of elements in the source
* @param characteristics properties of this spliterator's
* source or elements.
*/
public
DoubleIteratorSpliterator(
PrimitiveIterator.
OfDouble iterator, long
size, int
characteristics) {
this.
it =
iterator;
this.
est =
size;
this.
characteristics = (
characteristics &
Spliterator.
CONCURRENT) == 0
?
characteristics |
Spliterator.
SIZED |
Spliterator.
SUBSIZED
:
characteristics;
}
/**
* Creates a spliterator using the given iterator for a
* source of unknown size, reporting the given
* characteristics.
*
* @param iterator the iterator for the source
* @param characteristics properties of this spliterator's
* source or elements.
*/
public
DoubleIteratorSpliterator(
PrimitiveIterator.
OfDouble iterator, int
characteristics) {
this.
it =
iterator;
this.
est =
Long.
MAX_VALUE;
this.
characteristics =
characteristics & ~(
Spliterator.
SIZED |
Spliterator.
SUBSIZED);
}
@
Override
public
OfDouble trySplit() {
PrimitiveIterator.
OfDouble i =
it;
long
s =
est;
if (
s > 1 &&
i.
hasNext()) {
int
n =
batch +
BATCH_UNIT;
if (
n >
s)
n = (int)
s;
if (
n >
MAX_BATCH)
n =
MAX_BATCH;
double[]
a = new double[
n];
int
j = 0;
do {
a[
j] =
i.
nextDouble(); } while (++
j <
n &&
i.
hasNext());
batch =
j;
if (
est !=
Long.
MAX_VALUE)
est -=
j;
return new
DoubleArraySpliterator(
a, 0,
j,
characteristics);
}
return null;
}
@
Override
public void
forEachRemaining(
DoubleConsumer action) {
if (
action == null) throw new
NullPointerException();
it.
forEachRemaining(
action);
}
@
Override
public boolean
tryAdvance(
DoubleConsumer action) {
if (
action == null) throw new
NullPointerException();
if (
it.
hasNext()) {
action.
accept(
it.
nextDouble());
return true;
}
return false;
}
@
Override
public long
estimateSize() {
return
est;
}
@
Override
public int
characteristics() { return
characteristics; }
@
Override
public
Comparator<? super
Double>
getComparator() {
if (
hasCharacteristics(
Spliterator.
SORTED))
return null;
throw new
IllegalStateException();
}
}
}