--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/Spliterators.java Tue Apr 16 13:51:53 2013 -0400
@@ -0,0 +1,2154 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+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 IllegalArgumentException(
+ "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 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 from an iterator
+ * @throws NullPointerException if the given collection is {@code null}
+ */
+ public static <T> Spliterator<T> spliterator(Collection<? extends T> c,
+ int additionalCharacteristics) {
+ return new IteratorSpliterator<>(Objects.requireNonNull(c),
+ additionalCharacteristics);
+ }
+
+ /**
+ * 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 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 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 additionalCharacteristics) {
+ return new IteratorSpliterator<>(Objects.requireNonNull(iterator), size,
+ additionalCharacteristics);
+ }
+
+ /**
+ * 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 Properties 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 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 from an iterator
+ * @throws NullPointerException if the given iterator is {@code null}
+ */
+ public static Spliterator.OfInt spliterator(PrimitiveIterator.OfInt iterator,
+ long size,
+ int additionalCharacteristics) {
+ return new IntIteratorSpliterator(Objects.requireNonNull(iterator),
+ size, additionalCharacteristics);
+ }
+
+ /**
+ * 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 Properties 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 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 from an iterator
+ * @throws NullPointerException if the given iterator is {@code null}
+ */
+ public static Spliterator.OfLong spliterator(PrimitiveIterator.OfLong iterator,
+ long size,
+ int additionalCharacteristics) {
+ return new LongIteratorSpliterator(Objects.requireNonNull(iterator),
+ size, additionalCharacteristics);
+ }
+
+ /**
+ * 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 Properties 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 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 from an iterator
+ * @throws NullPointerException if the given iterator is {@code null}
+ */
+ public static Spliterator.OfDouble spliterator(PrimitiveIterator.OfDouble iterator,
+ long size,
+ int additionalCharacteristics) {
+ return new DoubleIteratorSpliterator(Objects.requireNonNull(iterator),
+ size, additionalCharacteristics);
+ }
+
+ /**
+ * 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 Properties 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> iteratorFromSpliterator(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 iteratorFromSpliterator(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 iteratorFromSpliterator(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 iteratorFromSpliterator(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;
+ try {
+ a = new Object[n];
+ } catch (OutOfMemoryError oome) {
+ return null;
+ }
+ 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;
+ try {
+ a = new int[n];
+ } catch (OutOfMemoryError oome) {
+ return null;
+ }
+ 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;
+ try {
+ a = new long[n];
+ } catch (OutOfMemoryError oome) {
+ return null;
+ }
+ 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;
+ try {
+ a = new double[n];
+ } catch (OutOfMemoryError oome) {
+ return null;
+ }
+ 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.SIZED | Spliterator.SUBSIZED;
+ }
+
+ /**
+ * 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.SIZED | Spliterator.SUBSIZED;
+ }
+
+ /**
+ * 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;
+ try {
+ a = new Object[n];
+ } catch (OutOfMemoryError oome) {
+ return null;
+ }
+ 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.SIZED | Spliterator.SUBSIZED;
+ }
+
+ /**
+ * 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;
+ try {
+ a = new int[n];
+ } catch (OutOfMemoryError oome) {
+ return null;
+ }
+ 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.SIZED | Spliterator.SUBSIZED;
+ }
+
+ /**
+ * 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;
+ try {
+ a = new long[n];
+ } catch (OutOfMemoryError oome) {
+ return null;
+ }
+ 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.SIZED | Spliterator.SUBSIZED;
+ }
+
+ /**
+ * 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;
+ try {
+ a = new double[n];
+ } catch (OutOfMemoryError oome) {
+ return null;
+ }
+ 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();
+ }
+ }
+}