Java tutorial
/* * 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 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 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 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 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 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 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 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 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 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 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 abstract static 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 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 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 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 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 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 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 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 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) forEachRemaining} * 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 abstract static 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) forEachRemaining} * 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 abstract static 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) forEachRemaining} * 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 abstract static 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) forEachRemaining} * 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 abstract static 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 * 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(); } } }