/* * Copyright (c) 1997, 2014, 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.IntFunction; import java.util.function.IntToDoubleFunction; import java.util.function.IntToLongFunction; import java.util.function.IntUnaryOperator; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; import java.util.stream.Stream; import java.util.stream.StreamSupport; /** * This class contains various methods for manipulating arrays (such as * sorting and searching). This class also contains a static factory * that allows arrays to be viewed as lists. * * <p>The methods in this class all throw a {@code NullPointerException}, * if the specified array reference is null, except where noted. * * <p>The documentation for the methods contained in this class includes * briefs description of the <i>implementations</i>. Such descriptions should * be regarded as <i>implementation notes</i>, rather than parts of the * <i>specification</i>. Implementors should feel free to substitute other * algorithms, so long as the specification itself is adhered to. (For * example, the algorithm used by {@code sort(Object[])} does not have to be * a MergeSort, but it does have to be <i>stable</i>.) * * <p>This class is a member of the * <a href="{@docRoot}/../technotes/guides/collections/index.html"> * Java Collections Framework</a>. * * @author Josh Bloch * @author Neal Gafter * @author John Rose * @since 1.2 */ // for desugar: partial copy of new methods in java.util.Arrays used in stream package public class DesugarArrays { // Suppresses default constructor, ensuring non-instantiability. private DesugarArrays() {} // For desugar: included in Arrays8 so we can call it from Objects static boolean deepEquals0(Object e1, Object e2) { assert e1 != null; boolean eq; if (e1 instanceof Object[] && e2 instanceof Object[]) eq = Arrays.deepEquals ((Object[]) e1, (Object[]) e2); else if (e1 instanceof byte[] && e2 instanceof byte[]) eq = Arrays.equals((byte[]) e1, (byte[]) e2); else if (e1 instanceof short[] && e2 instanceof short[]) eq = Arrays.equals((short[]) e1, (short[]) e2); else if (e1 instanceof int[] && e2 instanceof int[]) eq = Arrays.equals((int[]) e1, (int[]) e2); else if (e1 instanceof long[] && e2 instanceof long[]) eq = Arrays.equals((long[]) e1, (long[]) e2); else if (e1 instanceof char[] && e2 instanceof char[]) eq = Arrays.equals((char[]) e1, (char[]) e2); else if (e1 instanceof float[] && e2 instanceof float[]) eq = Arrays.equals((float[]) e1, (float[]) e2); else if (e1 instanceof double[] && e2 instanceof double[]) eq = Arrays.equals((double[]) e1, (double[]) e2); else if (e1 instanceof boolean[] && e2 instanceof boolean[]) eq = Arrays.equals((boolean[]) e1, (boolean[]) e2); else eq = e1.equals(e2); return eq; } /** * Set all elements of the specified array, using the provided * generator function to compute each element. * * <p>If the generator function throws an exception, it is relayed to * the caller and the array is left in an indeterminate state. * * @param <T> type of elements of the array * @param array array to be initialized * @param generator a function accepting an index and producing the desired * value for that position * @throws NullPointerException if the generator is null * @since 1.8 */ public static <T> void setAll(T[] array, IntFunction<? extends T> generator) { Objects.requireNonNull(generator); for (int i = 0; i < array.length; i++) array[i] = generator.apply(i); } /** * Set all elements of the specified array, in parallel, using the * provided generator function to compute each element. * * <p>If the generator function throws an exception, an unchecked exception * is thrown from {@code parallelSetAll} and the array is left in an * indeterminate state. * * @param <T> type of elements of the array * @param array array to be initialized * @param generator a function accepting an index and producing the desired * value for that position * @throws NullPointerException if the generator is null * @since 1.8 */ public static <T> void parallelSetAll(T[] array, IntFunction<? extends T> generator) { Objects.requireNonNull(generator); IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.apply(i); }); } /** * Set all elements of the specified array, using the provided * generator function to compute each element. * * <p>If the generator function throws an exception, it is relayed to * the caller and the array is left in an indeterminate state. * * @param array array to be initialized * @param generator a function accepting an index and producing the desired * value for that position * @throws NullPointerException if the generator is null * @since 1.8 */ public static void setAll(int[] array, IntUnaryOperator generator) { Objects.requireNonNull(generator); for (int i = 0; i < array.length; i++) array[i] = generator.applyAsInt(i); } /** * Set all elements of the specified array, in parallel, using the * provided generator function to compute each element. * * <p>If the generator function throws an exception, an unchecked exception * is thrown from {@code parallelSetAll} and the array is left in an * indeterminate state. * * @param array array to be initialized * @param generator a function accepting an index and producing the desired * value for that position * @throws NullPointerException if the generator is null * @since 1.8 */ public static void parallelSetAll(int[] array, IntUnaryOperator generator) { Objects.requireNonNull(generator); IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsInt(i); }); } /** * Set all elements of the specified array, using the provided * generator function to compute each element. * * <p>If the generator function throws an exception, it is relayed to * the caller and the array is left in an indeterminate state. * * @param array array to be initialized * @param generator a function accepting an index and producing the desired * value for that position * @throws NullPointerException if the generator is null * @since 1.8 */ public static void setAll(long[] array, IntToLongFunction generator) { Objects.requireNonNull(generator); for (int i = 0; i < array.length; i++) array[i] = generator.applyAsLong(i); } /** * Set all elements of the specified array, in parallel, using the * provided generator function to compute each element. * * <p>If the generator function throws an exception, an unchecked exception * is thrown from {@code parallelSetAll} and the array is left in an * indeterminate state. * * @param array array to be initialized * @param generator a function accepting an index and producing the desired * value for that position * @throws NullPointerException if the generator is null * @since 1.8 */ public static void parallelSetAll(long[] array, IntToLongFunction generator) { Objects.requireNonNull(generator); IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsLong(i); }); } /** * Set all elements of the specified array, using the provided * generator function to compute each element. * * <p>If the generator function throws an exception, it is relayed to * the caller and the array is left in an indeterminate state. * * @param array array to be initialized * @param generator a function accepting an index and producing the desired * value for that position * @throws NullPointerException if the generator is null * @since 1.8 */ public static void setAll(double[] array, IntToDoubleFunction generator) { Objects.requireNonNull(generator); for (int i = 0; i < array.length; i++) array[i] = generator.applyAsDouble(i); } /** * Set all elements of the specified array, in parallel, using the * provided generator function to compute each element. * * <p>If the generator function throws an exception, an unchecked exception * is thrown from {@code parallelSetAll} and the array is left in an * indeterminate state. * * @param array array to be initialized * @param generator a function accepting an index and producing the desired * value for that position * @throws NullPointerException if the generator is null * @since 1.8 */ public static void parallelSetAll(double[] array, IntToDoubleFunction generator) { Objects.requireNonNull(generator); IntStream.range(0, array.length).parallel().forEach(i -> { array[i] = generator.applyAsDouble(i); }); } /** * Returns a {@link Spliterator} covering all of the specified array. * * <p>The spliterator reports {@link Spliterator#SIZED}, * {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and * {@link Spliterator#IMMUTABLE}. * * @param <T> type of elements * @param array the array, assumed to be unmodified during use * @return a spliterator for the array elements * @since 1.8 */ public static <T> Spliterator<T> spliterator(T[] array) { return Spliterators.spliterator(array, Spliterator.ORDERED | Spliterator.IMMUTABLE); } /** * Returns a {@link Spliterator} covering the specified range of the * specified array. * * <p>The spliterator reports {@link Spliterator#SIZED}, * {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and * {@link Spliterator#IMMUTABLE}. * * @param <T> type of elements * @param array the array, assumed to be unmodified during use * @param startInclusive the first index to cover, inclusive * @param endExclusive index immediately past the last index to cover * @return a spliterator for the array elements * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is * negative, {@code endExclusive} is less than * {@code startInclusive}, or {@code endExclusive} is greater than * the array size * @since 1.8 */ public static <T> Spliterator<T> spliterator(T[] array, int startInclusive, int endExclusive) { return Spliterators.spliterator(array, startInclusive, endExclusive, Spliterator.ORDERED | Spliterator.IMMUTABLE); } /** * Returns a {@link Spliterator.OfInt} covering all of the specified array. * * <p>The spliterator reports {@link Spliterator#SIZED}, * {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and * {@link Spliterator#IMMUTABLE}. * * @param array the array, assumed to be unmodified during use * @return a spliterator for the array elements * @since 1.8 */ public static Spliterator.OfInt spliterator(int[] array) { return Spliterators.spliterator(array, Spliterator.ORDERED | Spliterator.IMMUTABLE); } /** * Returns a {@link Spliterator.OfInt} covering the specified range of the * specified array. * * <p>The spliterator reports {@link Spliterator#SIZED}, * {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and * {@link Spliterator#IMMUTABLE}. * * @param array the array, assumed to be unmodified during use * @param startInclusive the first index to cover, inclusive * @param endExclusive index immediately past the last index to cover * @return a spliterator for the array elements * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is * negative, {@code endExclusive} is less than * {@code startInclusive}, or {@code endExclusive} is greater than * the array size * @since 1.8 */ public static Spliterator.OfInt spliterator(int[] array, int startInclusive, int endExclusive) { return Spliterators.spliterator(array, startInclusive, endExclusive, Spliterator.ORDERED | Spliterator.IMMUTABLE); } /** * Returns a {@link Spliterator.OfLong} covering all of the specified array. * * <p>The spliterator reports {@link Spliterator#SIZED}, * {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and * {@link Spliterator#IMMUTABLE}. * * @param array the array, assumed to be unmodified during use * @return the spliterator for the array elements * @since 1.8 */ public static Spliterator.OfLong spliterator(long[] array) { return Spliterators.spliterator(array, Spliterator.ORDERED | Spliterator.IMMUTABLE); } /** * Returns a {@link Spliterator.OfLong} covering the specified range of the * specified array. * * <p>The spliterator reports {@link Spliterator#SIZED}, * {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and * {@link Spliterator#IMMUTABLE}. * * @param array the array, assumed to be unmodified during use * @param startInclusive the first index to cover, inclusive * @param endExclusive index immediately past the last index to cover * @return a spliterator for the array elements * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is * negative, {@code endExclusive} is less than * {@code startInclusive}, or {@code endExclusive} is greater than * the array size * @since 1.8 */ public static Spliterator.OfLong spliterator(long[] array, int startInclusive, int endExclusive) { return Spliterators.spliterator(array, startInclusive, endExclusive, Spliterator.ORDERED | Spliterator.IMMUTABLE); } /** * Returns a {@link Spliterator.OfDouble} covering all of the specified * array. * * <p>The spliterator reports {@link Spliterator#SIZED}, * {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and * {@link Spliterator#IMMUTABLE}. * * @param array the array, assumed to be unmodified during use * @return a spliterator for the array elements * @since 1.8 */ public static Spliterator.OfDouble spliterator(double[] array) { return Spliterators.spliterator(array, Spliterator.ORDERED | Spliterator.IMMUTABLE); } /** * Returns a {@link Spliterator.OfDouble} covering the specified range of * the specified array. * * <p>The spliterator reports {@link Spliterator#SIZED}, * {@link Spliterator#SUBSIZED}, {@link Spliterator#ORDERED}, and * {@link Spliterator#IMMUTABLE}. * * @param array the array, assumed to be unmodified during use * @param startInclusive the first index to cover, inclusive * @param endExclusive index immediately past the last index to cover * @return a spliterator for the array elements * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is * negative, {@code endExclusive} is less than * {@code startInclusive}, or {@code endExclusive} is greater than * the array size * @since 1.8 */ public static Spliterator.OfDouble spliterator(double[] array, int startInclusive, int endExclusive) { return Spliterators.spliterator(array, startInclusive, endExclusive, Spliterator.ORDERED | Spliterator.IMMUTABLE); } /** * Returns a sequential {@link Stream} with the specified array as its * source. * * @param <T> The type of the array elements * @param array The array, assumed to be unmodified during use * @return a {@code Stream} for the array * @since 1.8 */ public static <T> Stream<T> stream(T[] array) { return stream(array, 0, array.length); } /** * Returns a sequential {@link Stream} with the specified range of the * specified array as its source. * * @param <T> the type of the array elements * @param array the array, assumed to be unmodified during use * @param startInclusive the first index to cover, inclusive * @param endExclusive index immediately past the last index to cover * @return a {@code Stream} for the array range * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is * negative, {@code endExclusive} is less than * {@code startInclusive}, or {@code endExclusive} is greater than * the array size * @since 1.8 */ public static <T> Stream<T> stream(T[] array, int startInclusive, int endExclusive) { return StreamSupport.stream(spliterator(array, startInclusive, endExclusive), false); } /** * Returns a sequential {@link IntStream} with the specified array as its * source. * * @param array the array, assumed to be unmodified during use * @return an {@code IntStream} for the array * @since 1.8 */ public static IntStream stream(int[] array) { return stream(array, 0, array.length); } /** * Returns a sequential {@link IntStream} with the specified range of the * specified array as its source. * * @param array the array, assumed to be unmodified during use * @param startInclusive the first index to cover, inclusive * @param endExclusive index immediately past the last index to cover * @return an {@code IntStream} for the array range * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is * negative, {@code endExclusive} is less than * {@code startInclusive}, or {@code endExclusive} is greater than * the array size * @since 1.8 */ public static IntStream stream(int[] array, int startInclusive, int endExclusive) { return StreamSupport.intStream(spliterator(array, startInclusive, endExclusive), false); } /** * Returns a sequential {@link LongStream} with the specified array as its * source. * * @param array the array, assumed to be unmodified during use * @return a {@code LongStream} for the array * @since 1.8 */ public static LongStream stream(long[] array) { return stream(array, 0, array.length); } /** * Returns a sequential {@link LongStream} with the specified range of the * specified array as its source. * * @param array the array, assumed to be unmodified during use * @param startInclusive the first index to cover, inclusive * @param endExclusive index immediately past the last index to cover * @return a {@code LongStream} for the array range * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is * negative, {@code endExclusive} is less than * {@code startInclusive}, or {@code endExclusive} is greater than * the array size * @since 1.8 */ public static LongStream stream(long[] array, int startInclusive, int endExclusive) { return StreamSupport.longStream(spliterator(array, startInclusive, endExclusive), false); } /** * Returns a sequential {@link DoubleStream} with the specified array as its * source. * * @param array the array, assumed to be unmodified during use * @return a {@code DoubleStream} for the array * @since 1.8 */ public static DoubleStream stream(double[] array) { return stream(array, 0, array.length); } /** * Returns a sequential {@link DoubleStream} with the specified range of the * specified array as its source. * * @param array the array, assumed to be unmodified during use * @param startInclusive the first index to cover, inclusive * @param endExclusive index immediately past the last index to cover * @return a {@code DoubleStream} for the array range * @throws ArrayIndexOutOfBoundsException if {@code startInclusive} is * negative, {@code endExclusive} is less than * {@code startInclusive}, or {@code endExclusive} is greater than * the array size * @since 1.8 */ public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) { return StreamSupport.doubleStream(spliterator(array, startInclusive, endExclusive), false); } }