001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.lang3;
018
019import java.lang.reflect.Array;
020import java.lang.reflect.Field;
021import java.lang.reflect.Method;
022import java.lang.reflect.Type;
023import java.security.SecureRandom;
024import java.util.Arrays;
025import java.util.BitSet;
026import java.util.Comparator;
027import java.util.Date;
028import java.util.HashMap;
029import java.util.Map;
030import java.util.Objects;
031import java.util.Random;
032import java.util.concurrent.ThreadLocalRandom;
033import java.util.function.Function;
034import java.util.function.IntFunction;
035import java.util.function.Supplier;
036
037import org.apache.commons.lang3.builder.EqualsBuilder;
038import org.apache.commons.lang3.builder.HashCodeBuilder;
039import org.apache.commons.lang3.builder.ToStringBuilder;
040import org.apache.commons.lang3.builder.ToStringStyle;
041import org.apache.commons.lang3.function.FailableFunction;
042import org.apache.commons.lang3.mutable.MutableInt;
043import org.apache.commons.lang3.stream.IntStreams;
044import org.apache.commons.lang3.stream.Streams;
045
046/**
047 * Operations on arrays, primitive arrays (like {@code int[]}) and
048 * primitive wrapper arrays (like {@code Integer[]}).
049 * <p>
050 * This class tries to handle {@code null} input gracefully.
051 * An exception will not be thrown for a {@code null}
052 * array input. However, an Object array that contains a {@code null}
053 * element may throw an exception. Each method documents its behavior.
054 * </p>
055 * <p>
056 * #ThreadSafe#
057 * </p>
058 *
059 * @since 2.0
060 */
061public class ArrayUtils {
062
063    /**
064     * Bridge class to {@link Math} methods for testing purposes.
065     */
066    static class MathBridge {
067        static int addExact(final int a, final int b) {
068            return Math.addExact(a, b);
069        }
070    }
071
072    /**
073     * An empty immutable {@code boolean} array.
074     */
075    public static final boolean[] EMPTY_BOOLEAN_ARRAY = {};
076
077    /**
078     * An empty immutable {@link Boolean} array.
079     */
080    public static final Boolean[] EMPTY_BOOLEAN_OBJECT_ARRAY = {};
081
082    /**
083     * An empty immutable {@code byte} array.
084     */
085    public static final byte[] EMPTY_BYTE_ARRAY = {};
086
087    /**
088     * An empty immutable {@link Byte} array.
089     */
090    public static final Byte[] EMPTY_BYTE_OBJECT_ARRAY = {};
091
092    /**
093     * An empty immutable {@code char} array.
094     */
095    public static final char[] EMPTY_CHAR_ARRAY = {};
096
097    /**
098     * An empty immutable {@link Character} array.
099     */
100    public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = {};
101
102    /**
103     * An empty immutable {@link Class} array.
104     */
105    public static final Class<?>[] EMPTY_CLASS_ARRAY = {};
106
107    /**
108     * An empty immutable {@code double} array.
109     */
110    public static final double[] EMPTY_DOUBLE_ARRAY = {};
111
112    /**
113     * An empty immutable {@link Double} array.
114     */
115    public static final Double[] EMPTY_DOUBLE_OBJECT_ARRAY = {};
116
117    /**
118     * An empty immutable {@link Field} array.
119     *
120     * @since 3.10
121     */
122    public static final Field[] EMPTY_FIELD_ARRAY = {};
123
124    /**
125     * An empty immutable {@code float} array.
126     */
127    public static final float[] EMPTY_FLOAT_ARRAY = {};
128
129    /**
130     * An empty immutable {@link Float} array.
131     */
132    public static final Float[] EMPTY_FLOAT_OBJECT_ARRAY = {};
133
134    /**
135     * An empty immutable {@code int} array.
136     */
137    public static final int[] EMPTY_INT_ARRAY = {};
138
139    /**
140     * An empty immutable {@link Integer} array.
141     */
142    public static final Integer[] EMPTY_INTEGER_OBJECT_ARRAY = {};
143
144    /**
145     * An empty immutable {@code long} array.
146     */
147    public static final long[] EMPTY_LONG_ARRAY = {};
148
149    /**
150     * An empty immutable {@link Long} array.
151     */
152    public static final Long[] EMPTY_LONG_OBJECT_ARRAY = {};
153
154    /**
155     * An empty immutable {@link Method} array.
156     *
157     * @since 3.10
158     */
159    public static final Method[] EMPTY_METHOD_ARRAY = {};
160
161    /**
162     * An empty immutable {@link Object} array.
163     */
164    public static final Object[] EMPTY_OBJECT_ARRAY = {};
165
166    /**
167     * An empty immutable {@code short} array.
168     */
169    public static final short[] EMPTY_SHORT_ARRAY = {};
170
171    /**
172     * An empty immutable {@link Short} array.
173     */
174    public static final Short[] EMPTY_SHORT_OBJECT_ARRAY = {};
175
176    /**
177     * An empty immutable {@link String} array.
178     */
179    public static final String[] EMPTY_STRING_ARRAY = {};
180
181    /**
182     * An empty immutable {@link Throwable} array.
183     *
184     * @since 3.10
185     */
186    public static final Throwable[] EMPTY_THROWABLE_ARRAY = {};
187
188    /**
189     * An empty immutable {@link Type} array.
190     *
191     * @since 3.10
192     */
193    public static final Type[] EMPTY_TYPE_ARRAY = {};
194
195    /**
196     * The index value when an element is not found in a list or array: {@code -1}.
197     * This value is returned by methods in this class and can also be used in comparisons with values returned by
198     * various method from {@link java.util.List}.
199     */
200    public static final int INDEX_NOT_FOUND = -1;
201
202    /**
203     * The {@code SOFT_MAX_ARRAY_LENGTH} constant from Java's internal ArraySupport class.
204     *
205     * @since 3.19.0
206     * @deprecated This variable will be final in 4.0; to guarantee immutability now, use {@link #SAFE_MAX_ARRAY_LENGTH}.
207     */
208    @Deprecated
209    public static int SOFT_MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;
210
211    /**
212     * The {@code MAX_ARRAY_LENGTH} constant from Java's internal ArraySupport class.
213     *
214     * @since 3.21.0
215     */
216    public static final int SAFE_MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;
217
218    /**
219     * Copies the given array and adds the given element at the end of the new array.
220     * <p>
221     * The new array contains the same elements of the input
222     * array plus the given element in the last position. The component type of
223     * the new array is the same as that of the input array.
224     * </p>
225     * <p>
226     * If the input array is {@code null}, a new one element array is returned
227     * whose component type is the same as the element.
228     * </p>
229     * <pre>
230     * ArrayUtils.add(null, true)          = [true]
231     * ArrayUtils.add([true], false)       = [true, false]
232     * ArrayUtils.add([true, false], true) = [true, false, true]
233     * </pre>
234     *
235     * @param array  The array to copy and add the element to, may be {@code null}.
236     * @param element  The object to add at the last index of the new array.
237     * @return A new array containing the existing elements plus the new element.
238     * @since 2.1
239     */
240    public static boolean[] add(final boolean[] array, final boolean element) {
241        final boolean[] newArray = (boolean[]) copyArrayGrow1(array, Boolean.TYPE);
242        newArray[newArray.length - 1] = element;
243        return newArray;
244    }
245
246    /**
247     * Inserts the specified element at the specified position in the array.
248     * Shifts the element currently at that position (if any) and any subsequent
249     * elements to the right (adds one to their indices).
250     * <p>
251     * This method returns a new array with the same elements of the input
252     * array plus the given element on the specified position. The component
253     * type of the returned array is always the same as that of the input
254     * array.
255     * </p>
256     * <p>
257     * If the input array is {@code null}, a new one element array is returned
258     * whose component type is the same as the element.
259     * </p>
260     * <pre>
261     * ArrayUtils.add(null, 0, true)          = [true]
262     * ArrayUtils.add([true], 0, false)       = [false, true]
263     * ArrayUtils.add([false], 1, true)       = [false, true]
264     * ArrayUtils.add([true, false], 1, true) = [true, true, false]
265     * </pre>
266     *
267     * @param array  The array to add the element to, may be {@code null}.
268     * @param index  The position of the new object.
269     * @param element  The object to add.
270     * @return A new array containing the existing elements and the new element.
271     * @throws IndexOutOfBoundsException Thrown if the index is out of range (index &lt; 0 || index &gt; array.length).
272     * @deprecated this method has been superseded by {@link #insert(int, boolean[], boolean...)} and
273     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
274     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
275     */
276    @Deprecated
277    public static boolean[] add(final boolean[] array, final int index, final boolean element) {
278        return (boolean[]) add(array, index, Boolean.valueOf(element), Boolean.TYPE);
279    }
280
281    /**
282     * Copies the given array and adds the given element at the end of the new array.
283     * <p>
284     * The new array contains the same elements of the input
285     * array plus the given element in the last position. The component type of
286     * the new array is the same as that of the input array.
287     * </p>
288     * <p>
289     * If the input array is {@code null}, a new one element array is returned
290     * whose component type is the same as the element.
291     * </p>
292     * <pre>
293     * ArrayUtils.add(null, 0)   = [0]
294     * ArrayUtils.add([1], 0)    = [1, 0]
295     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
296     * </pre>
297     *
298     * @param array  The array to copy and add the element to, may be {@code null}.
299     * @param element  The object to add at the last index of the new array.
300     * @return A new array containing the existing elements plus the new element.
301     * @since 2.1
302     */
303    public static byte[] add(final byte[] array, final byte element) {
304        final byte[] newArray = (byte[]) copyArrayGrow1(array, Byte.TYPE);
305        newArray[newArray.length - 1] = element;
306        return newArray;
307    }
308
309    /**
310     * Inserts the specified element at the specified position in the array.
311     * Shifts the element currently at that position (if any) and any subsequent
312     * elements to the right (adds one to their indices).
313     * <p>
314     * This method returns a new array with the same elements of the input
315     * array plus the given element on the specified position. The component
316     * type of the returned array is always the same as that of the input
317     * array.
318     * </p>
319     * <p>
320     * If the input array is {@code null}, a new one element array is returned
321     * whose component type is the same as the element.
322     * </p>
323     * <pre>
324     * ArrayUtils.add([1], 0, 2)         = [2, 1]
325     * ArrayUtils.add([2, 6], 2, 3)      = [2, 6, 3]
326     * ArrayUtils.add([2, 6], 0, 1)      = [1, 2, 6]
327     * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
328     * </pre>
329     *
330     * @param array  The array to add the element to, may be {@code null}.
331     * @param index  The position of the new object.
332     * @param element  The object to add.
333     * @return A new array containing the existing elements and the new element.
334     * @throws IndexOutOfBoundsException Thrown if the index is out of range.
335     * (index &lt; 0 || index &gt; array.length).
336     * @deprecated this method has been superseded by {@link #insert(int, byte[], byte...)} and
337     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
338     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
339     */
340    @Deprecated
341    public static byte[] add(final byte[] array, final int index, final byte element) {
342        return (byte[]) add(array, index, Byte.valueOf(element), Byte.TYPE);
343    }
344
345    /**
346     * Copies the given array and adds the given element at the end of the new array.
347     * <p>
348     * The new array contains the same elements of the input
349     * array plus the given element in the last position. The component type of
350     * the new array is the same as that of the input array.
351     * </p>
352     * <p>
353     * If the input array is {@code null}, a new one element array is returned
354     * whose component type is the same as the element.
355     * </p>
356     * <pre>
357     * ArrayUtils.add(null, '0')       = ['0']
358     * ArrayUtils.add(['1'], '0')      = ['1', '0']
359     * ArrayUtils.add(['1', '0'], '1') = ['1', '0', '1']
360     * </pre>
361     *
362     * @param array  The array to copy and add the element to, may be {@code null}.
363     * @param element  The object to add at the last index of the new array.
364     * @return A new array containing the existing elements plus the new element.
365     * @since 2.1
366     */
367    public static char[] add(final char[] array, final char element) {
368        final char[] newArray = (char[]) copyArrayGrow1(array, Character.TYPE);
369        newArray[newArray.length - 1] = element;
370        return newArray;
371    }
372
373    /**
374     * Inserts the specified element at the specified position in the array.
375     * Shifts the element currently at that position (if any) and any subsequent
376     * elements to the right (adds one to their indices).
377     * <p>
378     * This method returns a new array with the same elements of the input
379     * array plus the given element on the specified position. The component
380     * type of the returned array is always the same as that of the input
381     * array.
382     * </p>
383     * <p>
384     * If the input array is {@code null}, a new one element array is returned
385     * whose component type is the same as the element.
386     * </p>
387     * <pre>
388     * ArrayUtils.add(null, 0, 'a')            = ['a']
389     * ArrayUtils.add(['a'], 0, 'b')           = ['b', 'a']
390     * ArrayUtils.add(['a', 'b'], 0, 'c')      = ['c', 'a', 'b']
391     * ArrayUtils.add(['a', 'b'], 1, 'k')      = ['a', 'k', 'b']
392     * ArrayUtils.add(['a', 'b', 'c'], 1, 't') = ['a', 't', 'b', 'c']
393     * </pre>
394     *
395     * @param array  The array to add the element to, may be {@code null}.
396     * @param index  The position of the new object.
397     * @param element  The object to add.
398     * @return A new array containing the existing elements and the new element.
399     * @throws IndexOutOfBoundsException Thrown if the index is out of range.
400     * (index &lt; 0 || index &gt; array.length).
401     * @deprecated this method has been superseded by {@link #insert(int, char[], char...)} and
402     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
403     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
404     */
405    @Deprecated
406    public static char[] add(final char[] array, final int index, final char element) {
407        return (char[]) add(array, index, Character.valueOf(element), Character.TYPE);
408    }
409
410    /**
411     * Copies the given array and adds the given element at the end of the new array.
412     *
413     * <p>
414     * The new array contains the same elements of the input
415     * array plus the given element in the last position. The component type of
416     * the new array is the same as that of the input array.
417     * </p>
418     * <p>
419     * If the input array is {@code null}, a new one element array is returned
420     * whose component type is the same as the element.
421     * </p>
422     * <pre>
423     * ArrayUtils.add(null, 0)   = [0]
424     * ArrayUtils.add([1], 0)    = [1, 0]
425     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
426     * </pre>
427     *
428     * @param array  The array to copy and add the element to, may be {@code null}.
429     * @param element  The object to add at the last index of the new array.
430     * @return A new array containing the existing elements plus the new element.
431     * @since 2.1
432     */
433    public static double[] add(final double[] array, final double element) {
434        final double[] newArray = (double[]) copyArrayGrow1(array, Double.TYPE);
435        newArray[newArray.length - 1] = element;
436        return newArray;
437    }
438
439    /**
440     * Inserts the specified element at the specified position in the array.
441     * Shifts the element currently at that position (if any) and any subsequent
442     * elements to the right (adds one to their indices).
443     * <p>
444     * This method returns a new array with the same elements of the input
445     * array plus the given element on the specified position. The component
446     * type of the returned array is always the same as that of the input
447     * array.
448     * </p>
449     * <p>
450     * If the input array is {@code null}, a new one element array is returned
451     * whose component type is the same as the element.
452     * </p>
453     * <pre>
454     * ArrayUtils.add([1.1], 0, 2.2)              = [2.2, 1.1]
455     * ArrayUtils.add([2.3, 6.4], 2, 10.5)        = [2.3, 6.4, 10.5]
456     * ArrayUtils.add([2.6, 6.7], 0, -4.8)        = [-4.8, 2.6, 6.7]
457     * ArrayUtils.add([2.9, 6.0, 0.3], 2, 1.0)    = [2.9, 6.0, 1.0, 0.3]
458     * </pre>
459     *
460     * @param array  The array to add the element to, may be {@code null}.
461     * @param index  The position of the new object.
462     * @param element  The object to add.
463     * @return A new array containing the existing elements and the new element.
464     * @throws IndexOutOfBoundsException Thrown if the index is out of range
465     * (index &lt; 0 || index &gt; array.length).
466     * @deprecated this method has been superseded by {@link #insert(int, double[], double...)} and
467     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
468     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
469     */
470    @Deprecated
471    public static double[] add(final double[] array, final int index, final double element) {
472        return (double[]) add(array, index, Double.valueOf(element), Double.TYPE);
473    }
474
475    /**
476     * Copies the given array and adds the given element at the end of the new array.
477     * <p>
478     * The new array contains the same elements of the input
479     * array plus the given element in the last position. The component type of
480     * the new array is the same as that of the input array.
481     * </p>
482     * <p>
483     * If the input array is {@code null}, a new one element array is returned
484     * whose component type is the same as the element.
485     * </p>
486     * <pre>
487     * ArrayUtils.add(null, 0)   = [0]
488     * ArrayUtils.add([1], 0)    = [1, 0]
489     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
490     * </pre>
491     *
492     * @param array  The array to copy and add the element to, may be {@code null}.
493     * @param element  The object to add at the last index of the new array.
494     * @return A new array containing the existing elements plus the new element.
495     * @since 2.1
496     */
497    public static float[] add(final float[] array, final float element) {
498        final float[] newArray = (float[]) copyArrayGrow1(array, Float.TYPE);
499        newArray[newArray.length - 1] = element;
500        return newArray;
501    }
502
503    /**
504     * Inserts the specified element at the specified position in the array.
505     * Shifts the element currently at that position (if any) and any subsequent
506     * elements to the right (adds one to their indices).
507     * <p>
508     * This method returns a new array with the same elements of the input
509     * array plus the given element on the specified position. The component
510     * type of the returned array is always the same as that of the input
511     * array.
512     * </p>
513     * <p>
514     * If the input array is {@code null}, a new one element array is returned
515     * whose component type is the same as the element.
516     * </p>
517     * <pre>
518     * ArrayUtils.add([1.1f], 0, 2.2f)               = [2.2f, 1.1f]
519     * ArrayUtils.add([2.3f, 6.4f], 2, 10.5f)        = [2.3f, 6.4f, 10.5f]
520     * ArrayUtils.add([2.6f, 6.7f], 0, -4.8f)        = [-4.8f, 2.6f, 6.7f]
521     * ArrayUtils.add([2.9f, 6.0f, 0.3f], 2, 1.0f)   = [2.9f, 6.0f, 1.0f, 0.3f]
522     * </pre>
523     *
524     * @param array  The array to add the element to, may be {@code null}.
525     * @param index  The position of the new object.
526     * @param element  The object to add.
527     * @return A new array containing the existing elements and the new element.
528     * @throws IndexOutOfBoundsException Thrown if the index is out of range
529     * (index &lt; 0 || index &gt; array.length).
530     * @deprecated this method has been superseded by {@link #insert(int, float[], float...)} and
531     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
532     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
533     */
534    @Deprecated
535    public static float[] add(final float[] array, final int index, final float element) {
536        return (float[]) add(array, index, Float.valueOf(element), Float.TYPE);
537    }
538
539    /**
540     * Copies the given array and adds the given element at the end of the new array.
541     * <p>
542     * The new array contains the same elements of the input
543     * array plus the given element in the last position. The component type of
544     * the new array is the same as that of the input array.
545     * </p>
546     * <p>
547     * If the input array is {@code null}, a new one element array is returned
548     * whose component type is the same as the element.
549     * </p>
550     * <pre>
551     * ArrayUtils.add(null, 0)   = [0]
552     * ArrayUtils.add([1], 0)    = [1, 0]
553     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
554     * </pre>
555     *
556     * @param array  The array to copy and add the element to, may be {@code null}.
557     * @param element  The object to add at the last index of the new array.
558     * @return A new array containing the existing elements plus the new element.
559     * @since 2.1
560     */
561    public static int[] add(final int[] array, final int element) {
562        final int[] newArray = (int[]) copyArrayGrow1(array, Integer.TYPE);
563        newArray[newArray.length - 1] = element;
564        return newArray;
565    }
566
567    /**
568     * Inserts the specified element at the specified position in the array.
569     * Shifts the element currently at that position (if any) and any subsequent
570     * elements to the right (adds one to their indices).
571     * <p>
572     * This method returns a new array with the same elements of the input
573     * array plus the given element on the specified position. The component
574     * type of the returned array is always the same as that of the input
575     * array.
576     * </p>
577     * <p>
578     * If the input array is {@code null}, a new one element array is returned
579     * whose component type is the same as the element.
580     * </p>
581     * <pre>
582     * ArrayUtils.add([1], 0, 2)         = [2, 1]
583     * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
584     * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
585     * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
586     * </pre>
587     *
588     * @param array  The array to add the element to, may be {@code null}.
589     * @param index  The position of the new object.
590     * @param element  The object to add.
591     * @return A new array containing the existing elements and the new element.
592     * @throws IndexOutOfBoundsException Thrown if the index is out of range
593     * (index &lt; 0 || index &gt; array.length).
594     * @deprecated this method has been superseded by {@link #insert(int, int[], int...)} and
595     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
596     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
597     */
598    @Deprecated
599    public static int[] add(final int[] array, final int index, final int element) {
600        return (int[]) add(array, index, Integer.valueOf(element), Integer.TYPE);
601    }
602
603    /**
604     * Inserts the specified element at the specified position in the array.
605     * Shifts the element currently at that position (if any) and any subsequent
606     * elements to the right (adds one to their indices).
607     * <p>
608     * This method returns a new array with the same elements of the input
609     * array plus the given element on the specified position. The component
610     * type of the returned array is always the same as that of the input
611     * array.
612     * </p>
613     * <p>
614     * If the input array is {@code null}, a new one element array is returned
615     * whose component type is the same as the element.
616     * </p>
617     * <pre>
618     * ArrayUtils.add([1L], 0, 2L)           = [2L, 1L]
619     * ArrayUtils.add([2L, 6L], 2, 10L)      = [2L, 6L, 10L]
620     * ArrayUtils.add([2L, 6L], 0, -4L)      = [-4L, 2L, 6L]
621     * ArrayUtils.add([2L, 6L, 3L], 2, 1L)   = [2L, 6L, 1L, 3L]
622     * </pre>
623     *
624     * @param array  The array to add the element to, may be {@code null}.
625     * @param index  The position of the new object.
626     * @param element  The object to add.
627     * @return A new array containing the existing elements and the new element.
628     * @throws IndexOutOfBoundsException Thrown if the index is out of range
629     * (index &lt; 0 || index &gt; array.length).
630     * @deprecated this method has been superseded by {@link #insert(int, long[], long...)} and
631     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
632     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
633     */
634    @Deprecated
635    public static long[] add(final long[] array, final int index, final long element) {
636        return (long[]) add(array, index, Long.valueOf(element), Long.TYPE);
637    }
638
639    /**
640     * Copies the given array and adds the given element at the end of the new array.
641     * <p>
642     * The new array contains the same elements of the input
643     * array plus the given element in the last position. The component type of
644     * the new array is the same as that of the input array.
645     * </p>
646     * <p>
647     * If the input array is {@code null}, a new one element array is returned
648     * whose component type is the same as the element.
649     * </p>
650     * <pre>
651     * ArrayUtils.add(null, 0)   = [0]
652     * ArrayUtils.add([1], 0)    = [1, 0]
653     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
654     * </pre>
655     *
656     * @param array  The array to copy and add the element to, may be {@code null}.
657     * @param element  The object to add at the last index of the new array.
658     * @return A new array containing the existing elements plus the new element.
659     * @since 2.1
660     */
661    public static long[] add(final long[] array, final long element) {
662        final long[] newArray = (long[]) copyArrayGrow1(array, Long.TYPE);
663        newArray[newArray.length - 1] = element;
664        return newArray;
665    }
666
667    /**
668     * Underlying implementation of add(array, index, element) methods.
669     * The last parameter is the class, which may not equal element.getClass
670     * for primitives.
671     *
672     * @param array  The array to add the element to, may be {@code null}.
673     * @param index  The position of the new object.
674     * @param element  The object to add.
675     * @param clazz The type of the element being added.
676     * @return A new array containing the existing elements and the new element.
677     */
678    private static Object add(final Object array, final int index, final Object element, final Class<?> clazz) {
679        if (array == null) {
680            if (index != 0) {
681                throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
682            }
683            final Object joinedArray = Array.newInstance(clazz, 1);
684            Array.set(joinedArray, 0, element);
685            return joinedArray;
686        }
687        final int length = Array.getLength(array);
688        if (index > length || index < 0) {
689            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
690        }
691        final Object result = arraycopy(array, 0, 0, index, () -> Array.newInstance(clazz, length + 1));
692        Array.set(result, index, element);
693        if (index < length) {
694            System.arraycopy(array, index, result, index + 1, length - index);
695        }
696        return result;
697    }
698
699    /**
700     * Inserts the specified element at the specified position in the array.
701     * Shifts the element currently at that position (if any) and any subsequent
702     * elements to the right (adds one to their indices).
703     * <p>
704     * This method returns a new array with the same elements of the input
705     * array plus the given element on the specified position. The component
706     * type of the returned array is always the same as that of the input
707     * array.
708     * </p>
709     * <p>
710     * If the input array is {@code null}, a new one element array is returned
711     * whose component type is the same as the element.
712     * </p>
713     * <pre>
714     * ArrayUtils.add([1], 0, 2)         = [2, 1]
715     * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
716     * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
717     * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
718     * </pre>
719     *
720     * @param array  The array to add the element to, may be {@code null}.
721     * @param index  The position of the new object.
722     * @param element  The object to add.
723     * @return A new array containing the existing elements and the new element.
724     * @throws IndexOutOfBoundsException Thrown if the index is out of range
725     * (index &lt; 0 || index &gt; array.length).
726     * @deprecated this method has been superseded by {@link #insert(int, short[], short...)} and
727     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
728     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
729     */
730    @Deprecated
731    public static short[] add(final short[] array, final int index, final short element) {
732        return (short[]) add(array, index, Short.valueOf(element), Short.TYPE);
733    }
734
735    /**
736     * Copies the given array and adds the given element at the end of the new array.
737     * <p>
738     * The new array contains the same elements of the input
739     * array plus the given element in the last position. The component type of
740     * the new array is the same as that of the input array.
741     * </p>
742     * <p>
743     * If the input array is {@code null}, a new one element array is returned
744     * whose component type is the same as the element.
745     * </p>
746     * <pre>
747     * ArrayUtils.add(null, 0)   = [0]
748     * ArrayUtils.add([1], 0)    = [1, 0]
749     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
750     * </pre>
751     *
752     * @param array  The array to copy and add the element to, may be {@code null}.
753     * @param element  The object to add at the last index of the new array.
754     * @return A new array containing the existing elements plus the new element.
755     * @since 2.1
756     */
757    public static short[] add(final short[] array, final short element) {
758        final short[] newArray = (short[]) copyArrayGrow1(array, Short.TYPE);
759        newArray[newArray.length - 1] = element;
760        return newArray;
761    }
762
763    /**
764     * Inserts the specified element at the specified position in the array.
765     * Shifts the element currently at that position (if any) and any subsequent
766     * elements to the right (adds one to their indices).
767     * <p>
768     * This method returns a new array with the same elements of the input
769     * array plus the given element on the specified position. The component
770     * type of the returned array is always the same as that of the input
771     * array.
772     * </p>
773     * <p>
774     * If the input array is {@code null}, a new one element array is returned
775     * whose component type is the same as the element.
776     * </p>
777     * <pre>
778     * ArrayUtils.add(null, 0, null)      = Throws {@link IllegalArgumentException}
779     * ArrayUtils.add(null, 0, "a")       = ["a"]
780     * ArrayUtils.add(["a"], 1, null)     = ["a", null]
781     * ArrayUtils.add(["a"], 1, "b")      = ["a", "b"]
782     * ArrayUtils.add(["a", "b"], 3, "c") = ["a", "b", "c"]
783     * </pre>
784     *
785     * @param <T> The component type of the array.
786     * @param array  The array to add the element to, may be {@code null}.
787     * @param index  The position of the new object.
788     * @param element  The object to add.
789     * @return A new array containing the existing elements and the new element.
790     * @throws IndexOutOfBoundsException Thrown if the index is out of range (index &lt; 0 || index &gt; array.length).
791     * @throws IllegalArgumentException Thrown if both array and element are null.
792     * @deprecated this method has been superseded by {@link #insert(int, Object[], Object...) insert(int, T[], T...)} and
793     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
794     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
795     */
796    @Deprecated
797    public static <T> T[] add(final T[] array, final int index, final T element) {
798        final Class<T> clazz;
799        if (array != null) {
800            clazz = getComponentType(array);
801        } else if (element != null) {
802            clazz = ObjectUtils.getClass(element);
803        } else {
804            throw new IllegalArgumentException("Array and element cannot both be null");
805        }
806        return (T[]) add(array, index, element, clazz);
807    }
808
809    /**
810     * Copies the given array and adds the given element at the end of the new array.
811     * <p>
812     * The new array contains the same elements of the input
813     * array plus the given element in the last position. The component type of
814     * the new array is the same as that of the input array.
815     * </p>
816     * <p>
817     * If the input array is {@code null}, a new one element array is returned
818     * whose component type is the same as the element, unless the element itself is null,
819     * in which case the return type is Object[]
820     * </p>
821     * <pre>
822     * ArrayUtils.add(null, null)      = Throws {@link IllegalArgumentException}
823     * ArrayUtils.add(null, "a")       = ["a"]
824     * ArrayUtils.add(["a"], null)     = ["a", null]
825     * ArrayUtils.add(["a"], "b")      = ["a", "b"]
826     * ArrayUtils.add(["a", "b"], "c") = ["a", "b", "c"]
827     * </pre>
828     *
829     * @param <T> The component type of the array.
830     * @param array  The array to "add" the element to, may be {@code null}.
831     * @param element  The object to add, may be {@code null}.
832     * @return A new array containing the existing elements plus the new element
833     * The returned array type will be that of the input array (unless null),
834     * in which case it will have the same type as the element.
835     * If both are null, an IllegalArgumentException is thrown.
836     * @throws IllegalArgumentException Thrown if both arguments are null.
837     * @since 2.1
838     */
839    public static <T> T[] add(final T[] array, final T element) {
840        final Class<?> type;
841        if (array != null) {
842            type = array.getClass().getComponentType();
843        } else if (element != null) {
844            type = element.getClass();
845        } else {
846            throw new IllegalArgumentException("Arguments cannot both be null");
847        }
848        @SuppressWarnings("unchecked") // type must be T
849        final
850        T[] newArray = (T[]) copyArrayGrow1(array, type);
851        newArray[newArray.length - 1] = element;
852        return newArray;
853    }
854
855    /**
856     * Adds all the elements of the given arrays into a new array.
857     * <p>
858     * The new array contains all of the element of {@code array1} followed
859     * by all of the elements {@code array2}. When an array is returned, it is always
860     * a new array.
861     * </p>
862     * <pre>
863     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
864     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
865     * ArrayUtils.addAll([], [])         = []
866     * ArrayUtils.addAll(null, null)     = null
867     * </pre>
868     *
869     * @param array1  The first array whose elements are added to the new array.
870     * @param array2  The second array whose elements are added to the new array.
871     * @return The new boolean[] array or {@code null}.
872     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
873     * @since 2.1
874     */
875    public static boolean[] addAll(final boolean[] array1, final boolean... array2) {
876        if (array1 == null) {
877            return clone(array2);
878        }
879        if (array2 == null) {
880            return clone(array1);
881        }
882        final boolean[] joinedArray = new boolean[addExact(array1.length, array2)];
883        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
884        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
885        return joinedArray;
886    }
887
888    /**
889     * Adds all the elements of the given arrays into a new array.
890     * <p>
891     * The new array contains all of the element of {@code array1} followed
892     * by all of the elements {@code array2}. When an array is returned, it is always
893     * a new array.
894     * </p>
895     * <pre>
896     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
897     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
898     * ArrayUtils.addAll([], [])         = []
899     * ArrayUtils.addAll(null, null)     = null
900     * </pre>
901     *
902     * @param array1  The first array whose elements are added to the new array.
903     * @param array2  The second array whose elements are added to the new array.
904     * @return The new byte[] array or {@code null}.
905     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
906     * @since 2.1
907     */
908    public static byte[] addAll(final byte[] array1, final byte... array2) {
909        if (array1 == null) {
910            return clone(array2);
911        }
912        if (array2 == null) {
913            return clone(array1);
914        }
915        final byte[] joinedArray = new byte[addExact(array1.length, array2)];
916        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
917        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
918        return joinedArray;
919    }
920
921    /**
922     * Adds all the elements of the given arrays into a new array.
923     * <p>
924     * The new array contains all of the element of {@code array1} followed
925     * by all of the elements {@code array2}. When an array is returned, it is always
926     * a new array.
927     * </p>
928     * <pre>
929     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
930     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
931     * ArrayUtils.addAll([], [])         = []
932     * ArrayUtils.addAll(null, null)     = null
933     * </pre>
934     *
935     * @param array1  The first array whose elements are added to the new array.
936     * @param array2  The second array whose elements are added to the new array.
937     * @return The new char[] array or {@code null}.
938     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
939     * @since 2.1
940     */
941    public static char[] addAll(final char[] array1, final char... array2) {
942        if (array1 == null) {
943            return clone(array2);
944        }
945        if (array2 == null) {
946            return clone(array1);
947        }
948        final char[] joinedArray = new char[addExact(array1.length, array2)];
949        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
950        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
951        return joinedArray;
952    }
953
954    /**
955     * Adds all the elements of the given arrays into a new array.
956     * <p>
957     * The new array contains all of the element of {@code array1} followed
958     * by all of the elements {@code array2}. When an array is returned, it is always
959     * a new array.
960     * </p>
961     * <pre>
962     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
963     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
964     * ArrayUtils.addAll([], [])         = []
965     * ArrayUtils.addAll(null, null)     = null
966     * </pre>
967     *
968     * @param array1  The first array whose elements are added to the new array.
969     * @param array2  The second array whose elements are added to the new array.
970     * @return The new double[] array or {@code null}.
971     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
972     * @since 2.1
973     */
974    public static double[] addAll(final double[] array1, final double... array2) {
975        if (array1 == null) {
976            return clone(array2);
977        }
978        if (array2 == null) {
979            return clone(array1);
980        }
981        final double[] joinedArray = new double[addExact(array1.length, array2)];
982        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
983        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
984        return joinedArray;
985    }
986
987    /**
988     * Adds all the elements of the given arrays into a new array.
989     * <p>
990     * The new array contains all of the element of {@code array1} followed
991     * by all of the elements {@code array2}. When an array is returned, it is always
992     * a new array.
993     * </p>
994     * <pre>
995     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
996     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
997     * ArrayUtils.addAll([], [])         = []
998     * ArrayUtils.addAll(null, null)     = null
999     * </pre>
1000     *
1001     * @param array1  The first array whose elements are added to the new array.
1002     * @param array2  The second array whose elements are added to the new array.
1003     * @return The new float[] array or {@code null}.
1004     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1005     * @since 2.1
1006     */
1007    public static float[] addAll(final float[] array1, final float... array2) {
1008        if (array1 == null) {
1009            return clone(array2);
1010        }
1011        if (array2 == null) {
1012            return clone(array1);
1013        }
1014        final float[] joinedArray = new float[addExact(array1.length, array2)];
1015        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1016        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1017        return joinedArray;
1018    }
1019
1020    /**
1021     * Adds all the elements of the given arrays into a new array.
1022     * <p>
1023     * The new array contains all of the element of {@code array1} followed
1024     * by all of the elements {@code array2}. When an array is returned, it is always
1025     * a new array.
1026     * </p>
1027     * <pre>
1028     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1029     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1030     * ArrayUtils.addAll([], [])         = []
1031     * ArrayUtils.addAll(null, null)     = null
1032     * </pre>
1033     *
1034     * @param array1  The first array whose elements are added to the new array.
1035     * @param array2  The second array whose elements are added to the new array.
1036     * @return The new int[] array or {@code null}.
1037     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1038     * @since 2.1
1039     */
1040    public static int[] addAll(final int[] array1, final int... array2) {
1041        if (array1 == null) {
1042            return clone(array2);
1043        }
1044        if (array2 == null) {
1045            return clone(array1);
1046        }
1047        final int[] joinedArray = new int[addExact(array1.length, array2)];
1048        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1049        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1050        return joinedArray;
1051    }
1052
1053    /**
1054     * Adds all the elements of the given arrays into a new array.
1055     * <p>
1056     * The new array contains all of the element of {@code array1} followed
1057     * by all of the elements {@code array2}. When an array is returned, it is always
1058     * a new array.
1059     * </p>
1060     * <pre>
1061     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1062     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1063     * ArrayUtils.addAll([], [])         = []
1064     * ArrayUtils.addAll(null, null)     = null
1065     * </pre>
1066     *
1067     * @param array1  The first array whose elements are added to the new array.
1068     * @param array2  The second array whose elements are added to the new array.
1069     * @return The new long[] array or {@code null}.
1070     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1071     * @since 2.1
1072     */
1073    public static long[] addAll(final long[] array1, final long... array2) {
1074        if (array1 == null) {
1075            return clone(array2);
1076        }
1077        if (array2 == null) {
1078            return clone(array1);
1079        }
1080        final long[] joinedArray = new long[addExact(array1.length, array2)];
1081        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1082        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1083        return joinedArray;
1084    }
1085
1086    /**
1087     * Adds all the elements of the given arrays into a new array.
1088     * <p>
1089     * The new array contains all of the element of {@code array1} followed
1090     * by all of the elements {@code array2}. When an array is returned, it is always
1091     * a new array.
1092     * </p>
1093     * <pre>
1094     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1095     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1096     * ArrayUtils.addAll([], [])         = []
1097     * ArrayUtils.addAll(null, null)     = null
1098     * </pre>
1099     *
1100     * @param array1  The first array whose elements are added to the new array.
1101     * @param array2  The second array whose elements are added to the new array.
1102     * @return The new short[] array or {@code null}.
1103     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1104     * @since 2.1
1105     */
1106    public static short[] addAll(final short[] array1, final short... array2) {
1107        if (array1 == null) {
1108            return clone(array2);
1109        }
1110        if (array2 == null) {
1111            return clone(array1);
1112        }
1113        final short[] joinedArray = new short[addExact(array1.length, array2)];
1114        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1115        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1116        return joinedArray;
1117    }
1118
1119    /**
1120     * Adds all the elements of the given arrays into a new array.
1121     * <p>
1122     * The new array contains all of the element of {@code array1} followed
1123     * by all of the elements {@code array2}. When an array is returned, it is always
1124     * a new array.
1125     * </p>
1126     * <pre>
1127     * ArrayUtils.addAll(null, null)     = null
1128     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1129     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1130     * ArrayUtils.addAll([], [])         = []
1131     * ArrayUtils.addAll(null, null)     = null
1132     * ArrayUtils.addAll([null], [null]) = [null, null]
1133     * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
1134     * </pre>
1135     *
1136     * @param <T> The component type of the array.
1137     * @param array1  The first array whose elements are added to the new array, may be {@code null}.
1138     * @param array2  The second array whose elements are added to the new array, may be {@code null}.
1139     * @return The new array, {@code null} if both arrays are {@code null}.
1140     *      The type of the new array is the type of the first array,
1141     *      unless the first array is null, in which case the type is the same as the second array.
1142     * @throws IllegalArgumentException Thrown if the array types are incompatible or if the total array length exceeds
1143     *         {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1144     * @since 2.1
1145     */
1146    public static <T> T[] addAll(final T[] array1, @SuppressWarnings("unchecked") final T... array2) {
1147        if (array1 == null) {
1148            return clone(array2);
1149        }
1150        if (array2 == null) {
1151            return clone(array1);
1152        }
1153        final Class<T> type1 = getComponentType(array1);
1154        final T[] joinedArray = arraycopy(array1, 0, 0, array1.length, () -> newInstance(type1, addExact(array1.length, array2)));
1155        try {
1156            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1157        } catch (final ArrayStoreException ase) {
1158            // Check if problem was due to incompatible types
1159            /*
1160             * We do this here, rather than before the copy because: - it would be a wasted check most of the time - safer, in case check turns out to be too
1161             * strict
1162             */
1163            final Class<?> type2 = array2.getClass().getComponentType();
1164            if (!type1.isAssignableFrom(type2)) {
1165                throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of " + type1.getName(), ase);
1166            }
1167            throw ase; // No, so rethrow original
1168        }
1169        return joinedArray;
1170    }
1171
1172    /**
1173     * Safely adds the length of an array to a running total, checking for overflow.
1174     *
1175     * @param totalLength The current accumulated length
1176     * @param array The array whose length should be added (can be {@code null},
1177     *              in which case its length is considered 0)
1178     * @return The new total length after adding the array's length
1179     * @throws IllegalArgumentException Thrown if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1180     */
1181    private static int addExact(final int totalLength, final Object array) {
1182        try {
1183            final int length = MathBridge.addExact(totalLength, getLength(array));
1184            if (length > SAFE_MAX_ARRAY_LENGTH) {
1185                throw new IllegalArgumentException("Total arrays length exceed " + SAFE_MAX_ARRAY_LENGTH);
1186            }
1187            return length;
1188        } catch (final ArithmeticException exception) {
1189            throw new IllegalArgumentException("Total arrays length exceed " + SAFE_MAX_ARRAY_LENGTH);
1190        }
1191    }
1192
1193    /**
1194     * Copies the given array and adds the given element at the beginning of the new array.
1195     * <p>
1196     * The new array contains the same elements of the input array plus the given element in the first position. The
1197     * component type of the new array is the same as that of the input array.
1198     * </p>
1199     * <p>
1200     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1201     * element.
1202     * </p>
1203     * <pre>
1204     * ArrayUtils.addFirst(null, true)          = [true]
1205     * ArrayUtils.addFirst([true], false)       = [false, true]
1206     * ArrayUtils.addFirst([true, false], true) = [true, true, false]
1207     * </pre>
1208     *
1209     * @param array The array to "add" the element to, may be {@code null}.
1210     * @param element The object to add.
1211     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1212     *         the input array (unless null), in which case it will have the same type as the element.
1213     * @since 3.10
1214     */
1215    public static boolean[] addFirst(final boolean[] array, final boolean element) {
1216        return array == null ? add(array, element) : insert(0, array, element);
1217    }
1218
1219    /**
1220     * Copies the given array and adds the given element at the beginning of the new array.
1221     * <p>
1222     * The new array contains the same elements of the input array plus the given element in the first position. The
1223     * component type of the new array is the same as that of the input array.
1224     * </p>
1225     * <p>
1226     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1227     * element.
1228     * </p>
1229     * <pre>
1230     * ArrayUtils.addFirst(null, 1)   = [1]
1231     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1232     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1233     * </pre>
1234     *
1235     * @param array The array to "add" the element to, may be {@code null}.
1236     * @param element The object to add.
1237     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1238     *         the input array (unless null), in which case it will have the same type as the element.
1239     * @since 3.10
1240     */
1241    public static byte[] addFirst(final byte[] array, final byte element) {
1242        return array == null ? add(array, element) : insert(0, array, element);
1243    }
1244
1245    /**
1246     * Copies the given array and adds the given element at the beginning of the new array.
1247     * <p>
1248     * The new array contains the same elements of the input array plus the given element in the first position. The
1249     * component type of the new array is the same as that of the input array.
1250     * </p>
1251     * <p>
1252     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1253     * element.
1254     * </p>
1255     * <pre>
1256     * ArrayUtils.addFirst(null, '1')       = ['1']
1257     * ArrayUtils.addFirst(['1'], '0')      = ['0', '1']
1258     * ArrayUtils.addFirst(['1', '0'], '1') = ['1', '1', '0']
1259     * </pre>
1260     *
1261     * @param array The array to "add" the element to, may be {@code null}.
1262     * @param element The object to add.
1263     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1264     *         the input array (unless null), in which case it will have the same type as the element.
1265     * @since 3.10
1266     */
1267    public static char[] addFirst(final char[] array, final char element) {
1268        return array == null ? add(array, element) : insert(0, array, element);
1269    }
1270
1271    /**
1272     * Copies the given array and adds the given element at the beginning of the new array.
1273     * <p>
1274     * The new array contains the same elements of the input array plus the given element in the first position. The
1275     * component type of the new array is the same as that of the input array.
1276     * </p>
1277     * <p>
1278     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1279     * element.
1280     * </p>
1281     * <pre>
1282     * ArrayUtils.addFirst(null, 1)   = [1]
1283     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1284     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1285     * </pre>
1286     *
1287     * @param array The array to "add" the element to, may be {@code null}.
1288     * @param element The object to add.
1289     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1290     *         the input array (unless null), in which case it will have the same type as the element.
1291     * @since 3.10
1292     */
1293    public static double[] addFirst(final double[] array, final double element) {
1294        return array == null ? add(array, element) : insert(0, array, element);
1295    }
1296
1297    /**
1298     * Copies the given array and adds the given element at the beginning of the new array.
1299     * <p>
1300     * The new array contains the same elements of the input array plus the given element in the first position. The
1301     * component type of the new array is the same as that of the input array.
1302     * </p>
1303     * <p>
1304     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1305     * element.
1306     * </p>
1307     * <pre>
1308     * ArrayUtils.addFirst(null, 1)   = [1]
1309     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1310     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1311     * </pre>
1312     *
1313     * @param array The array to "add" the element to, may be {@code null}.
1314     * @param element The object to add.
1315     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1316     *         the input array (unless null), in which case it will have the same type as the element.
1317     * @since 3.10
1318     */
1319    public static float[] addFirst(final float[] array, final float element) {
1320        return array == null ? add(array, element) : insert(0, array, element);
1321    }
1322
1323    /**
1324     * Copies the given array and adds the given element at the beginning of the new array.
1325     * <p>
1326     * The new array contains the same elements of the input array plus the given element in the first position. The
1327     * component type of the new array is the same as that of the input array.
1328     * </p>
1329     * <p>
1330     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1331     * element.
1332     * </p>
1333     * <pre>
1334     * ArrayUtils.addFirst(null, 1)   = [1]
1335     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1336     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1337     * </pre>
1338     *
1339     * @param array The array to "add" the element to, may be {@code null}.
1340     * @param element The object to add.
1341     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1342     *         the input array (unless null), in which case it will have the same type as the element.
1343     * @since 3.10
1344     */
1345    public static int[] addFirst(final int[] array, final int element) {
1346        return array == null ? add(array, element) : insert(0, array, element);
1347    }
1348
1349    /**
1350     * Copies the given array and adds the given element at the beginning of the new array.
1351     * <p>
1352     * The new array contains the same elements of the input array plus the given element in the first position. The
1353     * component type of the new array is the same as that of the input array.
1354     * </p>
1355     * <p>
1356     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1357     * element.
1358     * </p>
1359     * <pre>
1360     * ArrayUtils.addFirst(null, 1)   = [1]
1361     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1362     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1363     * </pre>
1364     *
1365     * @param array The array to "add" the element to, may be {@code null}.
1366     * @param element The object to add.
1367     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1368     *         the input array (unless null), in which case it will have the same type as the element.
1369     * @since 3.10
1370     */
1371    public static long[] addFirst(final long[] array, final long element) {
1372        return array == null ? add(array, element) : insert(0, array, element);
1373    }
1374
1375    /**
1376     * Copies the given array and adds the given element at the beginning of the new array.
1377     * <p>
1378     * The new array contains the same elements of the input array plus the given element in the first position. The
1379     * component type of the new array is the same as that of the input array.
1380     * </p>
1381     * <p>
1382     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1383     * element.
1384     * </p>
1385     * <pre>
1386     * ArrayUtils.addFirst(null, 1)   = [1]
1387     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1388     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1389     * </pre>
1390     *
1391     * @param array The array to "add" the element to, may be {@code null}.
1392     * @param element The object to add.
1393     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1394     *         the input array (unless null), in which case it will have the same type as the element.
1395     * @since 3.10
1396     */
1397    public static short[] addFirst(final short[] array, final short element) {
1398        return array == null ? add(array, element) : insert(0, array, element);
1399    }
1400
1401    /**
1402     * Copies the given array and adds the given element at the beginning of the new array.
1403     * <p>
1404     * The new array contains the same elements of the input array plus the given element in the first position. The
1405     * component type of the new array is the same as that of the input array.
1406     * </p>
1407     * <p>
1408     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1409     * element, unless the element itself is null, in which case the return type is Object[]
1410     * </p>
1411     * <pre>
1412     * ArrayUtils.addFirst(null, null)      = Throws {@link IllegalArgumentException}
1413     * ArrayUtils.addFirst(null, "a")       = ["a"]
1414     * ArrayUtils.addFirst(["a"], null)     = [null, "a"]
1415     * ArrayUtils.addFirst(["a"], "b")      = ["b", "a"]
1416     * ArrayUtils.addFirst(["a", "b"], "c") = ["c", "a", "b"]
1417     * </pre>
1418     *
1419     * @param <T> The component type of the array.
1420     * @param array The array to "add" the element to, may be {@code null}.
1421     * @param element The object to add, may be {@code null}.
1422     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1423     *         the input array (unless null), in which case it will have the same type as the element. If both are null,
1424     *         an IllegalArgumentException is thrown.
1425     * @throws IllegalArgumentException Thrown if both arguments are null.
1426     * @since 3.10
1427     */
1428    public static <T> T[] addFirst(final T[] array, final T element) {
1429        return array == null ? add(array, element) : insert(0, array, element);
1430    }
1431
1432    /**
1433     * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array.
1434     *
1435     * @param <T>       the type.
1436     * @param source    The source array.
1437     * @param sourcePos starting position in the source array.
1438     * @param destPos   starting position in the destination data.
1439     * @param length    The number of array elements to be copied.
1440     * @param allocator allocates the array to populate and return.
1441     * @return dest
1442     * @throws IndexOutOfBoundsException Thrown if copying would cause access of data outside array bounds.
1443     * @throws ArrayStoreException       Thrown if an element in the {@code src} array could not be stored into the {@code dest} array because of a type
1444     *                                   mismatch.
1445     * @throws NullPointerException      Thrown if either {@code src} or {@code dest} is {@code null}.
1446     * @since 3.15.0
1447     */
1448    public static <T> T arraycopy(final T source, final int sourcePos, final int destPos, final int length, final Function<Integer, T> allocator) {
1449        return arraycopy(source, sourcePos, allocator.apply(length), destPos, length);
1450    }
1451
1452    /**
1453     * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array.
1454     *
1455     * @param <T>       the type.
1456     * @param source    The source array.
1457     * @param sourcePos starting position in the source array.
1458     * @param destPos   starting position in the destination data.
1459     * @param length    The number of array elements to be copied.
1460     * @param allocator allocates the array to populate and return.
1461     * @return dest
1462     * @throws IndexOutOfBoundsException Thrown if copying would cause access of data outside array bounds.
1463     * @throws ArrayStoreException       Thrown if an element in the {@code src} array could not be stored into the {@code dest} array because of a type
1464     *                                   mismatch.
1465     * @throws NullPointerException      Thrown if either {@code src} or {@code dest} is {@code null}.
1466     * @since 3.15.0
1467     */
1468    public static <T> T arraycopy(final T source, final int sourcePos, final int destPos, final int length, final Supplier<T> allocator) {
1469        return arraycopy(source, sourcePos, allocator.get(), destPos, length);
1470    }
1471
1472    /**
1473     * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array.
1474     *
1475     * @param <T>       the type.
1476     * @param source    The source array.
1477     * @param sourcePos starting position in the source array.
1478     * @param dest      The destination array.
1479     * @param destPos   starting position in the destination data.
1480     * @param length    The number of array elements to be copied.
1481     * @return dest
1482     * @throws IndexOutOfBoundsException Thrown if copying would cause access of data outside array bounds.
1483     * @throws ArrayStoreException       Thrown if an element in the {@code src} array could not be stored into the {@code dest} array because of a type
1484     *                                   mismatch.
1485     * @throws NullPointerException      Thrown if either {@code src} or {@code dest} is {@code null}.
1486     * @since 3.15.0
1487     */
1488    public static <T> T arraycopy(final T source, final int sourcePos, final T dest, final int destPos, final int length) {
1489        System.arraycopy(source, sourcePos, dest, destPos, length);
1490        return dest;
1491    }
1492
1493    /**
1494     * Clones an array or returns {@code null}.
1495     * <p>
1496     * This method returns {@code null} for a {@code null} input array.
1497     * </p>
1498     *
1499     * @param array The array to clone, may be {@code null}.
1500     * @return The cloned array, {@code null} if {@code null} input.
1501     */
1502    public static boolean[] clone(final boolean[] array) {
1503        return array != null ? array.clone() : null;
1504    }
1505
1506    /**
1507     * Clones an array or returns {@code null}.
1508     * <p>
1509     * This method returns {@code null} for a {@code null} input array.
1510     * </p>
1511     *
1512     * @param array The array to clone, may be {@code null}.
1513     * @return The cloned array, {@code null} if {@code null} input.
1514     */
1515    public static byte[] clone(final byte[] array) {
1516        return array != null ? array.clone() : null;
1517    }
1518
1519    /**
1520     * Clones an array or returns {@code null}.
1521     * <p>
1522     * This method returns {@code null} for a {@code null} input array.
1523     * </p>
1524     *
1525     * @param array The array to clone, may be {@code null}.
1526     * @return The cloned array, {@code null} if {@code null} input.
1527     */
1528    public static char[] clone(final char[] array) {
1529        return array != null ? array.clone() : null;
1530    }
1531
1532    /**
1533     * Clones an array or returns {@code null}.
1534     * <p>
1535     * This method returns {@code null} for a {@code null} input array.
1536     * </p>
1537     *
1538     * @param array The array to clone, may be {@code null}.
1539     * @return The cloned array, {@code null} if {@code null} input.
1540     */
1541    public static double[] clone(final double[] array) {
1542        return array != null ? array.clone() : null;
1543    }
1544
1545    /**
1546     * Clones an array or returns {@code null}.
1547     * <p>
1548     * This method returns {@code null} for a {@code null} input array.
1549     * </p>
1550     *
1551     * @param array The array to clone, may be {@code null}.
1552     * @return The cloned array, {@code null} if {@code null} input.
1553     */
1554    public static float[] clone(final float[] array) {
1555        return array != null ? array.clone() : null;
1556    }
1557
1558    /**
1559     * Clones an array or returns {@code null}.
1560     * <p>
1561     * This method returns {@code null} for a {@code null} input array.
1562     * </p>
1563     *
1564     * @param array The array to clone, may be {@code null}.
1565     * @return The cloned array, {@code null} if {@code null} input.
1566     */
1567    public static int[] clone(final int[] array) {
1568        return array != null ? array.clone() : null;
1569    }
1570
1571    /**
1572     * Clones an array or returns {@code null}.
1573     * <p>
1574     * This method returns {@code null} for a {@code null} input array.
1575     * </p>
1576     *
1577     * @param array The array to clone, may be {@code null}.
1578     * @return The cloned array, {@code null} if {@code null} input.
1579     */
1580    public static long[] clone(final long[] array) {
1581        return array != null ? array.clone() : null;
1582    }
1583
1584    /**
1585     * Clones an array or returns {@code null}.
1586     * <p>
1587     * This method returns {@code null} for a {@code null} input array.
1588     * </p>
1589     *
1590     * @param array The array to clone, may be {@code null}.
1591     * @return The cloned array, {@code null} if {@code null} input.
1592     */
1593    public static short[] clone(final short[] array) {
1594        return array != null ? array.clone() : null;
1595    }
1596
1597    /**
1598     * Shallow clones an array or returns {@code null}.
1599     * <p>
1600     * The objects in the array are not cloned, thus there is no special handling for multi-dimensional arrays.
1601     * </p>
1602     * <p>
1603     * This method returns {@code null} for a {@code null} input array.
1604     * </p>
1605     *
1606     * @param <T>   the component type of the array.
1607     * @param array The array to shallow clone, may be {@code null}.
1608     * @return The cloned array, {@code null} if {@code null} input.
1609     */
1610    public static <T> T[] clone(final T[] array) {
1611        return array != null ? array.clone() : null;
1612    }
1613
1614    /**
1615     * Concatenates multiple boolean arrays into a single array.
1616     * <p>
1617     * This method combines all input arrays in the order they are provided,
1618     * creating a new array that contains all elements from the input arrays.
1619     * The resulting array length is the sum of lengths of all non-null input arrays.
1620     * </p>
1621     *
1622     * @param arrays The arrays to concatenate. Can be empty, contain nulls,
1623     *               or be null itself (treated as empty varargs).
1624     * @return A new boolean array containing all elements from the input arrays
1625     *         in the order they appear, or an empty array if no elements are present.
1626     * @throws NullPointerException Thrown if the input array of arrays is null.
1627     * @throws IllegalArgumentException Thrown if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1628     * @since 3.21.0
1629     */
1630    public static boolean[] concat(final boolean[]... arrays) {
1631        int totalLength = 0;
1632        for (final boolean[] array : arrays) {
1633            totalLength = addExact(totalLength, array);
1634        }
1635        final boolean[] result = new boolean[totalLength];
1636        int currentPos = 0;
1637        for (final boolean[] array : arrays) {
1638            if (array != null && array.length > 0) {
1639                System.arraycopy(array, 0, result, currentPos, array.length);
1640                currentPos += array.length;
1641            }
1642        }
1643        return result;
1644    }
1645
1646    /**
1647     * Concatenates multiple byte arrays into a single array.
1648     * <p>
1649     * This method combines all input arrays in the order they are provided,
1650     * creating a new array that contains all elements from the input arrays.
1651     * The resulting array length is the sum of lengths of all non-null input arrays.
1652     * </p>
1653     *
1654     * @param arrays The arrays to concatenate. Can be empty, contain nulls,
1655     *               or be null itself (treated as empty varargs).
1656     * @return A new byte array containing all elements from the input arrays
1657     *         in the order they appear, or an empty array if no elements are present.
1658     * @throws NullPointerException Thrown if the input array of arrays is null.
1659     * @throws IllegalArgumentException Thrown if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1660     * @since 3.21.0
1661     */
1662    public static byte[] concat(final byte[]... arrays) {
1663        int totalLength = 0;
1664        for (final byte[] array : arrays) {
1665            totalLength = addExact(totalLength, array);
1666        }
1667        final byte[] result = new byte[totalLength];
1668        int currentPos = 0;
1669        for (final byte[] array : arrays) {
1670            if (array != null && array.length > 0) {
1671                System.arraycopy(array, 0, result, currentPos, array.length);
1672                currentPos += array.length;
1673            }
1674        }
1675        return result;
1676    }
1677
1678    /**
1679     * Concatenates multiple char arrays into a single array.
1680     * <p>
1681     * This method combines all input arrays in the order they are provided,
1682     * creating a new array that contains all elements from the input arrays.
1683     * The resulting array length is the sum of lengths of all non-null input arrays.
1684     * </p>
1685     *
1686     * @param arrays The arrays to concatenate. Can be empty, contain nulls,
1687     *               or be null itself (treated as empty varargs).
1688     * @return A new char array containing all elements from the input arrays
1689     *         in the order they appear, or an empty array if no elements are present.
1690     * @throws NullPointerException Thrown if the input array of arrays is null.
1691     * @throws IllegalArgumentException Thrown if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1692     * @since 3.21.0
1693     */
1694    public static char[] concat(final char[]... arrays) {
1695        int totalLength = 0;
1696        for (final char[] array : arrays) {
1697            totalLength = addExact(totalLength, array);
1698        }
1699        final char[] result = new char[totalLength];
1700        int currentPos = 0;
1701        for (final char[] array : arrays) {
1702            if (array != null && array.length > 0) {
1703                System.arraycopy(array, 0, result, currentPos, array.length);
1704                currentPos += array.length;
1705            }
1706        }
1707        return result;
1708    }
1709
1710    /**
1711     * Concatenates multiple double arrays into a single array.
1712     * <p>
1713     * This method combines all input arrays in the order they are provided,
1714     * creating a new array that contains all elements from the input arrays.
1715     * The resulting array length is the sum of lengths of all non-null input arrays.
1716     * </p>
1717     *
1718     * @param arrays The arrays to concatenate. Can be empty, contain nulls,
1719     *               or be null itself (treated as empty varargs).
1720     * @return A new double array containing all elements from the input arrays
1721     *         in the order they appear, or an empty array if no elements are present.
1722     * @throws NullPointerException Thrown if the input array of arrays is null.
1723     * @throws IllegalArgumentException Thrown if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1724     * @since 3.21.0
1725     */
1726    public static double[] concat(final double[]... arrays) {
1727        int totalLength = 0;
1728        for (final double[] array : arrays) {
1729            totalLength = addExact(totalLength, array);
1730        }
1731        final double[] result = new double[totalLength];
1732        int currentPos = 0;
1733        for (final double[] array : arrays) {
1734            if (array != null && array.length > 0) {
1735                System.arraycopy(array, 0, result, currentPos, array.length);
1736                currentPos += array.length;
1737            }
1738        }
1739        return result;
1740    }
1741
1742    /**
1743     * Concatenates multiple float arrays into a single array.
1744     * <p>
1745     * This method combines all input arrays in the order they are provided,
1746     * creating a new array that contains all elements from the input arrays.
1747     * The resulting array length is the sum of lengths of all non-null input arrays.
1748     * </p>
1749     *
1750     * @param arrays The arrays to concatenate. Can be empty, contain nulls,
1751     *               or be null itself (treated as empty varargs).
1752     * @return A new float array containing all elements from the input arrays
1753     *         in the order they appear, or an empty array if no elements are present.
1754     * @throws NullPointerException Thrown if the input array of arrays is null.
1755     * @throws IllegalArgumentException Thrown if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1756     * @since 3.21.0
1757     */
1758    public static float[] concat(final float[]... arrays) {
1759        int totalLength = 0;
1760        for (final float[] array : arrays) {
1761            totalLength = addExact(totalLength, array);
1762        }
1763        final float[] result = new float[totalLength];
1764        int currentPos = 0;
1765        for (final float[] array : arrays) {
1766            if (array != null && array.length > 0) {
1767                System.arraycopy(array, 0, result, currentPos, array.length);
1768                currentPos += array.length;
1769            }
1770        }
1771        return result;
1772    }
1773
1774    /**
1775     * Concatenates multiple int arrays into a single array.
1776     * <p>
1777     * This method combines all input arrays in the order they are provided,
1778     * creating a new array that contains all elements from the input arrays.
1779     * The resulting array length is the sum of lengths of all non-null input arrays.
1780     * </p>
1781     *
1782     * @param arrays The arrays to concatenate. Can be empty, contain nulls,
1783     *               or be null itself (treated as empty varargs).
1784     * @return A new int array containing all elements from the input arrays
1785     *         in the order they appear, or an empty array if no elements are present.
1786     * @throws NullPointerException Thrown if the input array of arrays is null.
1787     * @throws IllegalArgumentException Thrown if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1788     * @since 3.21.0
1789     */
1790    public static int[] concat(final int[]... arrays) {
1791        int totalLength = 0;
1792        for (final int[] array : arrays) {
1793            totalLength = addExact(totalLength, array);
1794        }
1795        final int[] result = new int[totalLength];
1796        int currentPos = 0;
1797        for (final int[] array : arrays) {
1798            if (array != null && array.length > 0) {
1799                System.arraycopy(array, 0, result, currentPos, array.length);
1800                currentPos += array.length;
1801            }
1802        }
1803        return result;
1804    }
1805
1806    /**
1807     * Concatenates multiple long arrays into a single array.
1808     * <p>
1809     * This method combines all input arrays in the order they are provided,
1810     * creating a new array that contains all elements from the input arrays.
1811     * The resulting array length is the sum of lengths of all non-null input arrays.
1812     * </p>
1813     *
1814     * @param arrays The arrays to concatenate. Can be empty, contain nulls,
1815     *               or be null itself (treated as empty varargs).
1816     * @return A new long array containing all elements from the input arrays
1817     *         in the order they appear, or an empty array if no elements are present.
1818     * @throws NullPointerException Thrown if the input array of arrays is null.
1819     * @throws IllegalArgumentException Thrown if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1820     * @since 3.21.0
1821     */
1822    public static long[] concat(final long[]... arrays) {
1823        int totalLength = 0;
1824        for (final long[] array : arrays) {
1825            totalLength = addExact(totalLength, array);
1826        }
1827        final long[] result = new long[totalLength];
1828        int currentPos = 0;
1829        for (final long[] array : arrays) {
1830            if (array != null && array.length > 0) {
1831                System.arraycopy(array, 0, result, currentPos, array.length);
1832                currentPos += array.length;
1833            }
1834        }
1835        return result;
1836    }
1837
1838    /**
1839     * Concatenates multiple short arrays into a single array.
1840     * <p>
1841     * This method combines all input arrays in the order they are provided,
1842     * creating a new array that contains all elements from the input arrays.
1843     * The resulting array length is the sum of lengths of all non-null input arrays.
1844     * </p>
1845     *
1846     * @param arrays The arrays to concatenate. Can be empty, contain nulls,
1847     *               or be null itself (treated as empty varargs).
1848     * @return A new short array containing all elements from the input arrays
1849     *         in the order they appear, or an empty array if no elements are present.
1850     * @throws NullPointerException Thrown if the input array of arrays is null.
1851     * @throws IllegalArgumentException Thrown if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1852     * @since 3.21.0
1853     */
1854    public static short[] concat(final short[]... arrays) {
1855        int totalLength = 0;
1856        for (final short[] array : arrays) {
1857            totalLength = addExact(totalLength, array);
1858        }
1859        final short[] result = new short[totalLength];
1860        int currentPos = 0;
1861        for (final short[] array : arrays) {
1862            if (array != null && array.length > 0) {
1863                System.arraycopy(array, 0, result, currentPos, array.length);
1864                currentPos += array.length;
1865            }
1866        }
1867        return result;
1868    }
1869
1870    /**
1871     * Checks if the value is in the given array.
1872     * <p>
1873     * The method returns {@code false} if a {@code null} array is passed in.
1874     * </p>
1875     *
1876     * @param array  The array to search.
1877     * @param valueToFind  The value to find.
1878     * @return {@code true} if the array contains the object.
1879     */
1880    public static boolean contains(final boolean[] array, final boolean valueToFind) {
1881        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1882    }
1883
1884    /**
1885     * Checks if the value is in the given array.
1886     * <p>
1887     * The method returns {@code false} if a {@code null} array is passed in.
1888     * </p>
1889     * <p>
1890     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1891     * {@link Arrays#sort(byte[])} and {@link Arrays#binarySearch(byte[], byte)}.
1892     * </p>
1893     *
1894     * @param array  The array to search.
1895     * @param valueToFind  The value to find.
1896     * @return {@code true} if the array contains the object.
1897     */
1898    public static boolean contains(final byte[] array, final byte valueToFind) {
1899        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1900    }
1901
1902    /**
1903     * Checks if the value is in the given array.
1904     * <p>
1905     * The method returns {@code false} if a {@code null} array is passed in.
1906     * </p>
1907     * <p>
1908     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1909     * {@link Arrays#sort(char[])} and {@link Arrays#binarySearch(char[], char)}.
1910     * </p>
1911     *
1912     * @param array  The array to search.
1913     * @param valueToFind  The value to find.
1914     * @return {@code true} if the array contains the object.
1915     * @since 2.1
1916     */
1917    public static boolean contains(final char[] array, final char valueToFind) {
1918        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1919    }
1920
1921    /**
1922     * Checks if the value is in the given array.
1923     * <p>
1924     * The method returns {@code false} if a {@code null} array is passed in.
1925     * </p>
1926     * <p>
1927     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1928     * {@link Arrays#sort(double[])} and {@link Arrays#binarySearch(double[], double)}.
1929     * </p>
1930     *
1931     * @param array  The array to search.
1932     * @param valueToFind  The value to find.
1933     * @return {@code true} if the array contains the object.
1934     */
1935    public static boolean contains(final double[] array, final double valueToFind) {
1936        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1937    }
1938
1939    /**
1940     * Checks if a value falling within the given tolerance is in the
1941     * given array.  If the array contains a value within the inclusive range
1942     * defined by (value - tolerance) to (value + tolerance).
1943     * <p>
1944     * The method returns {@code false} if a {@code null} array
1945     * is passed in.
1946     * </p>
1947     * <p>
1948     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1949     * {@link Arrays#sort(double[])} and {@link Arrays#binarySearch(double[], double)}.
1950     * </p>
1951     *
1952     * @param array  The array to search.
1953     * @param valueToFind  The value to find.
1954     * @param tolerance  The array contains the tolerance of the search.
1955     * @return true if value falling within tolerance is in array.
1956     */
1957    public static boolean contains(final double[] array, final double valueToFind, final double tolerance) {
1958        return indexOf(array, valueToFind, 0, tolerance) != INDEX_NOT_FOUND;
1959    }
1960
1961    /**
1962     * Checks if the value is in the given array.
1963     * <p>
1964     * The method returns {@code false} if a {@code null} array is passed in.
1965     * </p>
1966     * <p>
1967     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1968     * {@link Arrays#sort(float[])} and {@link Arrays#binarySearch(float[], float)}.
1969     * </p>
1970     *
1971     * @param array  The array to search.
1972     * @param valueToFind  The value to find.
1973     * @return {@code true} if the array contains the object.
1974     */
1975    public static boolean contains(final float[] array, final float valueToFind) {
1976        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1977    }
1978
1979    /**
1980     * Checks if the value is in the given array.
1981     * <p>
1982     * The method returns {@code false} if a {@code null} array is passed in.
1983     * </p>
1984     * <p>
1985     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1986     * {@link Arrays#sort(int[])} and {@link Arrays#binarySearch(int[], int)}.
1987     * </p>
1988     *
1989     * @param array  The array to search.
1990     * @param valueToFind  The value to find.
1991     * @return {@code true} if the array contains the object.
1992     */
1993    public static boolean contains(final int[] array, final int valueToFind) {
1994        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1995    }
1996
1997    /**
1998     * Checks if the value is in the given array.
1999     * <p>
2000     * The method returns {@code false} if a {@code null} array is passed in.
2001     * </p>
2002     * <p>
2003     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
2004     * {@link Arrays#sort(long[])} and {@link Arrays#binarySearch(long[], long)}.
2005     * </p>
2006     *
2007     * @param array  The array to search.
2008     * @param valueToFind  The value to find.
2009     * @return {@code true} if the array contains the object.
2010     */
2011    public static boolean contains(final long[] array, final long valueToFind) {
2012        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2013    }
2014
2015    /**
2016     * Checks if the object is in the given array.
2017     * <p>
2018     * The method returns {@code false} if a {@code null} array is passed in.
2019     * </p>
2020     * <p>
2021     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
2022     * {@link Arrays#sort(Object[], Comparator)} and {@link Arrays#binarySearch(Object[], Object)}.
2023     * </p>
2024     *
2025     * @param array  The array to search, may be {@code null}.
2026     * @param objectToFind  The object to find, may be {@code null}.
2027     * @return {@code true} if the array contains the object.
2028     */
2029    public static boolean contains(final Object[] array, final Object objectToFind) {
2030        return indexOf(array, objectToFind) != INDEX_NOT_FOUND;
2031    }
2032
2033    /**
2034     * Checks if the value is in the given array.
2035     * <p>
2036     * The method returns {@code false} if a {@code null} array is passed in.
2037     * </p>
2038     * <p>
2039     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
2040     * {@link Arrays#sort(short[])} and {@link Arrays#binarySearch(short[], short)}.
2041     * </p>
2042     *
2043     * @param array  The array to search.
2044     * @param valueToFind  The value to find.
2045     * @return {@code true} if the array contains the object.
2046     */
2047    public static boolean contains(final short[] array, final short valueToFind) {
2048        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2049    }
2050
2051    /**
2052     * Checks if any of the ints are in the given array.
2053     * <p>
2054     * The method returns {@code false} if a {@code null} array is passed in.
2055     * </p>
2056     * <p>
2057     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
2058     * {@link Arrays#sort(int[])} and {@link Arrays#binarySearch(int[], int)}.
2059     * </p>
2060     *
2061     * @param array         The array to search.
2062     * @param objectsToFind any of the ints to find.
2063     * @return {@code true} if the array contains any of the ints.
2064     * @since 3.18.0
2065     */
2066    public static boolean containsAny(final int[] array, final int... objectsToFind) {
2067        return IntStreams.of(objectsToFind).anyMatch(e -> contains(array, e));
2068    }
2069
2070    /**
2071     * Checks if any of the objects are in the given array.
2072     * <p>
2073     * The method returns {@code false} if a {@code null} array is passed in.
2074     * </p>
2075     * <p>
2076     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
2077     * {@link Arrays#sort(Object[], Comparator)} and {@link Arrays#binarySearch(Object[], Object)}.
2078     * </p>
2079     *
2080     * @param array         The array to search, may be {@code null}.
2081     * @param objectsToFind any of the objects to find, may be {@code null}.
2082     * @return {@code true} if the array contains any of the objects.
2083     * @since 3.13.0
2084     */
2085    public static boolean containsAny(final Object[] array, final Object... objectsToFind) {
2086        return Streams.of(objectsToFind).anyMatch(e -> contains(array, e));
2087    }
2088
2089    /**
2090     * Returns a copy of the given array of size 1 greater than the argument.
2091     * The last value of the array is left to the default value.
2092     *
2093     * @param array The array to copy, must not be {@code null}.
2094     * @param newArrayComponentType If {@code array} is {@code null}, create a
2095     * size 1 array of this type.
2096     * @return A new copy of the array of size 1 greater than the input.
2097     */
2098    private static Object copyArrayGrow1(final Object array, final Class<?> newArrayComponentType) {
2099        if (array != null) {
2100            final int arrayLength = Array.getLength(array);
2101            final Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
2102            System.arraycopy(array, 0, newArray, 0, arrayLength);
2103            return newArray;
2104        }
2105        return Array.newInstance(newArrayComponentType, 1);
2106    }
2107
2108    /**
2109     * Gets the nTh element of an array or null if the index is out of bounds or the array is null.
2110     *
2111     * @param <T> The type of array elements.
2112     * @param array The array to index.
2113     * @param index The index.
2114     * @return The nTh element of an array or null if the index is out of bounds or the array is null.
2115     * @since 3.11
2116     */
2117    public static <T> T get(final T[] array, final int index) {
2118        return get(array, index, null);
2119    }
2120
2121    /**
2122     * Gets the nTh element of an array or a default value if the index is out of bounds.
2123     *
2124     * @param <T> The type of array elements.
2125     * @param array The array to index.
2126     * @param index The index.
2127     * @param defaultValue The return value of the given index is out of bounds.
2128     * @return The nTh element of an array or a default value if the index is out of bounds.
2129     * @since 3.11
2130     */
2131    public static <T> T get(final T[] array, final int index, final T defaultValue) {
2132        return isArrayIndexValid(array, index) ? array[index] : defaultValue;
2133    }
2134
2135    /**
2136     * Gets an array's component type.
2137     *
2138     * @param <T> The array type.
2139     * @param array The array.
2140     * @return The component type.
2141     * @since 3.13.0
2142     */
2143    public static <T> Class<T> getComponentType(final T[] array) {
2144        return ClassUtils.getComponentType(ObjectUtils.getClass(array));
2145    }
2146
2147    /**
2148     * Gets the number of dimensions of an array.
2149     * <p>
2150     * The <a href="https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.3">JVM specification</a> limits the number of dimensions to 255.
2151     * </p>
2152     *
2153     * @param array The array, may be {@code null}.
2154     * @return The number of dimensions, 0 if the input is null or not an array. The JVM specification limits the number of dimensions to 255.
2155     * @since 3.21.0
2156     * @see <a href="https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.3">JVM specification Field Descriptors</a>
2157     */
2158    public static int getDimensions(final Object array) {
2159        int dimensions = 0;
2160        if (array != null) {
2161            Class<?> arrayClass = array.getClass();
2162            while (arrayClass.isArray()) {
2163                dimensions++;
2164                arrayClass = arrayClass.getComponentType();
2165            }
2166        }
2167        return dimensions;
2168    }
2169
2170    /**
2171     * Gets the length of the specified array.
2172     * This method handles {@link Object} arrays and primitive arrays.
2173     * <p>
2174     * If the input array is {@code null}, {@code 0} is returned.
2175     * </p>
2176     * <pre>
2177     * ArrayUtils.getLength(null)            = 0
2178     * ArrayUtils.getLength([])              = 0
2179     * ArrayUtils.getLength([null])          = 1
2180     * ArrayUtils.getLength([true, false])   = 2
2181     * ArrayUtils.getLength([1, 2, 3])       = 3
2182     * ArrayUtils.getLength(["a", "b", "c"]) = 3
2183     * </pre>
2184     *
2185     * @param array  The array to retrieve the length from, may be {@code null}.
2186     * @return The length of the array, or {@code 0} if the array is {@code null}.
2187     * @throws IllegalArgumentException Thrown if the object argument is not an array.
2188     * @since 2.1
2189     */
2190    public static int getLength(final Object array) {
2191        return array != null ? Array.getLength(array) : 0;
2192    }
2193
2194    /**
2195     * Gets a hash code for an array handling multidimensional arrays.
2196     * <p>
2197     * Multi-dimensional primitive arrays are also handled by this method.
2198     * </p>
2199     *
2200     * @param array  The array to get a hash code for, may be {@code null}.
2201     * @return A hash code for the array.
2202     * @see HashCodeBuilder
2203     */
2204    public static int hashCode(final Object array) {
2205        return new HashCodeBuilder().append(array).toHashCode();
2206    }
2207
2208    static <K> void increment(final Map<K, MutableInt> occurrences, final K boxed) {
2209        occurrences.computeIfAbsent(boxed, k -> new MutableInt()).increment();
2210    }
2211
2212    /**
2213     * Finds the indices of the given value in the array.
2214     * <p>
2215     * This method returns an empty BitSet for a {@code null} input array.
2216     * </p>
2217     *
2218     * @param array  The array to search for the object, may be {@code null}.
2219     * @param valueToFind  The value to find.
2220     * @return A BitSet of all the indices of the value within the array,
2221     *  an empty BitSet if not found or {@code null} array input.
2222     * @since 3.10
2223     */
2224    public static BitSet indexesOf(final boolean[] array, final boolean valueToFind) {
2225        return indexesOf(array, valueToFind, 0);
2226    }
2227
2228    /**
2229     * Finds the indices of the given value in the array starting at the given index.
2230     * <p>
2231     * This method returns an empty BitSet for a {@code null} input array.
2232     * </p>
2233     * <p>
2234     * A negative startIndex is treated as zero. A startIndex larger than the array length will return an empty BitSet ({@code -1}).
2235     * </p>
2236     *
2237     * @param array       The array to search for the object, may be {@code null}.
2238     * @param valueToFind The value to find.
2239     * @param startIndex  The index to start searching.
2240     * @return A BitSet of all the indices of the value within the array, an empty BitSet if not found or {@code null} array input.
2241     * @since 3.10
2242     */
2243    public static BitSet indexesOf(final boolean[] array, final boolean valueToFind, int startIndex) {
2244        final BitSet bitSet = new BitSet();
2245        if (array != null) {
2246            while (startIndex < array.length) {
2247                startIndex = indexOf(array, valueToFind, startIndex);
2248                if (startIndex == INDEX_NOT_FOUND) {
2249                    break;
2250                }
2251                bitSet.set(startIndex);
2252                ++startIndex;
2253            }
2254        }
2255        return bitSet;
2256    }
2257
2258    /**
2259     * Finds the indices of the given value in the array.
2260     *
2261     * <p>
2262     * This method returns an empty BitSet for a {@code null} input array.
2263     * </p>
2264     *
2265     * @param array       The array to search for the object, may be {@code null}.
2266     * @param valueToFind The value to find.
2267     * @return A BitSet of all the indices of the value within the array, an empty BitSet if not found or {@code null} array input.
2268     * @since 3.10
2269     */
2270    public static BitSet indexesOf(final byte[] array, final byte valueToFind) {
2271        return indexesOf(array, valueToFind, 0);
2272    }
2273
2274    /**
2275     * Finds the indices of the given value in the array starting at the given index.
2276     *
2277     * <p>
2278     * This method returns an empty BitSet for a {@code null} input array.
2279     * </p>
2280     *
2281     * <p>
2282     * A negative startIndex is treated as zero. A startIndex larger than the array
2283     * length will return an empty BitSet.
2284     * </p>
2285     *
2286     * @param array  The array to search for the object, may be {@code null}.
2287     * @param valueToFind  The value to find.
2288     * @param startIndex  The index to start searching.
2289     * @return A BitSet of all the indices of the value within the array,
2290     *  an empty BitSet if not found or {@code null} array input.
2291     * @since 3.10
2292     */
2293    public static BitSet indexesOf(final byte[] array, final byte valueToFind, int startIndex) {
2294        final BitSet bitSet = new BitSet();
2295        if (array != null) {
2296            while (startIndex < array.length) {
2297                startIndex = indexOf(array, valueToFind, startIndex);
2298                if (startIndex == INDEX_NOT_FOUND) {
2299                    break;
2300                }
2301                bitSet.set(startIndex);
2302                ++startIndex;
2303            }
2304        }
2305        return bitSet;
2306    }
2307
2308    /**
2309     * Finds the indices of the given value in the array.
2310     *
2311     * <p>
2312     * This method returns an empty BitSet for a {@code null} input array.
2313     * </p>
2314     *
2315     * @param array  The array to search for the object, may be {@code null}.
2316     * @param valueToFind  The value to find.
2317     * @return A BitSet of all the indices of the value within the array,
2318     *  an empty BitSet if not found or {@code null} array input.
2319     * @since 3.10
2320     */
2321    public static BitSet indexesOf(final char[] array, final char valueToFind) {
2322        return indexesOf(array, valueToFind, 0);
2323    }
2324
2325    /**
2326     * Finds the indices of the given value in the array starting at the given index.
2327     *
2328     * <p>
2329     * This method returns an empty BitSet for a {@code null} input array.
2330     * </p>
2331     *
2332     * <p>
2333     * A negative startIndex is treated as zero. A startIndex larger than the array
2334     * length will return an empty BitSet.
2335     * </p>
2336     *
2337     * @param array  The array to search for the object, may be {@code null}.
2338     * @param valueToFind  The value to find.
2339     * @param startIndex  The index to start searching.
2340     * @return A BitSet of all the indices of the value within the array,
2341     *  an empty BitSet if not found or {@code null} array input.
2342     * @since 3.10
2343     */
2344    public static BitSet indexesOf(final char[] array, final char valueToFind, int startIndex) {
2345        final BitSet bitSet = new BitSet();
2346        if (array != null) {
2347            while (startIndex < array.length) {
2348                startIndex = indexOf(array, valueToFind, startIndex);
2349                if (startIndex == INDEX_NOT_FOUND) {
2350                    break;
2351                }
2352                bitSet.set(startIndex);
2353                ++startIndex;
2354            }
2355        }
2356        return bitSet;
2357    }
2358
2359    /**
2360     * Finds the indices of the given value in the array.
2361     *
2362     * <p>
2363     * This method returns an empty BitSet for a {@code null} input array.
2364     * </p>
2365     *
2366     * @param array  The array to search for the object, may be {@code null}.
2367     * @param valueToFind  The value to find.
2368     * @return A BitSet of all the indices of the value within the array,
2369     *  an empty BitSet if not found or {@code null} array input.
2370     * @since 3.10
2371     */
2372    public static BitSet indexesOf(final double[] array, final double valueToFind) {
2373        return indexesOf(array, valueToFind, 0);
2374    }
2375
2376    /**
2377     * Finds the indices of the given value within a given tolerance in the array.
2378     *
2379     * <p>
2380     * This method will return all the indices of the value which fall between the region
2381     * defined by valueToFind - tolerance and valueToFind + tolerance, each time between the nearest integers.
2382     * </p>
2383     *
2384     * <p>
2385     * This method returns an empty BitSet for a {@code null} input array.
2386     * </p>
2387     *
2388     * @param array  The array to search for the object, may be {@code null}.
2389     * @param valueToFind  The value to find.
2390     * @param tolerance tolerance of the search.
2391     * @return A BitSet of all the indices of the value within the array,
2392     *  an empty BitSet if not found or {@code null} array input.
2393     * @since 3.10
2394     */
2395    public static BitSet indexesOf(final double[] array, final double valueToFind, final double tolerance) {
2396        return indexesOf(array, valueToFind, 0, tolerance);
2397    }
2398
2399    /**
2400     * Finds the indices of the given value in the array starting at the given index.
2401     *
2402     * <p>
2403     * This method returns an empty BitSet for a {@code null} input array.
2404     * </p>
2405     *
2406     * <p>
2407     * A negative startIndex is treated as zero. A startIndex larger than the array
2408     * length will return an empty BitSet.
2409     * </p>
2410     *
2411     * @param array  The array to search for the object, may be {@code null}.
2412     * @param valueToFind  The value to find.
2413     * @param startIndex  The index to start searching.
2414     * @return A BitSet of the indices of the value within the array,
2415     *  an empty BitSet if not found or {@code null} array input.
2416     * @since 3.10
2417     */
2418    public static BitSet indexesOf(final double[] array, final double valueToFind, int startIndex) {
2419        final BitSet bitSet = new BitSet();
2420        if (array != null) {
2421            while (startIndex < array.length) {
2422                startIndex = indexOf(array, valueToFind, startIndex);
2423                if (startIndex == INDEX_NOT_FOUND) {
2424                    break;
2425                }
2426                bitSet.set(startIndex);
2427                ++startIndex;
2428            }
2429        }
2430        return bitSet;
2431    }
2432
2433    /**
2434     * Finds the indices of the given value in the array starting at the given index.
2435     *
2436     * <p>
2437     * This method will return the indices of the values which fall between the region
2438     * defined by valueToFind - tolerance and valueToFind + tolerance, between the nearest integers.
2439     * </p>
2440     *
2441     * <p>
2442     * This method returns an empty BitSet for a {@code null} input array.
2443     * </p>
2444     *
2445     * <p>
2446     * A negative startIndex is treated as zero. A startIndex larger than the array
2447     * length will return an empty BitSet.
2448     * </p>
2449     *
2450     * @param array  The array to search for the object, may be {@code null}.
2451     * @param valueToFind  The value to find.
2452     * @param startIndex  The index to start searching.
2453     * @param tolerance tolerance of the search.
2454     * @return A BitSet of the indices of the value within the array,
2455     *  an empty BitSet if not found or {@code null} array input.
2456     * @since 3.10
2457     */
2458    public static BitSet indexesOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
2459        final BitSet bitSet = new BitSet();
2460        if (array != null) {
2461            while (startIndex < array.length) {
2462                startIndex = indexOf(array, valueToFind, startIndex, tolerance);
2463                if (startIndex == INDEX_NOT_FOUND) {
2464                    break;
2465                }
2466                bitSet.set(startIndex);
2467                ++startIndex;
2468            }
2469        }
2470        return bitSet;
2471    }
2472
2473    /**
2474     * Finds the indices of the given value in the array.
2475     *
2476     * <p>
2477     * This method returns an empty BitSet for a {@code null} input array.
2478     * </p>
2479     *
2480     * @param array  The array to search for the object, may be {@code null}.
2481     * @param valueToFind  The value to find.
2482     * @return A BitSet of all the indices of the value within the array,
2483     *  an empty BitSet if not found or {@code null} array input.
2484     * @since 3.10
2485     */
2486    public static BitSet indexesOf(final float[] array, final float valueToFind) {
2487        return indexesOf(array, valueToFind, 0);
2488    }
2489
2490    /**
2491     * Finds the indices of the given value in the array starting at the given index.
2492     *
2493     * <p>
2494     * This method returns an empty BitSet for a {@code null} input array.
2495     * </p>
2496     *
2497     * <p>
2498     * A negative startIndex is treated as zero. A startIndex larger than the array
2499     * length will return empty BitSet.
2500     * </p>
2501     *
2502     * @param array  The array to search for the object, may be {@code null}.
2503     * @param valueToFind  The value to find.
2504     * @param startIndex  The index to start searching.
2505     * @return A BitSet of all the indices of the value within the array,
2506     *  an empty BitSet if not found or {@code null} array input.
2507     * @since 3.10
2508     */
2509    public static BitSet indexesOf(final float[] array, final float valueToFind, int startIndex) {
2510        final BitSet bitSet = new BitSet();
2511        if (array != null) {
2512            while (startIndex < array.length) {
2513                startIndex = indexOf(array, valueToFind, startIndex);
2514                if (startIndex == INDEX_NOT_FOUND) {
2515                    break;
2516                }
2517                bitSet.set(startIndex);
2518                ++startIndex;
2519            }
2520        }
2521        return bitSet;
2522    }
2523
2524    /**
2525     * Finds the indices of the given value in the array.
2526     *
2527     * <p>
2528     * This method returns an empty BitSet for a {@code null} input array.
2529     * </p>
2530     *
2531     * @param array  The array to search for the object, may be {@code null}.
2532     * @param valueToFind  The value to find.
2533     * @return A BitSet of all the indices of the value within the array,
2534     *  an empty BitSet if not found or {@code null} array input.
2535     * @since 3.10
2536     */
2537    public static BitSet indexesOf(final int[] array, final int valueToFind) {
2538        return indexesOf(array, valueToFind, 0);
2539    }
2540
2541    /**
2542     * Finds the indices of the given value in the array starting at the given index.
2543     *
2544     * <p>
2545     * This method returns an empty BitSet for a {@code null} input array.
2546     * </p>
2547     *
2548     * <p>
2549     * A negative startIndex is treated as zero. A startIndex larger than the array
2550     * length will return an empty BitSet.
2551     * </p>
2552     *
2553     * @param array  The array to search for the object, may be {@code null}.
2554     * @param valueToFind  The value to find.
2555     * @param startIndex  The index to start searching.
2556     * @return A BitSet of all the indices of the value within the array,
2557     *  an empty BitSet if not found or {@code null} array input.
2558     * @since 3.10
2559     */
2560    public static BitSet indexesOf(final int[] array, final int valueToFind, int startIndex) {
2561        final BitSet bitSet = new BitSet();
2562        if (array != null) {
2563            while (startIndex < array.length) {
2564                startIndex = indexOf(array, valueToFind, startIndex);
2565                if (startIndex == INDEX_NOT_FOUND) {
2566                    break;
2567                }
2568                bitSet.set(startIndex);
2569                ++startIndex;
2570            }
2571        }
2572        return bitSet;
2573    }
2574
2575    /**
2576     * Finds the indices of the given value in the array.
2577     *
2578     * <p>
2579     * This method returns an empty BitSet for a {@code null} input array.
2580     * </p>
2581     *
2582     * @param array  The array to search for the object, may be {@code null}.
2583     * @param valueToFind  The value to find.
2584     * @return A BitSet of all the indices of the value within the array,
2585     *  an empty BitSet if not found or {@code null} array input.
2586     * @since 3.10
2587     */
2588    public static BitSet indexesOf(final long[] array, final long valueToFind) {
2589        return indexesOf(array, valueToFind, 0);
2590    }
2591
2592    /**
2593     * Finds the indices of the given value in the array starting at the given index.
2594     *
2595     * <p>
2596     * This method returns an empty BitSet for a {@code null} input array.
2597     * </p>
2598     *
2599     * <p>
2600     * A negative startIndex is treated as zero. A startIndex larger than the array
2601     * length will return an empty BitSet.
2602     * </p>
2603     *
2604     * @param array  The array to search for the object, may be {@code null}.
2605     * @param valueToFind  The value to find.
2606     * @param startIndex  The index to start searching.
2607     * @return A BitSet of all the indices of the value within the array,
2608     *  an empty BitSet if not found or {@code null} array input.
2609     * @since 3.10
2610     */
2611    public static BitSet indexesOf(final long[] array, final long valueToFind, int startIndex) {
2612        final BitSet bitSet = new BitSet();
2613        if (array != null) {
2614            while (startIndex < array.length) {
2615                startIndex = indexOf(array, valueToFind, startIndex);
2616                if (startIndex == INDEX_NOT_FOUND) {
2617                    break;
2618                }
2619                bitSet.set(startIndex);
2620                ++startIndex;
2621            }
2622        }
2623        return bitSet;
2624    }
2625
2626    /**
2627     * Finds the indices of the given object in the array.
2628     *
2629     * <p>
2630     * This method returns an empty BitSet for a {@code null} input array.
2631     * </p>
2632     *
2633     * @param array  The array to search for the object, may be {@code null}.
2634     * @param objectToFind  The object to find, may be {@code null}.
2635     * @return A BitSet of all the indices of the object within the array,
2636     *  an empty BitSet if not found or {@code null} array input.
2637     * @since 3.10
2638     */
2639    public static BitSet indexesOf(final Object[] array, final Object objectToFind) {
2640        return indexesOf(array, objectToFind, 0);
2641    }
2642
2643    /**
2644     * Finds the indices of the given object in the array starting at the given index.
2645     *
2646     * <p>
2647     * This method returns an empty BitSet for a {@code null} input array.
2648     * </p>
2649     *
2650     * <p>
2651     * A negative startIndex is treated as zero. A startIndex larger than the array
2652     * length will return an empty BitSet.
2653     * </p>
2654     *
2655     * @param array  The array to search for the object, may be {@code null}.
2656     * @param objectToFind  The object to find, may be {@code null}.
2657     * @param startIndex  The index to start searching.
2658     * @return A BitSet of all the indices of the object within the array starting at the index,
2659     *  an empty BitSet if not found or {@code null} array input.
2660     * @since 3.10
2661     */
2662    public static BitSet indexesOf(final Object[] array, final Object objectToFind, int startIndex) {
2663        final BitSet bitSet = new BitSet();
2664        if (array != null) {
2665            while (startIndex < array.length) {
2666                startIndex = indexOf(array, objectToFind, startIndex);
2667                if (startIndex == INDEX_NOT_FOUND) {
2668                    break;
2669                }
2670                bitSet.set(startIndex);
2671                ++startIndex;
2672            }
2673        }
2674        return bitSet;
2675    }
2676
2677    /**
2678     * Finds the indices of the given value in the array.
2679     *
2680     * <p>
2681     * This method returns an empty BitSet for a {@code null} input array.
2682     * </p>
2683     *
2684     * @param array  The array to search for the object, may be {@code null}.
2685     * @param valueToFind  The value to find.
2686     * @return A BitSet of all the indices of the value within the array,
2687     *  an empty BitSet if not found or {@code null} array input.
2688     * @since 3.10
2689     */
2690    public static BitSet indexesOf(final short[] array, final short valueToFind) {
2691        return indexesOf(array, valueToFind, 0);
2692    }
2693
2694    /**
2695     * Finds the indices of the given value in the array starting at the given index.
2696     *
2697     * <p>
2698     * This method returns an empty BitSet for a {@code null} input array.
2699     * </p>
2700     *
2701     * <p>
2702     * A negative startIndex is treated as zero. A startIndex larger than the array
2703     * length will return an empty BitSet.
2704     * </p>
2705     *
2706     * @param array  The array to search for the object, may be {@code null}.
2707     * @param valueToFind  The value to find.
2708     * @param startIndex  The index to start searching.
2709     * @return A BitSet of all the indices of the value within the array,
2710     *  an empty BitSet if not found or {@code null} array input.
2711     * @since 3.10
2712     */
2713    public static BitSet indexesOf(final short[] array, final short valueToFind, int startIndex) {
2714        final BitSet bitSet = new BitSet();
2715        if (array != null) {
2716            while (startIndex < array.length) {
2717                startIndex = indexOf(array, valueToFind, startIndex);
2718                if (startIndex == INDEX_NOT_FOUND) {
2719                    break;
2720                }
2721                bitSet.set(startIndex);
2722                ++startIndex;
2723            }
2724        }
2725        return bitSet;
2726    }
2727
2728    /**
2729     * Finds the index of the given value in the array.
2730     * <p>
2731     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2732     * </p>
2733     *
2734     * @param array       The array to search for the object, may be {@code null}.
2735     * @param valueToFind The value to find.
2736     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2737     */
2738    public static int indexOf(final boolean[] array, final boolean valueToFind) {
2739        return indexOf(array, valueToFind, 0);
2740    }
2741
2742    /**
2743     * Finds the index of the given value in the array starting at the given index.
2744     * <p>
2745     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2746     * </p>
2747     * <p>
2748     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2749     * </p>
2750     *
2751     * @param array       The array to search for the object, may be {@code null}.
2752     * @param valueToFind The value to find.
2753     * @param startIndex  The index to start searching.
2754     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2755     */
2756    public static int indexOf(final boolean[] array, final boolean valueToFind, final int startIndex) {
2757        if (isEmpty(array)) {
2758            return INDEX_NOT_FOUND;
2759        }
2760        for (int i = max0(startIndex); i < array.length; i++) {
2761            if (valueToFind == array[i]) {
2762                return i;
2763            }
2764        }
2765        return INDEX_NOT_FOUND;
2766    }
2767
2768    /**
2769     * Finds the index of the given value in the array.
2770     * <p>
2771     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2772     * </p>
2773     *
2774     * @param array       The array to search for the object, may be {@code null}.
2775     * @param valueToFind The value to find.
2776     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2777     */
2778    public static int indexOf(final byte[] array, final byte valueToFind) {
2779        return indexOf(array, valueToFind, 0);
2780    }
2781
2782    /**
2783     * Finds the index of the given value in the array starting at the given index.
2784     * <p>
2785     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2786     * </p>
2787     * <p>
2788     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2789     * </p>
2790     *
2791     * @param array       The array to search for the object, may be {@code null}.
2792     * @param valueToFind The value to find.
2793     * @param startIndex  The index to start searching.
2794     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2795     */
2796    public static int indexOf(final byte[] array, final byte valueToFind, final int startIndex) {
2797        if (isEmpty(array)) {
2798            return INDEX_NOT_FOUND;
2799        }
2800        for (int i = max0(startIndex); i < array.length; i++) {
2801            if (valueToFind == array[i]) {
2802                return i;
2803            }
2804        }
2805        return INDEX_NOT_FOUND;
2806    }
2807
2808    /**
2809     * Finds the index of the given value in the array.
2810     * <p>
2811     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2812     * </p>
2813     *
2814     * @param array       The array to search for the object, may be {@code null}.
2815     * @param valueToFind The value to find.
2816     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2817     * @since 2.1
2818     */
2819    public static int indexOf(final char[] array, final char valueToFind) {
2820        return indexOf(array, valueToFind, 0);
2821    }
2822
2823    /**
2824     * Finds the index of the given value in the array starting at the given index.
2825     * <p>
2826     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2827     * </p>
2828     * <p>
2829     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2830     * </p>
2831     *
2832     * @param array       The array to search for the object, may be {@code null}.
2833     * @param valueToFind The value to find.
2834     * @param startIndex  The index to start searching.
2835     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2836     * @since 2.1
2837     */
2838    public static int indexOf(final char[] array, final char valueToFind, final int startIndex) {
2839        if (isEmpty(array)) {
2840            return INDEX_NOT_FOUND;
2841        }
2842        for (int i = max0(startIndex); i < array.length; i++) {
2843            if (valueToFind == array[i]) {
2844                return i;
2845            }
2846        }
2847        return INDEX_NOT_FOUND;
2848    }
2849
2850    /**
2851     * Finds the index of the given value in the array.
2852     * <p>
2853     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2854     * </p>
2855     *
2856     * @param array       The array to search for the object, may be {@code null}.
2857     * @param valueToFind The value to find.
2858     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2859     */
2860    public static int indexOf(final double[] array, final double valueToFind) {
2861        return indexOf(array, valueToFind, 0);
2862    }
2863
2864    /**
2865     * Finds the index of the given value within a given tolerance in the array. This method will return the index of the first value which falls between the
2866     * region defined by valueToFind - tolerance and valueToFind + tolerance.
2867     * <p>
2868     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2869     * </p>
2870     *
2871     * @param array       The array to search for the object, may be {@code null}.
2872     * @param valueToFind The value to find.
2873     * @param tolerance   tolerance of the search.
2874     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2875     */
2876    public static int indexOf(final double[] array, final double valueToFind, final double tolerance) {
2877        return indexOf(array, valueToFind, 0, tolerance);
2878    }
2879
2880    /**
2881     * Finds the index of the given value in the array starting at the given index.
2882     * <p>
2883     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2884     * </p>
2885     * <p>
2886     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2887     * </p>
2888     *
2889     * @param array       The array to search for the object, may be {@code null}.
2890     * @param valueToFind The value to find.
2891     * @param startIndex  The index to start searching.
2892     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2893     */
2894    public static int indexOf(final double[] array, final double valueToFind, final int startIndex) {
2895        if (Double.isNaN(valueToFind)) {
2896            return indexOfNaN(array, startIndex);
2897        }
2898        if (isEmpty(array)) {
2899            return INDEX_NOT_FOUND;
2900        }
2901        for (int i = max0(startIndex); i < array.length; i++) {
2902            if (valueToFind == array[i]) {
2903                return i;
2904            }
2905        }
2906        return INDEX_NOT_FOUND;
2907    }
2908
2909    /**
2910     * Finds the index of the given value in the array starting at the given index. This method will return the index of the first value which falls between the
2911     * region defined by valueToFind - tolerance and valueToFind + tolerance.
2912     * <p>
2913     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2914     * </p>
2915     * <p>
2916     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2917     * </p>
2918     *
2919     * @param array       The array to search for the object, may be {@code null}.
2920     * @param valueToFind The value to find.
2921     * @param startIndex  The index to start searching.
2922     * @param tolerance   tolerance of the search.
2923     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2924     */
2925    public static int indexOf(final double[] array, final double valueToFind, final int startIndex, final double tolerance) {
2926        if (Double.isNaN(valueToFind)) {
2927            return indexOfNaN(array, startIndex);
2928        }
2929        if (isEmpty(array)) {
2930            return INDEX_NOT_FOUND;
2931        }
2932        final double min = valueToFind - tolerance;
2933        final double max = valueToFind + tolerance;
2934        for (int i = max0(startIndex); i < array.length; i++) {
2935            if (array[i] >= min && array[i] <= max) {
2936                return i;
2937            }
2938        }
2939        return INDEX_NOT_FOUND;
2940    }
2941
2942    /**
2943     * Finds the index of the given value in the array.
2944     * <p>
2945     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2946     * </p>
2947     *
2948     * @param array       The array to search for the object, may be {@code null}.
2949     * @param valueToFind The value to find.
2950     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2951     */
2952    public static int indexOf(final float[] array, final float valueToFind) {
2953        return indexOf(array, valueToFind, 0);
2954    }
2955
2956    /**
2957     * Finds the index of the given value in the array starting at the given index.
2958     * <p>
2959     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2960     * </p>
2961     * <p>
2962     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2963     * </p>
2964     *
2965     * @param array       The array to search for the object, may be {@code null}.
2966     * @param valueToFind The value to find.
2967     * @param startIndex  The index to start searching.
2968     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2969     */
2970    public static int indexOf(final float[] array, final float valueToFind, final int startIndex) {
2971        if (isEmpty(array)) {
2972            return INDEX_NOT_FOUND;
2973        }
2974        final boolean searchNaN = Float.isNaN(valueToFind);
2975        for (int i = max0(startIndex); i < array.length; i++) {
2976            final float element = array[i];
2977            if (valueToFind == element || searchNaN && Float.isNaN(element)) {
2978                return i;
2979            }
2980        }
2981        return INDEX_NOT_FOUND;
2982    }
2983
2984    /**
2985     * Finds the index of the given value in the array.
2986     * <p>
2987     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2988     * </p>
2989     *
2990     * @param array       The array to search for the object, may be {@code null}.
2991     * @param valueToFind The value to find.
2992     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2993     */
2994    public static int indexOf(final int[] array, final int valueToFind) {
2995        return indexOf(array, valueToFind, 0);
2996    }
2997
2998    /**
2999     * Finds the index of the given value in the array starting at the given index.
3000     * <p>
3001     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3002     * </p>
3003     * <p>
3004     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3005     * </p>
3006     *
3007     * @param array       The array to search for the object, may be {@code null}.
3008     * @param valueToFind The value to find.
3009     * @param startIndex  The index to start searching.
3010     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3011     */
3012    public static int indexOf(final int[] array, final int valueToFind, final int startIndex) {
3013        if (isEmpty(array)) {
3014            return INDEX_NOT_FOUND;
3015        }
3016        for (int i = max0(startIndex); i < array.length; i++) {
3017            if (valueToFind == array[i]) {
3018                return i;
3019            }
3020        }
3021        return INDEX_NOT_FOUND;
3022    }
3023
3024    /**
3025     * Finds the index of the given value in the array.
3026     * <p>
3027     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3028     * </p>
3029     *
3030     * @param array       The array to search for the object, may be {@code null}.
3031     * @param valueToFind The value to find.
3032     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3033     */
3034    public static int indexOf(final long[] array, final long valueToFind) {
3035        return indexOf(array, valueToFind, 0);
3036    }
3037
3038    /**
3039     * Finds the index of the given value in the array starting at the given index.
3040     * <p>
3041     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3042     * </p>
3043     * <p>
3044     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3045     * </p>
3046     *
3047     * @param array       The array to search for the object, may be {@code null}.
3048     * @param valueToFind The value to find.
3049     * @param startIndex  The index to start searching.
3050     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3051     */
3052    public static int indexOf(final long[] array, final long valueToFind, final int startIndex) {
3053        if (isEmpty(array)) {
3054            return INDEX_NOT_FOUND;
3055        }
3056        for (int i = max0(startIndex); i < array.length; i++) {
3057            if (valueToFind == array[i]) {
3058                return i;
3059            }
3060        }
3061        return INDEX_NOT_FOUND;
3062    }
3063
3064    /**
3065     * Finds the index of the given object in the array.
3066     * <p>
3067     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3068     * </p>
3069     *
3070     * @param array        The array to search for the object, may be {@code null}.
3071     * @param objectToFind The object to find, may be {@code null}.
3072     * @return The index of the object within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3073     */
3074    public static int indexOf(final Object[] array, final Object objectToFind) {
3075        return indexOf(array, objectToFind, 0);
3076    }
3077
3078    /**
3079     * Finds the index of the given object in the array starting at the given index.
3080     * <p>
3081     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3082     * </p>
3083     * <p>
3084     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3085     * </p>
3086     *
3087     * @param array        The array to search for the object, may be {@code null}.
3088     * @param objectToFind The object to find, may be {@code null}.
3089     * @param startIndex   The index to start searching.
3090     * @return The index of the object within the array starting at the index, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3091     */
3092    public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
3093        if (isEmpty(array)) {
3094            return INDEX_NOT_FOUND;
3095        }
3096        startIndex = max0(startIndex);
3097        if (objectToFind == null) {
3098            for (int i = startIndex; i < array.length; i++) {
3099                if (array[i] == null) {
3100                    return i;
3101                }
3102            }
3103        } else {
3104            for (int i = startIndex; i < array.length; i++) {
3105                if (objectToFind.equals(array[i])) {
3106                    return i;
3107                }
3108            }
3109        }
3110        return INDEX_NOT_FOUND;
3111    }
3112
3113    /**
3114     * Finds the index of the given value in the array.
3115     * <p>
3116     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3117     * </p>
3118     *
3119     * @param array       The array to search for the object, may be {@code null}
3120     * @param valueToFind The value to find.
3121     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3122     */
3123    public static int indexOf(final short[] array, final short valueToFind) {
3124        return indexOf(array, valueToFind, 0);
3125    }
3126
3127    /**
3128     * Finds the index of the given value in the array starting at the given index.
3129     * <p>
3130     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3131     * </p>
3132     * <p>
3133     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3134     * </p>
3135     *
3136     * @param array       The array to search for the object, may be {@code null}.
3137     * @param valueToFind The value to find.
3138     * @param startIndex  The index to start searching.
3139     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3140     */
3141    public static int indexOf(final short[] array, final short valueToFind, final int startIndex) {
3142        if (isEmpty(array)) {
3143            return INDEX_NOT_FOUND;
3144        }
3145        for (int i = max0(startIndex); i < array.length; i++) {
3146            if (valueToFind == array[i]) {
3147                return i;
3148            }
3149        }
3150        return INDEX_NOT_FOUND;
3151    }
3152
3153    /**
3154     * Finds the index of the NaN value in a double array.
3155     * @param array The array to search for NaN, may be {@code null}.
3156     * @param startIndex The index to start searching.
3157     * @return The index of the NaN value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3158     */
3159    private static int indexOfNaN(final double[] array, final int startIndex) {
3160        if (isEmpty(array)) {
3161            return INDEX_NOT_FOUND;
3162        }
3163        for (int i = max0(startIndex); i < array.length; i++) {
3164            if (Double.isNaN(array[i])) {
3165                return i;
3166            }
3167        }
3168        return INDEX_NOT_FOUND;
3169    }
3170
3171    /**
3172     * Inserts elements into an array at the given index (starting from zero).
3173     *
3174     * <p>
3175     * When an array is returned, it is always a new array.
3176     * </p>
3177     *
3178     * <pre>
3179     * ArrayUtils.insert(index, null, null)      = null
3180     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3181     * ArrayUtils.insert(index, null, values)    = null
3182     * </pre>
3183     *
3184     * @param index  The position within {@code array} to insert the new values.
3185     * @param array  The array to insert the values into, may be {@code null}.
3186     * @param values The new values to insert, may be {@code null}.
3187     * @return The new array or {@code null} if the given array is {@code null}.
3188     * @throws IndexOutOfBoundsException Thrown if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3189     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
3190     * @since 3.6
3191     */
3192    public static boolean[] insert(final int index, final boolean[] array, final boolean... values) {
3193        if (array == null) {
3194            return null;
3195        }
3196        if (isEmpty(values)) {
3197            return clone(array);
3198        }
3199        if (index < 0 || index > array.length) {
3200            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3201        }
3202        final boolean[] result = new boolean[addExact(array.length, values)];
3203        System.arraycopy(values, 0, result, index, values.length);
3204        if (index > 0) {
3205            System.arraycopy(array, 0, result, 0, index);
3206        }
3207        if (index < array.length) {
3208            System.arraycopy(array, index, result, index + values.length, array.length - index);
3209        }
3210        return result;
3211    }
3212
3213    /**
3214     * Inserts elements into an array at the given index (starting from zero).
3215     *
3216     * <p>
3217     * When an array is returned, it is always a new array.
3218     * </p>
3219     *
3220     * <pre>
3221     * ArrayUtils.insert(index, null, null)      = null
3222     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3223     * ArrayUtils.insert(index, null, values)    = null
3224     * </pre>
3225     *
3226     * @param index  The position within {@code array} to insert the new values.
3227     * @param array  The array to insert the values into, may be {@code null}.
3228     * @param values The new values to insert, may be {@code null}.
3229     * @return The new array or {@code null} if the given array is {@code null}.
3230     * @throws IndexOutOfBoundsException Thrown if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3231     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
3232     * @since 3.6
3233     */
3234    public static byte[] insert(final int index, final byte[] array, final byte... values) {
3235        if (array == null) {
3236            return null;
3237        }
3238        if (isEmpty(values)) {
3239            return clone(array);
3240        }
3241        if (index < 0 || index > array.length) {
3242            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3243        }
3244        final byte[] result = new byte[addExact(array.length, values)];
3245        System.arraycopy(values, 0, result, index, values.length);
3246        if (index > 0) {
3247            System.arraycopy(array, 0, result, 0, index);
3248        }
3249        if (index < array.length) {
3250            System.arraycopy(array, index, result, index + values.length, array.length - index);
3251        }
3252        return result;
3253    }
3254
3255    /**
3256     * Inserts elements into an array at the given index (starting from zero).
3257     *
3258     * <p>
3259     * When an array is returned, it is always a new array.
3260     * </p>
3261     *
3262     * <pre>
3263     * ArrayUtils.insert(index, null, null)      = null
3264     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3265     * ArrayUtils.insert(index, null, values)    = null
3266     * </pre>
3267     *
3268     * @param index  The position within {@code array} to insert the new values.
3269     * @param array  The array to insert the values into, may be {@code null}.
3270     * @param values The new values to insert, may be {@code null}.
3271     * @return The new array or {@code null} if the given array is {@code null}.
3272     * @throws IndexOutOfBoundsException Thrown if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3273     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
3274     * @since 3.6
3275     */
3276    public static char[] insert(final int index, final char[] array, final char... values) {
3277        if (array == null) {
3278            return null;
3279        }
3280        if (isEmpty(values)) {
3281            return clone(array);
3282        }
3283        if (index < 0 || index > array.length) {
3284            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3285        }
3286        final char[] result = new char[addExact(array.length, values)];
3287        System.arraycopy(values, 0, result, index, values.length);
3288        if (index > 0) {
3289            System.arraycopy(array, 0, result, 0, index);
3290        }
3291        if (index < array.length) {
3292            System.arraycopy(array, index, result, index + values.length, array.length - index);
3293        }
3294        return result;
3295    }
3296
3297    /**
3298     * Inserts elements into an array at the given index (starting from zero).
3299     *
3300     * <p>
3301     * When an array is returned, it is always a new array.
3302     * </p>
3303     *
3304     * <pre>
3305     * ArrayUtils.insert(index, null, null)      = null
3306     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3307     * ArrayUtils.insert(index, null, values)    = null
3308     * </pre>
3309     *
3310     * @param index  The position within {@code array} to insert the new values.
3311     * @param array  The array to insert the values into, may be {@code null}.
3312     * @param values The new values to insert, may be {@code null}.
3313     * @return The new array or {@code null} if the given array is {@code null}.
3314     * @throws IndexOutOfBoundsException Thrown if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3315     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
3316     * @since 3.6
3317     */
3318    public static double[] insert(final int index, final double[] array, final double... values) {
3319        if (array == null) {
3320            return null;
3321        }
3322        if (isEmpty(values)) {
3323            return clone(array);
3324        }
3325        if (index < 0 || index > array.length) {
3326            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3327        }
3328        final double[] result = new double[addExact(array.length, values)];
3329        System.arraycopy(values, 0, result, index, values.length);
3330        if (index > 0) {
3331            System.arraycopy(array, 0, result, 0, index);
3332        }
3333        if (index < array.length) {
3334            System.arraycopy(array, index, result, index + values.length, array.length - index);
3335        }
3336        return result;
3337    }
3338
3339    /**
3340     * Inserts elements into an array at the given index (starting from zero).
3341     *
3342     * <p>
3343     * When an array is returned, it is always a new array.
3344     * </p>
3345     *
3346     * <pre>
3347     * ArrayUtils.insert(index, null, null)      = null
3348     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3349     * ArrayUtils.insert(index, null, values)    = null
3350     * </pre>
3351     *
3352     * @param index  The position within {@code array} to insert the new values.
3353     * @param array  The array to insert the values into, may be {@code null}.
3354     * @param values The new values to insert, may be {@code null}.
3355     * @return The new array or {@code null} if the given array is {@code null}.
3356     * @throws IndexOutOfBoundsException Thrown if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3357     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
3358     * @since 3.6
3359     */
3360    public static float[] insert(final int index, final float[] array, final float... values) {
3361        if (array == null) {
3362            return null;
3363        }
3364        if (isEmpty(values)) {
3365            return clone(array);
3366        }
3367        if (index < 0 || index > array.length) {
3368            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3369        }
3370        final float[] result = new float[addExact(array.length, values)];
3371        System.arraycopy(values, 0, result, index, values.length);
3372        if (index > 0) {
3373            System.arraycopy(array, 0, result, 0, index);
3374        }
3375        if (index < array.length) {
3376            System.arraycopy(array, index, result, index + values.length, array.length - index);
3377        }
3378        return result;
3379    }
3380
3381    /**
3382     * Inserts elements into an array at the given index (starting from zero).
3383     *
3384     * <p>
3385     * When an array is returned, it is always a new array.
3386     * </p>
3387     *
3388     * <pre>
3389     * ArrayUtils.insert(index, null, null)      = null
3390     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3391     * ArrayUtils.insert(index, null, values)    = null
3392     * </pre>
3393     *
3394     * @param index  The position within {@code array} to insert the new values.
3395     * @param array  The array to insert the values into, may be {@code null}.
3396     * @param values The new values to insert, may be {@code null}.
3397     * @return The new array or {@code null} if the given array is {@code null}.
3398     * @throws IndexOutOfBoundsException Thrown if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3399     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
3400     * @since 3.6
3401     */
3402    public static int[] insert(final int index, final int[] array, final int... values) {
3403        if (array == null) {
3404            return null;
3405        }
3406        if (isEmpty(values)) {
3407            return clone(array);
3408        }
3409        if (index < 0 || index > array.length) {
3410            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3411        }
3412        final int[] result = new int[addExact(array.length, values)];
3413        System.arraycopy(values, 0, result, index, values.length);
3414        if (index > 0) {
3415            System.arraycopy(array, 0, result, 0, index);
3416        }
3417        if (index < array.length) {
3418            System.arraycopy(array, index, result, index + values.length, array.length - index);
3419        }
3420        return result;
3421    }
3422
3423    /**
3424     * Inserts elements into an array at the given index (starting from zero).
3425     *
3426     * <p>
3427     * When an array is returned, it is always a new array.
3428     * </p>
3429     *
3430     * <pre>
3431     * ArrayUtils.insert(index, null, null)      = null
3432     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3433     * ArrayUtils.insert(index, null, values)    = null
3434     * </pre>
3435     *
3436     * @param index  The position within {@code array} to insert the new values.
3437     * @param array  The array to insert the values into, may be {@code null}.
3438     * @param values The new values to insert, may be {@code null}.
3439     * @return The new array or {@code null} if the given array is {@code null}.
3440     * @throws IndexOutOfBoundsException Thrown if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3441     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
3442     * @since 3.6
3443     */
3444    public static long[] insert(final int index, final long[] array, final long... values) {
3445        if (array == null) {
3446            return null;
3447        }
3448        if (isEmpty(values)) {
3449            return clone(array);
3450        }
3451        if (index < 0 || index > array.length) {
3452            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3453        }
3454        final long[] result = new long[addExact(array.length, values)];
3455        System.arraycopy(values, 0, result, index, values.length);
3456        if (index > 0) {
3457            System.arraycopy(array, 0, result, 0, index);
3458        }
3459        if (index < array.length) {
3460            System.arraycopy(array, index, result, index + values.length, array.length - index);
3461        }
3462        return result;
3463    }
3464
3465    /**
3466     * Inserts elements into an array at the given index (starting from zero).
3467     *
3468     * <p>
3469     * When an array is returned, it is always a new array.
3470     * </p>
3471     *
3472     * <pre>
3473     * ArrayUtils.insert(index, null, null)      = null
3474     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3475     * ArrayUtils.insert(index, null, values)    = null
3476     * </pre>
3477     *
3478     * @param index  The position within {@code array} to insert the new values.
3479     * @param array  The array to insert the values into, may be {@code null}.
3480     * @param values The new values to insert, may be {@code null}.
3481     * @return The new array or {@code null} if the given array is {@code null}.
3482     * @throws IndexOutOfBoundsException Thrown if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3483     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
3484     * @since 3.6
3485     */
3486    public static short[] insert(final int index, final short[] array, final short... values) {
3487        if (array == null) {
3488            return null;
3489        }
3490        if (isEmpty(values)) {
3491            return clone(array);
3492        }
3493        if (index < 0 || index > array.length) {
3494            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3495        }
3496        final short[] result = new short[addExact(array.length, values)];
3497        System.arraycopy(values, 0, result, index, values.length);
3498        if (index > 0) {
3499            System.arraycopy(array, 0, result, 0, index);
3500        }
3501        if (index < array.length) {
3502            System.arraycopy(array, index, result, index + values.length, array.length - index);
3503        }
3504        return result;
3505    }
3506
3507    /**
3508     * Inserts elements into an array at the given index (starting from zero).
3509     *
3510     * <p>
3511     * When an array is returned, it is always a new array.
3512     * </p>
3513     *
3514     * <pre>
3515     * ArrayUtils.insert(index, null, null)      = null
3516     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3517     * ArrayUtils.insert(index, null, values)    = null
3518     * </pre>
3519     *
3520     * @param <T>    The type of elements in {@code array} and {@code values}.
3521     * @param index  The position within {@code array} to insert the new values.
3522     * @param array  The array to insert the values into, may be {@code null}.
3523     * @param values The new values to insert, may be {@code null}.
3524     * @return The new array or {@code null} if the given array is {@code null}.
3525     * @throws IndexOutOfBoundsException Thrown if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3526     * @throws IllegalArgumentException Thrown if the total array length exceeds {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
3527     * @since 3.6
3528     */
3529    @SafeVarargs
3530    public static <T> T[] insert(final int index, final T[] array, final T... values) {
3531        /*
3532         * Note on use of @SafeVarargs:
3533         *
3534         * By returning null when 'array' is null, we avoid returning the vararg
3535         * array to the caller. We also avoid relying on the type of the vararg
3536         * array, by inspecting the component type of 'array'.
3537         */
3538        if (array == null) {
3539            return null;
3540        }
3541        if (isEmpty(values)) {
3542            return clone(array);
3543        }
3544        if (index < 0 || index > array.length) {
3545            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3546        }
3547        final Class<T> type = getComponentType(array);
3548        final int length = addExact(array.length, values);
3549        final T[] result = newInstance(type, length);
3550        System.arraycopy(values, 0, result, index, values.length);
3551        if (index > 0) {
3552            System.arraycopy(array, 0, result, 0, index);
3553        }
3554        if (index < array.length) {
3555            System.arraycopy(array, index, result, index + values.length, array.length - index);
3556        }
3557        return result;
3558    }
3559
3560    /**
3561     * Tests whether an array is empty or {@code null}.
3562     *
3563     * @param array The array to test.
3564     * @return {@code true} if the array is empty or {@code null}.
3565     */
3566    private static boolean isArrayEmpty(final Object array) {
3567        return getLength(array) == 0;
3568    }
3569
3570    /**
3571     * Tests whether a given array can safely be accessed at the given index.
3572     *
3573     * <pre>
3574     * ArrayUtils.isArrayIndexValid(null, 0)       = false
3575     * ArrayUtils.isArrayIndexValid([], 0)         = false
3576     * ArrayUtils.isArrayIndexValid(["a"], 0)      = true
3577     * </pre>
3578     *
3579     * @param <T> The component type of the array.
3580     * @param array The array to inspect, may be {@code null}.
3581     * @param index The index of the array to be inspected.
3582     * @return Whether the given index is safely-accessible in the given array.
3583     * @since 3.8
3584     */
3585    public static <T> boolean isArrayIndexValid(final T[] array, final int index) {
3586        return index >= 0 && getLength(array) > index;
3587    }
3588
3589    /**
3590     * Tests whether an array of primitive booleans is empty or {@code null}.
3591     *
3592     * @param array  The array to test.
3593     * @return {@code true} if the array is empty or {@code null}.
3594     * @since 2.1
3595     */
3596    public static boolean isEmpty(final boolean[] array) {
3597        return isArrayEmpty(array);
3598    }
3599
3600    /**
3601     * Tests whether an array of primitive bytes is empty or {@code null}.
3602     *
3603     * @param array  The array to test.
3604     * @return {@code true} if the array is empty or {@code null}.
3605     * @since 2.1
3606     */
3607    public static boolean isEmpty(final byte[] array) {
3608        return isArrayEmpty(array);
3609    }
3610
3611    /**
3612     * Tests whether an array of primitive chars is empty or {@code null}.
3613     *
3614     * @param array  The array to test.
3615     * @return {@code true} if the array is empty or {@code null}.
3616     * @since 2.1
3617     */
3618    public static boolean isEmpty(final char[] array) {
3619        return isArrayEmpty(array);
3620    }
3621
3622    /**
3623     * Tests whether an array of primitive doubles is empty or {@code null}.
3624     *
3625     * @param array  The array to test.
3626     * @return {@code true} if the array is empty or {@code null}.
3627     * @since 2.1
3628     */
3629    public static boolean isEmpty(final double[] array) {
3630        return isArrayEmpty(array);
3631    }
3632
3633    /**
3634     * Tests whether an array of primitive floats is empty or {@code null}.
3635     *
3636     * @param array  The array to test.
3637     * @return {@code true} if the array is empty or {@code null}.
3638     * @since 2.1
3639     */
3640    public static boolean isEmpty(final float[] array) {
3641        return isArrayEmpty(array);
3642    }
3643
3644    /**
3645     * Tests whether an array of primitive ints is empty or {@code null}.
3646     *
3647     * @param array  The array to test.
3648     * @return {@code true} if the array is empty or {@code null}.
3649     * @since 2.1
3650     */
3651    public static boolean isEmpty(final int[] array) {
3652        return isArrayEmpty(array);
3653    }
3654
3655    /**
3656     * Tests whether an array of primitive longs is empty or {@code null}.
3657     *
3658     * @param array  The array to test.
3659     * @return {@code true} if the array is empty or {@code null}.
3660     * @since 2.1
3661     */
3662    public static boolean isEmpty(final long[] array) {
3663        return isArrayEmpty(array);
3664    }
3665
3666    /**
3667     * Tests whether an array of Objects is empty or {@code null}.
3668     *
3669     * @param array  The array to test.
3670     * @return {@code true} if the array is empty or {@code null}.
3671     * @since 2.1
3672     */
3673    public static boolean isEmpty(final Object[] array) {
3674        return isArrayEmpty(array);
3675    }
3676
3677    /**
3678     * Tests whether an array of primitive shorts is empty or {@code null}.
3679     *
3680     * @param array  The array to test.
3681     * @return {@code true} if the array is empty or {@code null}.
3682     * @since 2.1
3683     */
3684    public static boolean isEmpty(final short[] array) {
3685        return isArrayEmpty(array);
3686    }
3687
3688     /**
3689     * Tests whether two arrays have equal content, using equals(), handling multidimensional arrays
3690     * correctly.
3691     * <p>
3692     * Multi-dimensional primitive arrays are also handled correctly by this method.
3693     * </p>
3694     *
3695     * @param array1  The left-hand side array to compare, may be {@code null}.
3696     * @param array2  The right-hand side array to compare, may be {@code null}.
3697     * @return {@code true} if the arrays are equal.
3698     * @deprecated Replaced by {@code java.util.Objects.deepEquals(Object, Object)} and will be
3699     * removed from future releases.
3700     */
3701    @Deprecated
3702    public static boolean isEquals(final Object array1, final Object array2) {
3703        return new EqualsBuilder().append(array1, array2).isEquals();
3704    }
3705
3706    /**
3707     * Tests whether an array of primitive booleans is not empty and not {@code null}.
3708     *
3709     * @param array  The array to test.
3710     * @return {@code true} if the array is not empty and not {@code null}.
3711     * @since 2.5
3712     */
3713    public static boolean isNotEmpty(final boolean[] array) {
3714        return !isEmpty(array);
3715    }
3716
3717    /**
3718     * Tests whether an array of primitive bytes is not empty and not {@code null}.
3719     *
3720     * @param array  The array to test.
3721     * @return {@code true} if the array is not empty and not {@code null}.
3722     * @since 2.5
3723     */
3724    public static boolean isNotEmpty(final byte[] array) {
3725        return !isEmpty(array);
3726    }
3727
3728    /**
3729     * Tests whether an array of primitive chars is not empty and not {@code null}.
3730     *
3731     * @param array  The array to test.
3732     * @return {@code true} if the array is not empty and not {@code null}.
3733     * @since 2.5
3734     */
3735    public static boolean isNotEmpty(final char[] array) {
3736        return !isEmpty(array);
3737    }
3738
3739    /**
3740     * Tests whether an array of primitive doubles is not empty and not {@code null}.
3741     *
3742     * @param array  The array to test.
3743     * @return {@code true} if the array is not empty and not {@code null}.
3744     * @since 2.5
3745     */
3746    public static boolean isNotEmpty(final double[] array) {
3747        return !isEmpty(array);
3748    }
3749
3750    /**
3751     * Tests whether an array of primitive floats is not empty and not {@code null}.
3752     *
3753     * @param array  The array to test.
3754     * @return {@code true} if the array is not empty and not {@code null}.
3755     * @since 2.5
3756     */
3757    public static boolean isNotEmpty(final float[] array) {
3758        return !isEmpty(array);
3759    }
3760
3761    /**
3762     * Tests whether an array of primitive ints is not empty and not {@code null}.
3763     *
3764     * @param array  The array to test.
3765     * @return {@code true} if the array is not empty and not {@code null}.
3766     * @since 2.5
3767     */
3768    public static boolean isNotEmpty(final int[] array) {
3769        return !isEmpty(array);
3770    }
3771
3772    /**
3773     * Tests whether an array of primitive longs is not empty and not {@code null}.
3774     *
3775     * @param array  The array to test.
3776     * @return {@code true} if the array is not empty and not {@code null}.
3777     * @since 2.5
3778     */
3779    public static boolean isNotEmpty(final long[] array) {
3780        return !isEmpty(array);
3781    }
3782
3783    /**
3784     * Tests whether an array of primitive shorts is not empty and not {@code null}.
3785     *
3786     * @param array  The array to test.
3787     * @return {@code true} if the array is not empty and not {@code null}.
3788     * @since 2.5
3789     */
3790    public static boolean isNotEmpty(final short[] array) {
3791        return !isEmpty(array);
3792    }
3793
3794    /**
3795     * Tests whether an array of Objects is not empty and not {@code null}.
3796     *
3797     * @param <T> The component type of the array
3798     * @param array  The array to test.
3799     * @return {@code true} if the array is not empty and not {@code null}.
3800     * @since 2.5
3801     */
3802     public static <T> boolean isNotEmpty(final T[] array) {
3803         return !isEmpty(array);
3804     }
3805
3806    /**
3807      * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3808      *
3809      * @param array1 The first array, may be {@code null}.
3810      * @param array2 The second array, may be {@code null}.
3811      * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3812      */
3813     public static boolean isSameLength(final boolean[] array1, final boolean[] array2) {
3814        return getLength(array1) == getLength(array2);
3815    }
3816
3817    /**
3818     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3819     *
3820     * @param array1 The first array, may be {@code null}.
3821     * @param array2 The second array, may be {@code null}.
3822     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3823     */
3824    public static boolean isSameLength(final byte[] array1, final byte[] array2) {
3825        return getLength(array1) == getLength(array2);
3826    }
3827
3828    /**
3829     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3830     *
3831     * @param array1 The first array, may be {@code null}.
3832     * @param array2 The second array, may be {@code null}.
3833     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3834     */
3835    public static boolean isSameLength(final char[] array1, final char[] array2) {
3836        return getLength(array1) == getLength(array2);
3837    }
3838
3839    /**
3840     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3841     *
3842     * @param array1 The first array, may be {@code null}.
3843     * @param array2 The second array, may be {@code null}.
3844     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3845     */
3846    public static boolean isSameLength(final double[] array1, final double[] array2) {
3847        return getLength(array1) == getLength(array2);
3848    }
3849
3850    /**
3851     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3852     *
3853     * @param array1 The first array, may be {@code null}.
3854     * @param array2 The second array, may be {@code null}.
3855     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3856     */
3857    public static boolean isSameLength(final float[] array1, final float[] array2) {
3858        return getLength(array1) == getLength(array2);
3859    }
3860
3861    /**
3862     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3863     *
3864     * @param array1 The first array, may be {@code null}.
3865     * @param array2 The second array, may be {@code null}.
3866     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3867     */
3868    public static boolean isSameLength(final int[] array1, final int[] array2) {
3869        return getLength(array1) == getLength(array2);
3870    }
3871
3872    /**
3873     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3874     *
3875     * @param array1 The first array, may be {@code null}.
3876     * @param array2 The second array, may be {@code null}.
3877     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3878     */
3879    public static boolean isSameLength(final long[] array1, final long[] array2) {
3880        return getLength(array1) == getLength(array2);
3881    }
3882
3883    /**
3884     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3885     * <p>
3886     * Any multi-dimensional aspects of the arrays are ignored.
3887     * </p>
3888     *
3889     * @param array1 The first array, may be {@code null}.
3890     * @param array2 The second array, may be {@code null}.
3891     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3892     * @since 3.11
3893     */
3894    public static boolean isSameLength(final Object array1, final Object array2) {
3895        return getLength(array1) == getLength(array2);
3896    }
3897
3898    /**
3899     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3900     * <p>
3901     * Any multi-dimensional aspects of the arrays are ignored.
3902     * </p>
3903     *
3904     * @param array1 The first array, may be {@code null}.
3905     * @param array2 The second array, may be {@code null}.
3906     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3907     */
3908    public static boolean isSameLength(final Object[] array1, final Object[] array2) {
3909        return getLength(array1) == getLength(array2);
3910    }
3911
3912    /**
3913     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3914     *
3915     * @param array1 The first array, may be {@code null}.
3916     * @param array2 The second array, may be {@code null}.
3917     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3918     */
3919    public static boolean isSameLength(final short[] array1, final short[] array2) {
3920        return getLength(array1) == getLength(array2);
3921    }
3922
3923    /**
3924     * Tests whether two arrays are the same type taking into account multidimensional arrays.
3925     *
3926     * @param array1 The first array, must not be {@code null}.
3927     * @param array2 The second array, must not be {@code null}.
3928     * @return {@code true} if type of arrays matches.
3929     * @throws IllegalArgumentException Thrown if either array is {@code null}.
3930     */
3931    public static boolean isSameType(final Object array1, final Object array2) {
3932        if (array1 == null || array2 == null) {
3933            throw new IllegalArgumentException("The Array must not be null");
3934        }
3935        return array1.getClass().getName().equals(array2.getClass().getName());
3936    }
3937
3938    /**
3939     * Tests whether the provided array is sorted according to natural ordering ({@code false} before {@code true}).
3940     *
3941     * @param array The array to check.
3942     * @return whether the array is sorted according to natural ordering.
3943     * @since 3.4
3944     */
3945    public static boolean isSorted(final boolean[] array) {
3946        if (getLength(array) < 2) {
3947            return true;
3948        }
3949        boolean previous = array[0];
3950        final int n = array.length;
3951        for (int i = 1; i < n; i++) {
3952            final boolean current = array[i];
3953            if (BooleanUtils.compare(previous, current) > 0) {
3954                return false;
3955            }
3956            previous = current;
3957        }
3958        return true;
3959    }
3960
3961    /**
3962     * Tests whether the provided array is sorted according to natural ordering.
3963     *
3964     * @param array The array to check.
3965     * @return whether the array is sorted according to natural ordering.
3966     * @since 3.4
3967     */
3968    public static boolean isSorted(final byte[] array) {
3969        if (getLength(array) < 2) {
3970            return true;
3971        }
3972        byte previous = array[0];
3973        final int n = array.length;
3974        for (int i = 1; i < n; i++) {
3975            final byte current = array[i];
3976            if (Byte.compare(previous, current) > 0) {
3977                return false;
3978            }
3979            previous = current;
3980        }
3981        return true;
3982    }
3983
3984    /**
3985     * Tests whether the provided array is sorted according to natural ordering.
3986     *
3987     * @param array The array to check.
3988     * @return whether the array is sorted according to natural ordering.
3989     * @since 3.4
3990     */
3991    public static boolean isSorted(final char[] array) {
3992        if (getLength(array) < 2) {
3993            return true;
3994        }
3995        char previous = array[0];
3996        final int n = array.length;
3997        for (int i = 1; i < n; i++) {
3998            final char current = array[i];
3999            if (CharUtils.compare(previous, current) > 0) {
4000                return false;
4001            }
4002            previous = current;
4003        }
4004        return true;
4005    }
4006
4007    /**
4008     * Tests whether the provided array is sorted according to natural ordering.
4009     *
4010     * @param array The array to check.
4011     * @return whether the array is sorted according to natural ordering.
4012     * @since 3.4
4013     */
4014    public static boolean isSorted(final double[] array) {
4015        if (getLength(array) < 2) {
4016            return true;
4017        }
4018        double previous = array[0];
4019        final int n = array.length;
4020        for (int i = 1; i < n; i++) {
4021            final double current = array[i];
4022            if (Double.compare(previous, current) > 0) {
4023                return false;
4024            }
4025            previous = current;
4026        }
4027        return true;
4028    }
4029
4030    /**
4031     * Tests whether the provided array is sorted according to natural ordering.
4032     *
4033     * @param array The array to check.
4034     * @return whether the array is sorted according to natural ordering.
4035     * @since 3.4
4036     */
4037    public static boolean isSorted(final float[] array) {
4038        if (getLength(array) < 2) {
4039            return true;
4040        }
4041        float previous = array[0];
4042        final int n = array.length;
4043        for (int i = 1; i < n; i++) {
4044            final float current = array[i];
4045            if (Float.compare(previous, current) > 0) {
4046                return false;
4047            }
4048            previous = current;
4049        }
4050        return true;
4051    }
4052
4053    /**
4054     * Tests whether the provided array is sorted according to natural ordering.
4055     *
4056     * @param array The array to check.
4057     * @return whether the array is sorted according to natural ordering.
4058     * @since 3.4
4059     */
4060    public static boolean isSorted(final int[] array) {
4061        if (getLength(array) < 2) {
4062            return true;
4063        }
4064        int previous = array[0];
4065        final int n = array.length;
4066        for (int i = 1; i < n; i++) {
4067            final int current = array[i];
4068            if (Integer.compare(previous, current) > 0) {
4069                return false;
4070            }
4071            previous = current;
4072        }
4073        return true;
4074    }
4075
4076    /**
4077     * Tests whether the provided array is sorted according to natural ordering.
4078     *
4079     * @param array The array to check.
4080     * @return whether the array is sorted according to natural ordering.
4081     * @since 3.4
4082     */
4083    public static boolean isSorted(final long[] array) {
4084        if (getLength(array) < 2) {
4085            return true;
4086        }
4087        long previous = array[0];
4088        final int n = array.length;
4089        for (int i = 1; i < n; i++) {
4090            final long current = array[i];
4091            if (Long.compare(previous, current) > 0) {
4092                return false;
4093            }
4094            previous = current;
4095        }
4096        return true;
4097    }
4098
4099    /**
4100     * Tests whether the provided array is sorted according to natural ordering.
4101     *
4102     * @param array The array to check.
4103     * @return whether the array is sorted according to natural ordering.
4104     * @since 3.4
4105     */
4106    public static boolean isSorted(final short[] array) {
4107        if (getLength(array) < 2) {
4108            return true;
4109        }
4110        short previous = array[0];
4111        final int n = array.length;
4112        for (int i = 1; i < n; i++) {
4113            final short current = array[i];
4114            if (Short.compare(previous, current) > 0) {
4115                return false;
4116            }
4117            previous = current;
4118        }
4119        return true;
4120    }
4121
4122    /**
4123     * Tests whether the provided array is sorted according to the class's
4124     * {@code compareTo} method.
4125     *
4126     * @param array The array to check.
4127     * @param <T> The datatype of the array to check, it must implement {@link Comparable}.
4128     * @return whether the array is sorted.
4129     * @since 3.4
4130     */
4131    public static <T extends Comparable<? super T>> boolean isSorted(final T[] array) {
4132        return isSorted(array, Comparable::compareTo);
4133    }
4134
4135    /**
4136     * Tests whether the provided array is sorted according to the provided {@link Comparator}.
4137     *
4138     * @param array The array to check.
4139     * @param comparator The {@link Comparator} to compare over.
4140     * @param <T> The datatype of the array.
4141     * @return whether the array is sorted.
4142     * @throws NullPointerException Thrown if {@code comparator} is {@code null}.
4143     * @since 3.4
4144     */
4145    public static <T> boolean isSorted(final T[] array, final Comparator<T> comparator) {
4146        Objects.requireNonNull(comparator, "comparator");
4147        if (getLength(array) < 2) {
4148            return true;
4149        }
4150        T previous = array[0];
4151        final int n = array.length;
4152        for (int i = 1; i < n; i++) {
4153            final T current = array[i];
4154            if (comparator.compare(previous, current) > 0) {
4155                return false;
4156            }
4157            previous = current;
4158        }
4159        return true;
4160    }
4161
4162    /**
4163     * Finds the last index of the given value within the array.
4164     * <p>
4165     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) if {@code null} array input.
4166     * </p>
4167     *
4168     * @param array       The array to traverse backwards looking for the object, may be {@code null}.
4169     * @param valueToFind The object to find.
4170     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4171     */
4172    public static int lastIndexOf(final boolean[] array, final boolean valueToFind) {
4173        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4174    }
4175
4176    /**
4177     * Finds the last index of the given value in the array starting at the given index.
4178     * <p>
4179     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4180     * </p>
4181     * <p>
4182     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4183     * </p>
4184     *
4185     * @param array       The array to traverse for looking for the object, may be {@code null}.
4186     * @param valueToFind The value to find.
4187     * @param startIndex  The start index to traverse backwards from.
4188     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4189     */
4190    public static int lastIndexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
4191        if (isEmpty(array) || startIndex < 0) {
4192            return INDEX_NOT_FOUND;
4193        }
4194        if (startIndex >= array.length) {
4195            startIndex = array.length - 1;
4196        }
4197        for (int i = startIndex; i >= 0; i--) {
4198            if (valueToFind == array[i]) {
4199                return i;
4200            }
4201        }
4202        return INDEX_NOT_FOUND;
4203    }
4204
4205    /**
4206     * Finds the last index of the given value within the array.
4207     * <p>
4208     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4209     * </p>
4210     *
4211     * @param array       The array to traverse backwards looking for the object, may be {@code null}.
4212     * @param valueToFind The object to find.
4213     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4214     */
4215    public static int lastIndexOf(final byte[] array, final byte valueToFind) {
4216        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4217    }
4218
4219    /**
4220     * Finds the last index of the given value in the array starting at the given index.
4221     * <p>
4222     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4223     * </p>
4224     * <p>
4225     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4226     * </p>
4227     *
4228     * @param array       The array to traverse for looking for the object, may be {@code null}.
4229     * @param valueToFind The value to find.
4230     * @param startIndex  The start index to traverse backwards from.
4231     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4232     */
4233    public static int lastIndexOf(final byte[] array, final byte valueToFind, int startIndex) {
4234        if (array == null || startIndex < 0) {
4235            return INDEX_NOT_FOUND;
4236        }
4237        if (startIndex >= array.length) {
4238            startIndex = array.length - 1;
4239        }
4240        for (int i = startIndex; i >= 0; i--) {
4241            if (valueToFind == array[i]) {
4242                return i;
4243            }
4244        }
4245        return INDEX_NOT_FOUND;
4246    }
4247
4248    /**
4249     * Finds the last index of the given value within the array.
4250     * <p>
4251     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4252     * </p>
4253     *
4254     * @param array       The array to traverse backwards looking for the object, may be {@code null}.
4255     * @param valueToFind The object to find.
4256     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4257     * @since 2.1
4258     */
4259    public static int lastIndexOf(final char[] array, final char valueToFind) {
4260        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4261    }
4262
4263    /**
4264     * Finds the last index of the given value in the array starting at the given index.
4265     * <p>
4266     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4267     * </p>
4268     * <p>
4269     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4270     * </p>
4271     *
4272     * @param array       The array to traverse for looking for the object, may be {@code null}.
4273     * @param valueToFind The value to find.
4274     * @param startIndex  The start index to traverse backwards from.
4275     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4276     * @since 2.1
4277     */
4278    public static int lastIndexOf(final char[] array, final char valueToFind, int startIndex) {
4279        if (array == null || startIndex < 0) {
4280            return INDEX_NOT_FOUND;
4281        }
4282        if (startIndex >= array.length) {
4283            startIndex = array.length - 1;
4284        }
4285        for (int i = startIndex; i >= 0; i--) {
4286            if (valueToFind == array[i]) {
4287                return i;
4288            }
4289        }
4290        return INDEX_NOT_FOUND;
4291    }
4292
4293    /**
4294     * Finds the last index of the given value within the array.
4295     * <p>
4296     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4297     * </p>
4298     *
4299     * @param array       The array to traverse backwards looking for the object, may be {@code null}.
4300     * @param valueToFind The object to find.
4301     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4302     */
4303    public static int lastIndexOf(final double[] array, final double valueToFind) {
4304        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4305    }
4306
4307    /**
4308     * Finds the last index of the given value within a given tolerance in the array. This method will return the index of the last value which falls between
4309     * the region defined by valueToFind - tolerance and valueToFind + tolerance.
4310     * <p>
4311     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4312     * </p>
4313     *
4314     * @param array       The array to search for the object, may be {@code null}.
4315     * @param valueToFind The value to find.
4316     * @param tolerance   tolerance of the search.
4317     * @return The index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4318     */
4319    public static int lastIndexOf(final double[] array, final double valueToFind, final double tolerance) {
4320        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance);
4321    }
4322
4323    /**
4324     * Finds the last index of the given value in the array starting at the given index.
4325     * <p>
4326     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4327     * </p>
4328     * <p>
4329     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4330     * </p>
4331     *
4332     * @param array       The array to traverse for looking for the object, may be {@code null}.
4333     * @param valueToFind The value to find.
4334     * @param startIndex  The start index to traverse backwards from.
4335     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4336     */
4337    public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex) {
4338        if (Double.isNaN(valueToFind)) {
4339            return lastIndexOfNaN(array, startIndex);
4340        }
4341        if (isEmpty(array) || startIndex < 0) {
4342            return INDEX_NOT_FOUND;
4343        }
4344        if (startIndex >= array.length) {
4345            startIndex = array.length - 1;
4346        }
4347        for (int i = startIndex; i >= 0; i--) {
4348            if (valueToFind == array[i]) {
4349                return i;
4350            }
4351        }
4352        return INDEX_NOT_FOUND;
4353    }
4354
4355    /**
4356     * Finds the last index of the given value in the array starting at the given index. This method will return the index of the last value which falls between
4357     * the region defined by valueToFind - tolerance and valueToFind + tolerance.
4358     * <p>
4359     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4360     * </p>
4361     * <p>
4362     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4363     * </p>
4364     *
4365     * @param array       The array to traverse for looking for the object, may be {@code null}.
4366     * @param valueToFind The value to find.
4367     * @param startIndex  The start index to traverse backwards from.
4368     * @param tolerance   search for value within plus/minus this amount.
4369     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4370     */
4371    public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
4372        if (Double.isNaN(valueToFind)) {
4373            return lastIndexOfNaN(array, startIndex);
4374        }
4375        if (isEmpty(array) || startIndex < 0) {
4376            return INDEX_NOT_FOUND;
4377        }
4378        if (startIndex >= array.length) {
4379            startIndex = array.length - 1;
4380        }
4381        final double min = valueToFind - tolerance;
4382        final double max = valueToFind + tolerance;
4383        for (int i = startIndex; i >= 0; i--) {
4384            if (array[i] >= min && array[i] <= max) {
4385                return i;
4386            }
4387        }
4388        return INDEX_NOT_FOUND;
4389    }
4390
4391    /**
4392     * Finds the last index of the given value within the array.
4393     * <p>
4394     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4395     * </p>
4396     *
4397     * @param array       The array to traverse backwards looking for the object, may be {@code null}.
4398     * @param valueToFind The object to find.
4399     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4400     */
4401    public static int lastIndexOf(final float[] array, final float valueToFind) {
4402        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4403    }
4404
4405    /**
4406     * Finds the last index of the given value in the array starting at the given index.
4407     * <p>
4408     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4409     * </p>
4410     * <p>
4411     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4412     * </p>
4413     *
4414     * @param array       The array to traverse for looking for the object, may be {@code null}.
4415     * @param valueToFind The value to find.
4416     * @param startIndex  The start index to traverse backwards from.
4417     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4418     */
4419    public static int lastIndexOf(final float[] array, final float valueToFind, int startIndex) {
4420        if (isEmpty(array) || startIndex < 0) {
4421            return INDEX_NOT_FOUND;
4422        }
4423        if (startIndex >= array.length) {
4424            startIndex = array.length - 1;
4425        }
4426        final boolean searchNaN = Float.isNaN(valueToFind);
4427        for (int i = startIndex; i >= 0; i--) {
4428            final float element = array[i];
4429            if (valueToFind == element || searchNaN && Float.isNaN(element)) {
4430                return i;
4431            }
4432        }
4433        return INDEX_NOT_FOUND;
4434    }
4435
4436    /**
4437     * Finds the last index of the given value within the array.
4438     * <p>
4439     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4440     * </p>
4441     *
4442     * @param array       The array to traverse backwards looking for the object, may be {@code null}.
4443     * @param valueToFind The object to find.
4444     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4445     */
4446    public static int lastIndexOf(final int[] array, final int valueToFind) {
4447        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4448    }
4449
4450    /**
4451     * Finds the last index of the given value in the array starting at the given index.
4452     * <p>
4453     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4454     * </p>
4455     * <p>
4456     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4457     * </p>
4458     *
4459     * @param array       The array to traverse for looking for the object, may be {@code null}.
4460     * @param valueToFind The value to find.
4461     * @param startIndex  The start index to traverse backwards from.
4462     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4463     */
4464    public static int lastIndexOf(final int[] array, final int valueToFind, int startIndex) {
4465        if (array == null || startIndex < 0) {
4466            return INDEX_NOT_FOUND;
4467        }
4468        if (startIndex >= array.length) {
4469            startIndex = array.length - 1;
4470        }
4471        for (int i = startIndex; i >= 0; i--) {
4472            if (valueToFind == array[i]) {
4473                return i;
4474            }
4475        }
4476        return INDEX_NOT_FOUND;
4477    }
4478
4479    /**
4480     * Finds the last index of the given value within the array.
4481     * <p>
4482     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4483     * </p>
4484     *
4485     * @param array       The array to traverse backwards looking for the object, may be {@code null}.
4486     * @param valueToFind The object to find.
4487     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4488     */
4489    public static int lastIndexOf(final long[] array, final long valueToFind) {
4490        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4491    }
4492
4493    /**
4494     * Finds the last index of the given value in the array starting at the given index.
4495     * <p>
4496     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4497     * </p>
4498     * <p>
4499     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4500     * </p>
4501     *
4502     * @param array       The array to traverse for looking for the object, may be {@code null}.
4503     * @param valueToFind The value to find.
4504     * @param startIndex  The start index to traverse backwards from.
4505     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4506     */
4507    public static int lastIndexOf(final long[] array, final long valueToFind, int startIndex) {
4508        if (array == null || startIndex < 0) {
4509            return INDEX_NOT_FOUND;
4510        }
4511        if (startIndex >= array.length) {
4512            startIndex = array.length - 1;
4513        }
4514        for (int i = startIndex; i >= 0; i--) {
4515            if (valueToFind == array[i]) {
4516                return i;
4517            }
4518        }
4519        return INDEX_NOT_FOUND;
4520    }
4521
4522    /**
4523     * Finds the last index of the given object within the array.
4524     * <p>
4525     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4526     * </p>
4527     *
4528     * @param array        The array to traverse backwards looking for the object, may be {@code null}.
4529     * @param objectToFind The object to find, may be {@code null}.
4530     * @return The last index of the object within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4531     */
4532    public static int lastIndexOf(final Object[] array, final Object objectToFind) {
4533        return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
4534    }
4535
4536    /**
4537     * Finds the last index of the given object in the array starting at the given index.
4538     * <p>
4539     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4540     * </p>
4541     * <p>
4542     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4543     * </p>
4544     *
4545     * @param array        The array to traverse for looking for the object, may be {@code null}.
4546     * @param objectToFind The object to find, may be {@code null}.
4547     * @param startIndex   The start index to traverse backwards from.
4548     * @return The last index of the object within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4549     */
4550    public static int lastIndexOf(final Object[] array, final Object objectToFind, int startIndex) {
4551        if (array == null || startIndex < 0) {
4552            return INDEX_NOT_FOUND;
4553        }
4554        if (startIndex >= array.length) {
4555            startIndex = array.length - 1;
4556        }
4557        if (objectToFind == null) {
4558            for (int i = startIndex; i >= 0; i--) {
4559                if (array[i] == null) {
4560                    return i;
4561                }
4562            }
4563        } else if (array.getClass().getComponentType().isInstance(objectToFind)) {
4564            for (int i = startIndex; i >= 0; i--) {
4565                if (objectToFind.equals(array[i])) {
4566                    return i;
4567                }
4568            }
4569        }
4570        return INDEX_NOT_FOUND;
4571    }
4572
4573    /**
4574     * Finds the last index of the given value within the array.
4575     * <p>
4576     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4577     * </p>
4578     *
4579     * @param array       The array to traverse backwards looking for the object, may be {@code null}.
4580     * @param valueToFind The object to find.
4581     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4582     */
4583    public static int lastIndexOf(final short[] array, final short valueToFind) {
4584        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4585    }
4586
4587    /**
4588     * Finds the last index of the given value in the array starting at the given index.
4589     * <p>
4590     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4591     * </p>
4592     * <p>
4593     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4594     * </p>
4595     *
4596     * @param array       The array to traverse for looking for the object, may be {@code null}.
4597     * @param valueToFind The value to find.
4598     * @param startIndex  The start index to traverse backwards from.
4599     * @return The last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4600     */
4601    public static int lastIndexOf(final short[] array, final short valueToFind, int startIndex) {
4602        if (array == null || startIndex < 0) {
4603            return INDEX_NOT_FOUND;
4604        }
4605        if (startIndex >= array.length) {
4606            startIndex = array.length - 1;
4607        }
4608        for (int i = startIndex; i >= 0; i--) {
4609            if (valueToFind == array[i]) {
4610                return i;
4611            }
4612        }
4613        return INDEX_NOT_FOUND;
4614    }
4615
4616    /**
4617     * Finds the last index of the NaN value in a double array.
4618     * @param array The array to traverse backwards for NaN, may be {@code null}.
4619     * @param startIndex The start index to traverse backwards from.
4620     * @return The last index of the NaN value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4621     */
4622    private static int lastIndexOfNaN(final double[] array, final int startIndex) {
4623        if (isEmpty(array) || startIndex < 0) {
4624            return INDEX_NOT_FOUND;
4625        }
4626        for (int i = Math.min(startIndex, array.length - 1); i >= 0; i--) {
4627            if (Double.isNaN(array[i])) {
4628                return i;
4629            }
4630        }
4631        return INDEX_NOT_FOUND;
4632    }
4633
4634    /**
4635     * Maps elements from an array into elements of a new array of a given type, while mapping old elements to new elements.
4636     *
4637     * @param <T>           The input array type.
4638     * @param <R>           The output array type.
4639     * @param <E>           The type of exceptions thrown when the mapper function fails.
4640     * @param array         The input array.
4641     * @param componentType The component type of the result array.
4642     * @param mapper        A non-interfering, stateless function to apply to each element.
4643     * @return A new array.
4644     * @throws E Thrown when the mapper function fails.
4645     */
4646    private static <T, R, E extends Throwable> R[] map(final T[] array, final Class<R> componentType, final FailableFunction<? super T, ? extends R, E> mapper)
4647            throws E {
4648        return ArrayFill.fill(newInstance(componentType, array.length), i -> mapper.apply(array[i]));
4649    }
4650
4651    private static int max0(final int other) {
4652        return Math.max(0, other);
4653    }
4654
4655    /**
4656     * Delegates to {@link Array#newInstance(Class,int)} using generics.
4657     *
4658     * @param <T> The array type.
4659     * @param componentType The array class.
4660     * @param length The array length
4661     * @return The new array.
4662     * @throws NullPointerException Thrown if the specified {@code componentType} parameter is null.
4663     * @since 3.13.0
4664     */
4665    @SuppressWarnings("unchecked") // OK, because array and values are of type T
4666    public static <T> T[] newInstance(final Class<T> componentType, final int length) {
4667        return (T[]) Array.newInstance(componentType, length);
4668    }
4669
4670    /**
4671     * Defensive programming technique to change a {@code null}
4672     * reference to an empty one.
4673     * <p>
4674     * This method returns a default array for a {@code null} input array.
4675     * </p>
4676     * <p>
4677     * As a memory optimizing technique an empty array passed in will be overridden with
4678     * the empty {@code public static} references in this class.
4679     * </p>
4680     *
4681     * @param <T> The array type.
4682     * @param array  The array to check for {@code null} or empty
4683     * @param defaultArray A default array, usually empty.
4684     * @return The same array, or defaultArray if {@code null} or empty input.
4685     * @since 3.15.0
4686     */
4687    public static <T> T[] nullTo(final T[] array, final T[] defaultArray) {
4688        return isEmpty(array) ? defaultArray : array;
4689    }
4690
4691    /**
4692     * Defensive programming technique to change a {@code null}
4693     * reference to an empty one.
4694     * <p>
4695     * This method returns an empty array for a {@code null} input array.
4696     * </p>
4697     * <p>
4698     * As a memory optimizing technique an empty array passed in will be overridden with
4699     * the empty {@code public static} references in this class.
4700     * </p>
4701     *
4702     * @param array  The array to check for {@code null} or empty.
4703     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4704     * @since 2.5
4705     */
4706    public static boolean[] nullToEmpty(final boolean[] array) {
4707        return isEmpty(array) ? EMPTY_BOOLEAN_ARRAY : array;
4708    }
4709
4710    /**
4711     * Defensive programming technique to change a {@code null}
4712     * reference to an empty one.
4713     * <p>
4714     * This method returns an empty array for a {@code null} input array.
4715     * </p>
4716     * <p>
4717     * As a memory optimizing technique an empty array passed in will be overridden with
4718     * the empty {@code public static} references in this class.
4719     * </p>
4720     *
4721     * @param array  The array to check for {@code null} or empty.
4722     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4723     * @since 2.5
4724     */
4725    public static Boolean[] nullToEmpty(final Boolean[] array) {
4726        return nullTo(array, EMPTY_BOOLEAN_OBJECT_ARRAY);
4727    }
4728
4729    /**
4730     * Defensive programming technique to change a {@code null}
4731     * reference to an empty one.
4732     * <p>
4733     * This method returns an empty array for a {@code null} input array.
4734     * </p>
4735     * <p>
4736     * As a memory optimizing technique an empty array passed in will be overridden with
4737     * the empty {@code public static} references in this class.
4738     * </p>
4739     *
4740     * @param array  The array to check for {@code null} or empty.
4741     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4742     * @since 2.5
4743     */
4744    public static byte[] nullToEmpty(final byte[] array) {
4745        return isEmpty(array) ? EMPTY_BYTE_ARRAY : array;
4746    }
4747
4748    /**
4749     * Defensive programming technique to change a {@code null}
4750     * reference to an empty one.
4751     * <p>
4752     * This method returns an empty array for a {@code null} input array.
4753     * </p>
4754     * <p>
4755     * As a memory optimizing technique an empty array passed in will be overridden with
4756     * the empty {@code public static} references in this class.
4757     * </p>
4758     *
4759     * @param array  The array to check for {@code null} or empty.
4760     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4761     * @since 2.5
4762     */
4763    public static Byte[] nullToEmpty(final Byte[] array) {
4764        return nullTo(array, EMPTY_BYTE_OBJECT_ARRAY);
4765    }
4766
4767    /**
4768     * Defensive programming technique to change a {@code null}
4769     * reference to an empty one.
4770     * <p>
4771     * This method returns an empty array for a {@code null} input array.
4772     * </p>
4773     * <p>
4774     * As a memory optimizing technique an empty array passed in will be overridden with
4775     * the empty {@code public static} references in this class.
4776     * </p>
4777     *
4778     * @param array  The array to check for {@code null} or empty.
4779     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4780     * @since 2.5
4781     */
4782    public static char[] nullToEmpty(final char[] array) {
4783        return isEmpty(array) ? EMPTY_CHAR_ARRAY : array;
4784    }
4785
4786    /**
4787     * Defensive programming technique to change a {@code null}
4788     * reference to an empty one.
4789     * <p>
4790     * This method returns an empty array for a {@code null} input array.
4791     * </p>
4792     * <p>
4793     * As a memory optimizing technique an empty array passed in will be overridden with
4794     * the empty {@code public static} references in this class.
4795     * </p>
4796     *
4797     * @param array  The array to check for {@code null} or empty.
4798     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4799     * @since 2.5
4800     */
4801    public static Character[] nullToEmpty(final Character[] array) {
4802        return nullTo(array, EMPTY_CHARACTER_OBJECT_ARRAY);
4803    }
4804
4805    /**
4806     * Defensive programming technique to change a {@code null}
4807     * reference to an empty one.
4808     * <p>
4809     * This method returns an empty array for a {@code null} input array.
4810     * </p>
4811     * <p>
4812     * As a memory optimizing technique an empty array passed in will be overridden with
4813     * the empty {@code public static} references in this class.
4814     * </p>
4815     *
4816     * @param array  The array to check for {@code null} or empty.
4817     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4818     * @since 3.2
4819     */
4820    public static Class<?>[] nullToEmpty(final Class<?>[] array) {
4821        return nullTo(array, EMPTY_CLASS_ARRAY);
4822    }
4823
4824    /**
4825     * Defensive programming technique to change a {@code null}
4826     * reference to an empty one.
4827     * <p>
4828     * This method returns an empty array for a {@code null} input array.
4829     * </p>
4830     * <p>
4831     * As a memory optimizing technique an empty array passed in will be overridden with
4832     * the empty {@code public static} references in this class.
4833     * </p>
4834     *
4835     * @param array  The array to check for {@code null} or empty.
4836     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4837     * @since 2.5
4838     */
4839    public static double[] nullToEmpty(final double[] array) {
4840        return isEmpty(array) ? EMPTY_DOUBLE_ARRAY : array;
4841    }
4842
4843    /**
4844     * Defensive programming technique to change a {@code null}
4845     * reference to an empty one.
4846     * <p>
4847     * This method returns an empty array for a {@code null} input array.
4848     * </p>
4849     * <p>
4850     * As a memory optimizing technique an empty array passed in will be overridden with
4851     * the empty {@code public static} references in this class.
4852     * </p>
4853     *
4854     * @param array  The array to check for {@code null} or empty.
4855     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4856     * @since 2.5
4857     */
4858    public static Double[] nullToEmpty(final Double[] array) {
4859        return nullTo(array, EMPTY_DOUBLE_OBJECT_ARRAY);
4860    }
4861
4862    /**
4863     * Defensive programming technique to change a {@code null}
4864     * reference to an empty one.
4865     * <p>
4866     * This method returns an empty array for a {@code null} input array.
4867     * </p>
4868     * <p>
4869     * As a memory optimizing technique an empty array passed in will be overridden with
4870     * the empty {@code public static} references in this class.
4871     * </p>
4872     *
4873     * @param array  The array to check for {@code null} or empty.
4874     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4875     * @since 2.5
4876     */
4877    public static float[] nullToEmpty(final float[] array) {
4878        return isEmpty(array) ? EMPTY_FLOAT_ARRAY : array;
4879    }
4880
4881    /**
4882     * Defensive programming technique to change a {@code null}
4883     * reference to an empty one.
4884     * <p>
4885     * This method returns an empty array for a {@code null} input array.
4886     * </p>
4887     * <p>
4888     * As a memory optimizing technique an empty array passed in will be overridden with
4889     * the empty {@code public static} references in this class.
4890     * </p>
4891     *
4892     * @param array  The array to check for {@code null} or empty.
4893     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4894     * @since 2.5
4895     */
4896    public static Float[] nullToEmpty(final Float[] array) {
4897        return nullTo(array, EMPTY_FLOAT_OBJECT_ARRAY);
4898    }
4899
4900    /**
4901     * Defensive programming technique to change a {@code null}
4902     * reference to an empty one.
4903     * <p>
4904     * This method returns an empty array for a {@code null} input array.
4905     * </p>
4906     * <p>
4907     * As a memory optimizing technique an empty array passed in will be overridden with
4908     * the empty {@code public static} references in this class.
4909     * </p>
4910     *
4911     * @param array  The array to check for {@code null} or empty.
4912     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4913     * @since 2.5
4914     */
4915    public static int[] nullToEmpty(final int[] array) {
4916        return isEmpty(array) ? EMPTY_INT_ARRAY : array;
4917    }
4918
4919    /**
4920     * Defensive programming technique to change a {@code null}
4921     * reference to an empty one.
4922     * <p>
4923     * This method returns an empty array for a {@code null} input array.
4924     * </p>
4925     * <p>
4926     * As a memory optimizing technique an empty array passed in will be overridden with
4927     * the empty {@code public static} references in this class.
4928     * </p>
4929     *
4930     * @param array  The array to check for {@code null} or empty.
4931     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4932     * @since 2.5
4933     */
4934    public static Integer[] nullToEmpty(final Integer[] array) {
4935        return nullTo(array, EMPTY_INTEGER_OBJECT_ARRAY);
4936    }
4937
4938    /**
4939     * Defensive programming technique to change a {@code null}
4940     * reference to an empty one.
4941     * <p>
4942     * This method returns an empty array for a {@code null} input array.
4943     * </p>
4944     * <p>
4945     * As a memory optimizing technique an empty array passed in will be overridden with
4946     * the empty {@code public static} references in this class.
4947     * </p>
4948     *
4949     * @param array  The array to check for {@code null} or empty.
4950     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4951     * @since 2.5
4952     */
4953    public static long[] nullToEmpty(final long[] array) {
4954        return isEmpty(array) ? EMPTY_LONG_ARRAY : array;
4955    }
4956
4957    /**
4958     * Defensive programming technique to change a {@code null}
4959     * reference to an empty one.
4960     * <p>
4961     * This method returns an empty array for a {@code null} input array.
4962     * </p>
4963     * <p>
4964     * As a memory optimizing technique an empty array passed in will be overridden with
4965     * the empty {@code public static} references in this class.
4966     * </p>
4967     *
4968     * @param array  The array to check for {@code null} or empty.
4969     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4970     * @since 2.5
4971     */
4972    public static Long[] nullToEmpty(final Long[] array) {
4973        return nullTo(array, EMPTY_LONG_OBJECT_ARRAY);
4974    }
4975
4976    /**
4977     * Defensive programming technique to change a {@code null}
4978     * reference to an empty one.
4979     * <p>
4980     * This method returns an empty array for a {@code null} input array.
4981     * </p>
4982     * <p>
4983     * As a memory optimizing technique an empty array passed in will be overridden with
4984     * the empty {@code public static} references in this class.
4985     * </p>
4986     *
4987     * @param array  The array to check for {@code null} or empty.
4988     * @return The same array, {@code public static} empty array if {@code null} or empty input.
4989     * @since 2.5
4990     */
4991    public static Object[] nullToEmpty(final Object[] array) {
4992        return nullTo(array, EMPTY_OBJECT_ARRAY);
4993    }
4994
4995    /**
4996     * Defensive programming technique to change a {@code null}
4997     * reference to an empty one.
4998     * <p>
4999     * This method returns an empty array for a {@code null} input array.
5000     * </p>
5001     * <p>
5002     * As a memory optimizing technique an empty array passed in will be overridden with
5003     * the empty {@code public static} references in this class.
5004     * </p>
5005     *
5006     * @param array  The array to check for {@code null} or empty.
5007     * @return The same array, {@code public static} empty array if {@code null} or empty input.
5008     * @since 2.5
5009     */
5010    public static short[] nullToEmpty(final short[] array) {
5011        return isEmpty(array) ? EMPTY_SHORT_ARRAY : array;
5012    }
5013
5014    /**
5015     * Defensive programming technique to change a {@code null}
5016     * reference to an empty one.
5017     * <p>
5018     * This method returns an empty array for a {@code null} input array.
5019     * </p>
5020     * <p>
5021     * As a memory optimizing technique an empty array passed in will be overridden with
5022     * the empty {@code public static} references in this class.
5023     * </p>
5024     *
5025     * @param array  The array to check for {@code null} or empty.
5026     * @return The same array, {@code public static} empty array if {@code null} or empty input.
5027     * @since 2.5
5028     */
5029    public static Short[] nullToEmpty(final Short[] array) {
5030        return nullTo(array, EMPTY_SHORT_OBJECT_ARRAY);
5031    }
5032
5033    /**
5034     * Defensive programming technique to change a {@code null}
5035     * reference to an empty one.
5036     * <p>
5037     * This method returns an empty array for a {@code null} input array.
5038     * </p>
5039     * <p>
5040     * As a memory optimizing technique an empty array passed in will be overridden with
5041     * the empty {@code public static} references in this class.
5042     * </p>
5043     *
5044     * @param array  The array to check for {@code null} or empty.
5045     * @return The same array, {@code public static} empty array if {@code null} or empty input.
5046     * @since 2.5
5047     */
5048    public static String[] nullToEmpty(final String[] array) {
5049        return nullTo(array, EMPTY_STRING_ARRAY);
5050    }
5051
5052    /**
5053     * Defensive programming technique to change a {@code null}
5054     * reference to an empty one.
5055     * <p>
5056     * This method returns an empty array for a {@code null} input array.
5057     * </p>
5058     *
5059     * @param array  The array to check for {@code null} or empty.
5060     * @param type   The class representation of the desired array.
5061     * @param <T>  the class type.
5062     * @return The same array, {@code public static} empty array if {@code null}.
5063     * @throws IllegalArgumentException Thrown if the type argument is null.
5064     * @since 3.5
5065     */
5066    public static <T> T[] nullToEmpty(final T[] array, final Class<T[]> type) {
5067        if (type == null) {
5068            throw new IllegalArgumentException("The type must not be null");
5069        }
5070        if (array == null) {
5071            return type.cast(Array.newInstance(type.getComponentType(), 0));
5072        }
5073        return array;
5074    }
5075
5076    /**
5077     * Gets the current thread's {@link ThreadLocalRandom} for {@code shuffle} methods that don't take a {@link Random} argument.
5078     *
5079     * @return The current ThreadLocalRandom.
5080     */
5081    private static ThreadLocalRandom random() {
5082        return ThreadLocalRandom.current();
5083    }
5084
5085    /**
5086     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5087     * indices).
5088     * <p>
5089     * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5090     * returned array is always the same as that of the input array.
5091     * </p>
5092     * <p>
5093     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5094     * </p>
5095     *
5096     * <pre>
5097     * ArrayUtils.remove([true], 0)              = []
5098     * ArrayUtils.remove([true, false], 0)       = [false]
5099     * ArrayUtils.remove([true, false], 1)       = [true]
5100     * ArrayUtils.remove([true, true, false], 1) = [true, false]
5101     * </pre>
5102     *
5103     * @param array The array to remove the element from, may not be {@code null}.
5104     * @param index The position of the element to be removed.
5105     * @return A new array containing the existing elements except the element at the specified position.
5106     * @throws IndexOutOfBoundsException Thrown if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5107     * @since 2.1
5108     */
5109    public static boolean[] remove(final boolean[] array, final int index) {
5110        return (boolean[]) remove((Object) array, index);
5111    }
5112
5113    /**
5114     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5115     * indices).
5116     * <p>
5117     * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5118     * returned array is always the same as that of the input array.
5119     * </p>
5120     * <p>
5121     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5122     * </p>
5123     *
5124     * <pre>
5125     * ArrayUtils.remove([1], 0)          = []
5126     * ArrayUtils.remove([1, 0], 0)       = [0]
5127     * ArrayUtils.remove([1, 0], 1)       = [1]
5128     * ArrayUtils.remove([1, 0, 1], 1)    = [1, 1]
5129     * </pre>
5130     *
5131     * @param array The array to remove the element from, may not be {@code null}.
5132     * @param index The position of the element to be removed.
5133     * @return A new array containing the existing elements except the element at the specified position.
5134     * @throws IndexOutOfBoundsException Thrown if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5135     * @since 2.1
5136     */
5137    public static byte[] remove(final byte[] array, final int index) {
5138        return (byte[]) remove((Object) array, index);
5139    }
5140
5141    /**
5142     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5143     * indices).
5144     * <p>
5145     * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5146     * returned array is always the same as that of the input array.
5147     * </p>
5148     * <p>
5149     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5150     * </p>
5151     *
5152     * <pre>
5153     * ArrayUtils.remove(['a'], 0)           = []
5154     * ArrayUtils.remove(['a', 'b'], 0)      = ['b']
5155     * ArrayUtils.remove(['a', 'b'], 1)      = ['a']
5156     * ArrayUtils.remove(['a', 'b', 'c'], 1) = ['a', 'c']
5157     * </pre>
5158     *
5159     * @param array The array to remove the element from, may not be {@code null}.
5160     * @param index The position of the element to be removed.
5161     * @return A new array containing the existing elements except the element at the specified position.
5162     * @throws IndexOutOfBoundsException Thrown if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5163     * @since 2.1
5164     */
5165    public static char[] remove(final char[] array, final int index) {
5166        return (char[]) remove((Object) array, index);
5167    }
5168
5169    /**
5170     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5171     * indices).
5172     * <p>
5173     * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5174     * returned array is always the same as that of the input array.
5175     * </p>
5176     * <p>
5177     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5178     * </p>
5179     *
5180     * <pre>
5181     * ArrayUtils.remove([1.1], 0)           = []
5182     * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
5183     * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
5184     * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
5185     * </pre>
5186     *
5187     * @param array The array to remove the element from, may not be {@code null}.
5188     * @param index The position of the element to be removed.
5189     * @return A new array containing the existing elements except the element at the specified position.
5190     * @throws IndexOutOfBoundsException Thrown if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5191     * @since 2.1
5192     */
5193    public static double[] remove(final double[] array, final int index) {
5194        return (double[]) remove((Object) array, index);
5195    }
5196
5197    /**
5198     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5199     * indices).
5200     * <p>
5201     * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5202     * returned array is always the same as that of the input array.
5203     * </p>
5204     * <p>
5205     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5206     * </p>
5207     *
5208     * <pre>
5209     * ArrayUtils.remove([1.1], 0)           = []
5210     * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
5211     * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
5212     * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
5213     * </pre>
5214     *
5215     * @param array The array to remove the element from, may not be {@code null}.
5216     * @param index The position of the element to be removed.
5217     * @return A new array containing the existing elements except the element at the specified position.
5218     * @throws IndexOutOfBoundsException Thrown if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5219     * @since 2.1
5220     */
5221    public static float[] remove(final float[] array, final int index) {
5222        return (float[]) remove((Object) array, index);
5223    }
5224
5225    /**
5226     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5227     * indices).
5228     * <p>
5229     * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5230     * returned array is always the same as that of the input array.
5231     * </p>
5232     * <p>
5233     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5234     * </p>
5235     *
5236     * <pre>
5237     * ArrayUtils.remove([1], 0)         = []
5238     * ArrayUtils.remove([2, 6], 0)      = [6]
5239     * ArrayUtils.remove([2, 6], 1)      = [2]
5240     * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
5241     * </pre>
5242     *
5243     * @param array The array to remove the element from, may not be {@code null}.
5244     * @param index The position of the element to be removed.
5245     * @return A new array containing the existing elements except the element at the specified position.
5246     * @throws IndexOutOfBoundsException Thrown if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5247     * @since 2.1
5248     */
5249    public static int[] remove(final int[] array, final int index) {
5250        return (int[]) remove((Object) array, index);
5251    }
5252
5253    /**
5254     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5255     * indices).
5256     * <p>
5257     * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5258     * returned array is always the same as that of the input array.
5259     * </p>
5260     * <p>
5261     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5262     * </p>
5263     *
5264     * <pre>
5265     * ArrayUtils.remove([1], 0)         = []
5266     * ArrayUtils.remove([2, 6], 0)      = [6]
5267     * ArrayUtils.remove([2, 6], 1)      = [2]
5268     * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
5269     * </pre>
5270     *
5271     * @param array The array to remove the element from, may not be {@code null}.
5272     * @param index The position of the element to be removed.
5273     * @return A new array containing the existing elements except the element at the specified position.
5274     * @throws IndexOutOfBoundsException Thrown if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5275     * @since 2.1
5276     */
5277    public static long[] remove(final long[] array, final int index) {
5278        return (long[]) remove((Object) array, index);
5279    }
5280
5281    /**
5282     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5283     * indices).
5284     * <p>
5285     * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5286     * returned array is always the same as that of the input array.
5287     * </p>
5288     * <p>
5289     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5290     * </p>
5291     *
5292     * @param array The array to remove the element from, may not be {@code null}.
5293     * @param index The position of the element to be removed.
5294     * @return A new array containing the existing elements except the element at the specified position.
5295     * @throws IndexOutOfBoundsException Thrown if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5296     * @since 2.1
5297     */
5298    private static Object remove(final Object array, final int index) {
5299        final int length = getLength(array);
5300        if (index < 0 || index >= length) {
5301            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
5302        }
5303        final Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
5304        System.arraycopy(array, 0, result, 0, index);
5305        if (index < length - 1) {
5306            System.arraycopy(array, index + 1, result, index, length - index - 1);
5307        }
5308        return result;
5309    }
5310
5311    /**
5312     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5313     * indices).
5314     * <p>
5315     * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5316     * returned array is always the same as that of the input array.
5317     * </p>
5318     * <p>
5319     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5320     * </p>
5321     *
5322     * <pre>
5323     * ArrayUtils.remove([1], 0)         = []
5324     * ArrayUtils.remove([2, 6], 0)      = [6]
5325     * ArrayUtils.remove([2, 6], 1)      = [2]
5326     * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
5327     * </pre>
5328     *
5329     * @param array The array to remove the element from, may not be {@code null}.
5330     * @param index The position of the element to be removed.
5331     * @return A new array containing the existing elements except the element at the specified position.
5332     * @throws IndexOutOfBoundsException Thrown if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5333     * @since 2.1
5334     */
5335    public static short[] remove(final short[] array, final int index) {
5336        return (short[]) remove((Object) array, index);
5337    }
5338
5339    /**
5340     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5341     * indices).
5342     * <p>
5343     * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5344     * returned array is always the same as that of the input array.
5345     * </p>
5346     * <p>
5347     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5348     * </p>
5349     *
5350     * <pre>
5351     * ArrayUtils.remove(["a"], 0)           = []
5352     * ArrayUtils.remove(["a", "b"], 0)      = ["b"]
5353     * ArrayUtils.remove(["a", "b"], 1)      = ["a"]
5354     * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"]
5355     * </pre>
5356     *
5357     * @param <T>   the component type of the array.
5358     * @param array The array to remove the element from, may not be {@code null}.
5359     * @param index The position of the element to be removed.
5360     * @return A new array containing the existing elements except the element at the specified position.
5361     * @throws IndexOutOfBoundsException Thrown if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5362     * @since 2.1
5363     */
5364    @SuppressWarnings("unchecked") // remove() always creates an array of the same type as its input
5365    public static <T> T[] remove(final T[] array, final int index) {
5366        return (T[]) remove((Object) array, index);
5367    }
5368
5369    /**
5370     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5371     * <p>
5372     * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5373     * array is always the same as that of the input array.
5374     * </p>
5375     * <p>
5376     * If the input array is {@code null}, then return {@code null}.
5377     * </p>
5378     *
5379     * <pre>
5380     * ArrayUtils.removeAll([true, false, true], 0, 2) = [false]
5381     * ArrayUtils.removeAll([true, false, true], 1, 2) = [true]
5382     * </pre>
5383     *
5384     * @param array   The array to remove the element from, may not be {@code null}.
5385     * @param indices The positions of the elements to be removed.
5386     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5387     * @throws IndexOutOfBoundsException Thrown if any index is out of range (index &lt; 0 || index &gt;= array.length).
5388     * @since 3.0.1
5389     */
5390    public static boolean[] removeAll(final boolean[] array, final int... indices) {
5391        return (boolean[]) removeAll((Object) array, indices);
5392    }
5393
5394    /**
5395     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5396     * <p>
5397     * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5398     * array is always the same as that of the input array.
5399     * </p>
5400     * <p>
5401     * If the input array is {@code null}, then return {@code null}.
5402     * </p>
5403     *
5404     * <pre>
5405     * ArrayUtils.removeAll([1], 0)             = []
5406     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5407     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5408     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5409     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5410     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5411     * </pre>
5412     *
5413     * @param array   The array to remove the element from, may not be {@code null}.
5414     * @param indices The positions of the elements to be removed.
5415     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5416     * @throws IndexOutOfBoundsException Thrown if any index is out of range (index &lt; 0 || index &gt;= array.length).
5417     * @since 3.0.1
5418     */
5419    public static byte[] removeAll(final byte[] array, final int... indices) {
5420        return (byte[]) removeAll((Object) array, indices);
5421    }
5422
5423    /**
5424     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5425     * <p>
5426     * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5427     * array is always the same as that of the input array.
5428     * </p>
5429     * <p>
5430     * If the input array is {@code null}, then return {@code null}.
5431     * </p>
5432     *
5433     * <pre>
5434     * ArrayUtils.removeAll([1], 0)             = []
5435     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5436     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5437     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5438     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5439     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5440     * </pre>
5441     *
5442     * @param array   The array to remove the element from, may not be {@code null}.
5443     * @param indices The positions of the elements to be removed.
5444     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5445     * @throws IndexOutOfBoundsException Thrown if any index is out of range (index &lt; 0 || index &gt;= array.length).
5446     * @since 3.0.1
5447     */
5448    public static char[] removeAll(final char[] array, final int... indices) {
5449        return (char[]) removeAll((Object) array, indices);
5450    }
5451
5452    /**
5453     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5454     * <p>
5455     * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5456     * array is always the same as that of the input array.
5457     * </p>
5458     * <p>
5459     * If the input array is {@code null}, then return {@code null}.
5460     * </p>
5461     *
5462     * <pre>
5463     * ArrayUtils.removeAll([1], 0)             = []
5464     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5465     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5466     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5467     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5468     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5469     * </pre>
5470     *
5471     * @param array   The array to remove the element from, may not be {@code null}.
5472     * @param indices The positions of the elements to be removed.
5473     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5474     * @throws IndexOutOfBoundsException Thrown if any index is out of range (index &lt; 0 || index &gt;= array.length).
5475     * @since 3.0.1
5476     */
5477    public static double[] removeAll(final double[] array, final int... indices) {
5478        return (double[]) removeAll((Object) array, indices);
5479    }
5480
5481    /**
5482     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5483     * <p>
5484     * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5485     * array is always the same as that of the input array.
5486     * </p>
5487     * <p>
5488     * If the input array is {@code null}, then return {@code null}.
5489     * </p>
5490     *
5491     * <pre>
5492     * ArrayUtils.removeAll([1], 0)             = []
5493     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5494     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5495     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5496     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5497     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5498     * </pre>
5499     *
5500     * @param array   The array to remove the element from, may not be {@code null}.
5501     * @param indices The positions of the elements to be removed.
5502     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5503     * @throws IndexOutOfBoundsException Thrown if any index is out of range (index &lt; 0 || index &gt;= array.length).
5504     * @since 3.0.1
5505     */
5506    public static float[] removeAll(final float[] array, final int... indices) {
5507        return (float[]) removeAll((Object) array, indices);
5508    }
5509
5510    /**
5511     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5512     * <p>
5513     * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5514     * array is always the same as that of the input array.
5515     * </p>
5516     * <p>
5517     * If the input array is {@code null}, then return {@code null}.
5518     * </p>
5519     *
5520     * <pre>
5521     * ArrayUtils.removeAll([1], 0)             = []
5522     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5523     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5524     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5525     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5526     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5527     * </pre>
5528     *
5529     * @param array   The array to remove the element from, may not be {@code null}.
5530     * @param indices The positions of the elements to be removed.
5531     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5532     * @throws IndexOutOfBoundsException Thrown if any index is out of range (index &lt; 0 || index &gt;= array.length).
5533     * @since 3.0.1
5534     */
5535    public static int[] removeAll(final int[] array, final int... indices) {
5536        return (int[]) removeAll((Object) array, indices);
5537    }
5538
5539    /**
5540     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5541     * <p>
5542     * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5543     * array is always the same as that of the input array.
5544     * </p>
5545     * <p>
5546     * If the input array is {@code null}, then return {@code null}.
5547     * </p>
5548     *
5549     * <pre>
5550     * ArrayUtils.removeAll([1], 0)             = []
5551     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5552     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5553     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5554     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5555     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5556     * </pre>
5557     *
5558     * @param array   The array to remove the element from, may not be {@code null}.
5559     * @param indices The positions of the elements to be removed.
5560     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5561     * @throws IndexOutOfBoundsException Thrown if any index is out of range (index &lt; 0 || index &gt;= array.length).
5562     * @since 3.0.1
5563     */
5564    public static long[] removeAll(final long[] array, final int... indices) {
5565        return (long[]) removeAll((Object) array, indices);
5566    }
5567
5568    /**
5569     * Removes multiple array elements specified by index.
5570     *
5571     * @param array   source
5572     * @param indices to remove
5573     * @return new array of same type minus elements specified by unique values of {@code indices}
5574     */
5575    // package protected for access by unit tests
5576    static Object removeAll(final Object array, final int... indices) {
5577        if (array == null) {
5578            return null;
5579        }
5580        final int length = getLength(array);
5581        int diff = 0; // number of distinct indexes, i.e. number of entries that will be removed
5582        final int[] clonedIndices = ArraySorter.sort(clone(indices));
5583        // identify length of result array
5584        if (isNotEmpty(clonedIndices)) {
5585            int i = clonedIndices.length;
5586            int prevIndex = length;
5587            while (--i >= 0) {
5588                final int index = clonedIndices[i];
5589                if (index < 0 || index >= length) {
5590                    throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
5591                }
5592                if (index >= prevIndex) {
5593                    continue;
5594                }
5595                diff++;
5596                prevIndex = index;
5597            }
5598        }
5599        // create result array
5600        final Object result = Array.newInstance(array.getClass().getComponentType(), length - diff);
5601        if (diff < length && clonedIndices != null) {
5602            int end = length; // index just after last copy
5603            int dest = length - diff; // number of entries so far not copied
5604            for (int i = clonedIndices.length - 1; i >= 0; i--) {
5605                final int index = clonedIndices[i];
5606                if (end - index > 1) { // same as (cp > 0)
5607                    final int cp = end - index - 1;
5608                    dest -= cp;
5609                    System.arraycopy(array, index + 1, result, dest, cp);
5610                    // After this copy, we still have room for dest items.
5611                }
5612                end = index;
5613            }
5614            if (end > 0) {
5615                System.arraycopy(array, 0, result, 0, end);
5616            }
5617        }
5618        return result;
5619    }
5620
5621    /**
5622     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5623     * <p>
5624     * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5625     * array is always the same as that of the input array.
5626     * </p>
5627     * <p>
5628     * If the input array is {@code null}, then return {@code null}.
5629     * </p>
5630     *
5631     * <pre>
5632     * ArrayUtils.removeAll([1], 0)             = []
5633     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5634     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5635     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5636     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5637     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5638     * </pre>
5639     *
5640     * @param array   The array to remove the element from, may not be {@code null}.
5641     * @param indices The positions of the elements to be removed.
5642     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5643     * @throws IndexOutOfBoundsException Thrown if any index is out of range (index &lt; 0 || index &gt;= array.length).
5644     * @since 3.0.1
5645     */
5646    public static short[] removeAll(final short[] array, final int... indices) {
5647        return (short[]) removeAll((Object) array, indices);
5648    }
5649
5650    /**
5651     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5652     * <p>
5653     * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5654     * array is always the same as that of the input array.
5655     * </p>
5656     * <p>
5657     * If the input array is {@code null}, then return {@code null}.
5658     * </p>
5659     *
5660     * <pre>
5661     * ArrayUtils.removeAll(["a", "b", "c"], 0, 2) = ["b"]
5662     * ArrayUtils.removeAll(["a", "b", "c"], 1, 2) = ["a"]
5663     * </pre>
5664     *
5665     * @param <T>     the component type of the array.
5666     * @param array   The array to remove the element from, may not be {@code null}.
5667     * @param indices The positions of the elements to be removed.
5668     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5669     * @throws IndexOutOfBoundsException Thrown if any index is out of range (index &lt; 0 || index &gt;= array.length).
5670     * @since 3.0.1
5671     */
5672    @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
5673    public static <T> T[] removeAll(final T[] array, final int... indices) {
5674        return (T[]) removeAll((Object) array, indices);
5675    }
5676
5677    /**
5678     * Removes the occurrences of the specified element from the specified boolean array.
5679     * <p>
5680     * All subsequent elements are shifted to the left (subtracts one from their indices).
5681     * If the array doesn't contain such an element, no elements are removed from the array.
5682     * {@code null} will be returned if the input array is {@code null}.
5683     * </p>
5684     *
5685     * @param array The input array, will not be modified, and may be {@code null}.
5686     * @param element The element to remove.
5687     * @return A new array containing the existing elements except the occurrences of the specified element.
5688     * @since 3.5
5689     * @deprecated Use {@link #removeAllOccurrences(boolean[], boolean)}.
5690     */
5691    @Deprecated
5692    public static boolean[] removeAllOccurences(final boolean[] array, final boolean element) {
5693        return (boolean[]) removeAt(array, indexesOf(array, element));
5694    }
5695
5696    /**
5697     * Removes the occurrences of the specified element from the specified byte array.
5698     * <p>
5699     * All subsequent elements are shifted to the left (subtracts one from their indices).
5700     * If the array doesn't contain such an element, no elements are removed from the array.
5701     * {@code null} will be returned if the input array is {@code null}.
5702     * </p>
5703     *
5704     * @param array The input array, will not be modified, and may be {@code null}.
5705     * @param element The element to remove.
5706     * @return A new array containing the existing elements except the occurrences of the specified element.
5707     * @since 3.5
5708     * @deprecated Use {@link #removeAllOccurrences(byte[], byte)}.
5709     */
5710    @Deprecated
5711    public static byte[] removeAllOccurences(final byte[] array, final byte element) {
5712        return (byte[]) removeAt(array, indexesOf(array, element));
5713    }
5714
5715    /**
5716     * Removes the occurrences of the specified element from the specified char array.
5717     * <p>
5718     * All subsequent elements are shifted to the left (subtracts one from their indices).
5719     * If the array doesn't contain such an element, no elements are removed from the array.
5720     * {@code null} will be returned if the input array is {@code null}.
5721     * </p>
5722     *
5723     * @param array The input array, will not be modified, and may be {@code null}.
5724     * @param element The element to remove.
5725     * @return A new array containing the existing elements except the occurrences of the specified element.
5726     * @since 3.5
5727     * @deprecated Use {@link #removeAllOccurrences(char[], char)}.
5728     */
5729    @Deprecated
5730    public static char[] removeAllOccurences(final char[] array, final char element) {
5731        return (char[]) removeAt(array, indexesOf(array, element));
5732    }
5733
5734    /**
5735     * Removes the occurrences of the specified element from the specified double array.
5736     * <p>
5737     * All subsequent elements are shifted to the left (subtracts one from their indices).
5738     * If the array doesn't contain such an element, no elements are removed from the array.
5739     * {@code null} will be returned if the input array is {@code null}.
5740     * </p>
5741     *
5742     * @param array The input array, will not be modified, and may be {@code null}.
5743     * @param element The element to remove.
5744     * @return A new array containing the existing elements except the occurrences of the specified element.
5745     * @since 3.5
5746     * @deprecated Use {@link #removeAllOccurrences(double[], double)}.
5747     */
5748    @Deprecated
5749    public static double[] removeAllOccurences(final double[] array, final double element) {
5750        return (double[]) removeAt(array, indexesOf(array, element));
5751    }
5752
5753    /**
5754     * Removes the occurrences of the specified element from the specified float array.
5755     * <p>
5756     * All subsequent elements are shifted to the left (subtracts one from their indices).
5757     * If the array doesn't contain such an element, no elements are removed from the array.
5758     * {@code null} will be returned if the input array is {@code null}.
5759     * </p>
5760     *
5761     * @param array The input array, will not be modified, and may be {@code null}.
5762     * @param element The element to remove.
5763     * @return A new array containing the existing elements except the occurrences of the specified element.
5764     * @since 3.5
5765     * @deprecated Use {@link #removeAllOccurrences(float[], float)}.
5766     */
5767    @Deprecated
5768    public static float[] removeAllOccurences(final float[] array, final float element) {
5769        return (float[]) removeAt(array, indexesOf(array, element));
5770    }
5771
5772    /**
5773     * Removes the occurrences of the specified element from the specified int array.
5774     * <p>
5775     * All subsequent elements are shifted to the left (subtracts one from their indices).
5776     * If the array doesn't contain such an element, no elements are removed from the array.
5777     * {@code null} will be returned if the input array is {@code null}.
5778     * </p>
5779     *
5780     * @param array The input array, will not be modified, and may be {@code null}.
5781     * @param element The element to remove.
5782     * @return A new array containing the existing elements except the occurrences of the specified element.
5783     * @since 3.5
5784     * @deprecated Use {@link #removeAllOccurrences(int[], int)}.
5785     */
5786    @Deprecated
5787    public static int[] removeAllOccurences(final int[] array, final int element) {
5788        return (int[]) removeAt(array, indexesOf(array, element));
5789    }
5790
5791    /**
5792     * Removes the occurrences of the specified element from the specified long array.
5793     * <p>
5794     * All subsequent elements are shifted to the left (subtracts one from their indices).
5795     * If the array doesn't contain such an element, no elements are removed from the array.
5796     * {@code null} will be returned if the input array is {@code null}.
5797     * </p>
5798     *
5799     * @param array The input array, will not be modified, and may be {@code null}.
5800     * @param element The element to remove.
5801     * @return A new array containing the existing elements except the occurrences of the specified element.
5802     * @since 3.5
5803     * @deprecated Use {@link #removeAllOccurrences(long[], long)}.
5804     */
5805    @Deprecated
5806    public static long[] removeAllOccurences(final long[] array, final long element) {
5807        return (long[]) removeAt(array, indexesOf(array, element));
5808    }
5809
5810    /**
5811     * Removes the occurrences of the specified element from the specified short array.
5812     * <p>
5813     * All subsequent elements are shifted to the left (subtracts one from their indices).
5814     * If the array doesn't contain such an element, no elements are removed from the array.
5815     * {@code null} will be returned if the input array is {@code null}.
5816     * </p>
5817     *
5818     * @param array The input array, will not be modified, and may be {@code null}.
5819     * @param element The element to remove.
5820     * @return A new array containing the existing elements except the occurrences of the specified element.
5821     * @since 3.5
5822     * @deprecated Use {@link #removeAllOccurrences(short[], short)}.
5823     */
5824    @Deprecated
5825    public static short[] removeAllOccurences(final short[] array, final short element) {
5826        return (short[]) removeAt(array, indexesOf(array, element));
5827    }
5828
5829    /**
5830     * Removes the occurrences of the specified element from the specified array.
5831     * <p>
5832     * All subsequent elements are shifted to the left (subtracts one from their indices).
5833     * If the array doesn't contain such an element, no elements are removed from the array.
5834     * {@code null} will be returned if the input array is {@code null}.
5835     * </p>
5836     *
5837     * @param <T> The type of object in the array, may be {@code null}.
5838     * @param array The input array, will not be modified, and may be {@code null}.
5839     * @param element The element to remove, may be {@code null}.
5840     * @return A new array containing the existing elements except the occurrences of the specified element.
5841     * @since 3.5
5842     * @deprecated Use {@link #removeAllOccurrences(Object[], Object)}.
5843     */
5844    @Deprecated
5845    public static <T> T[] removeAllOccurences(final T[] array, final T element) {
5846        return (T[]) removeAt(array, indexesOf(array, element));
5847    }
5848
5849    /**
5850     * Removes the occurrences of the specified element from the specified boolean array.
5851     * <p>
5852     * All subsequent elements are shifted to the left (subtracts one from their indices).
5853     * If the array doesn't contain such an element, no elements are removed from the array.
5854     * {@code null} will be returned if the input array is {@code null}.
5855     * </p>
5856     *
5857     * @param array The input array, will not be modified, and may be {@code null}.
5858     * @param element The element to remove.
5859     * @return A new array containing the existing elements except the occurrences of the specified element.
5860     * @since 3.10
5861     */
5862    public static boolean[] removeAllOccurrences(final boolean[] array, final boolean element) {
5863        return (boolean[]) removeAt(array, indexesOf(array, element));
5864    }
5865
5866    /**
5867     * Removes the occurrences of the specified element from the specified byte array.
5868     * <p>
5869     * All subsequent elements are shifted to the left (subtracts one from their indices).
5870     * If the array doesn't contain such an element, no elements are removed from the array.
5871     * {@code null} will be returned if the input array is {@code null}.
5872     * </p>
5873     *
5874     * @param array The input array, will not be modified, and may be {@code null}.
5875     * @param element The element to remove.
5876     * @return A new array containing the existing elements except the occurrences of the specified element.
5877     * @since 3.10
5878     */
5879    public static byte[] removeAllOccurrences(final byte[] array, final byte element) {
5880        return (byte[]) removeAt(array, indexesOf(array, element));
5881    }
5882
5883    /**
5884     * Removes the occurrences of the specified element from the specified char array.
5885     * <p>
5886     * All subsequent elements are shifted to the left (subtracts one from their indices).
5887     * If the array doesn't contain such an element, no elements are removed from the array.
5888     * {@code null} will be returned if the input array is {@code null}.
5889     * </p>
5890     *
5891     * @param array The input array, will not be modified, and may be {@code null}.
5892     * @param element The element to remove.
5893     * @return A new array containing the existing elements except the occurrences of the specified element.
5894     * @since 3.10
5895     */
5896    public static char[] removeAllOccurrences(final char[] array, final char element) {
5897        return (char[]) removeAt(array, indexesOf(array, element));
5898    }
5899
5900    /**
5901     * Removes the occurrences of the specified element from the specified double array.
5902     * <p>
5903     * All subsequent elements are shifted to the left (subtracts one from their indices).
5904     * If the array doesn't contain such an element, no elements are removed from the array.
5905     * {@code null} will be returned if the input array is {@code null}.
5906     * </p>
5907     *
5908     * @param array The input array, will not be modified, and may be {@code null}.
5909     * @param element The element to remove.
5910     * @return A new array containing the existing elements except the occurrences of the specified element.
5911     * @since 3.10
5912     */
5913    public static double[] removeAllOccurrences(final double[] array, final double element) {
5914        return (double[]) removeAt(array, indexesOf(array, element));
5915    }
5916
5917    /**
5918     * Removes the occurrences of the specified element from the specified float array.
5919     * <p>
5920     * All subsequent elements are shifted to the left (subtracts one from their indices).
5921     * If the array doesn't contain such an element, no elements are removed from the array.
5922     * {@code null} will be returned if the input array is {@code null}.
5923     * </p>
5924     *
5925     * @param array The input array, will not be modified, and may be {@code null}.
5926     * @param element The element to remove.
5927     * @return A new array containing the existing elements except the occurrences of the specified element.
5928     * @since 3.10
5929     */
5930    public static float[] removeAllOccurrences(final float[] array, final float element) {
5931        return (float[]) removeAt(array, indexesOf(array, element));
5932    }
5933
5934    /**
5935     * Removes the occurrences of the specified element from the specified int array.
5936     * <p>
5937     * All subsequent elements are shifted to the left (subtracts one from their indices).
5938     * If the array doesn't contain such an element, no elements are removed from the array.
5939     * {@code null} will be returned if the input array is {@code null}.
5940     * </p>
5941     *
5942     * @param array The input array, will not be modified, and may be {@code null}.
5943     * @param element The element to remove.
5944     * @return A new array containing the existing elements except the occurrences of the specified element.
5945     * @since 3.10
5946     */
5947    public static int[] removeAllOccurrences(final int[] array, final int element) {
5948        return (int[]) removeAt(array, indexesOf(array, element));
5949    }
5950
5951    /**
5952     * Removes the occurrences of the specified element from the specified long array.
5953     * <p>
5954     * All subsequent elements are shifted to the left (subtracts one from their indices).
5955     * If the array doesn't contain such an element, no elements are removed from the array.
5956     * {@code null} will be returned if the input array is {@code null}.
5957     * </p>
5958     *
5959     * @param array The input array, will not be modified, and may be {@code null}.
5960     * @param element The element to remove.
5961     * @return A new array containing the existing elements except the occurrences of the specified element.
5962     * @since 3.10
5963     */
5964    public static long[] removeAllOccurrences(final long[] array, final long element) {
5965        return (long[]) removeAt(array, indexesOf(array, element));
5966    }
5967
5968    /**
5969     * Removes the occurrences of the specified element from the specified short array.
5970     * <p>
5971     * All subsequent elements are shifted to the left (subtracts one from their indices).
5972     * If the array doesn't contain such an element, no elements are removed from the array.
5973     * {@code null} will be returned if the input array is {@code null}.
5974     * </p>
5975     *
5976     * @param array The input array, will not be modified, and may be {@code null}.
5977     * @param element The element to remove.
5978     * @return A new array containing the existing elements except the occurrences of the specified element.
5979     * @since 3.10
5980     */
5981    public static short[] removeAllOccurrences(final short[] array, final short element) {
5982        return (short[]) removeAt(array, indexesOf(array, element));
5983    }
5984
5985    /**
5986     * Removes the occurrences of the specified element from the specified array.
5987     * <p>
5988     * All subsequent elements are shifted to the left (subtracts one from their indices).
5989     * If the array doesn't contain such an element, no elements are removed from the array.
5990     * {@code null} will be returned if the input array is {@code null}.
5991     * </p>
5992     *
5993     * @param <T> The type of object in the array, may be {@code null}.
5994     * @param array The input array, will not be modified, and may be {@code null}.
5995     * @param element The element to remove, may be {@code null}.
5996     * @return A new array containing the existing elements except the occurrences of the specified element.
5997     * @since 3.10
5998     */
5999    public static <T> T[] removeAllOccurrences(final T[] array, final T element) {
6000        return (T[]) removeAt(array, indexesOf(array, element));
6001    }
6002
6003    /**
6004     * Removes multiple array elements specified by indices.
6005     *
6006     * @param array The input array, will not be modified, and may be {@code null}.
6007     * @param indices to remove.
6008     * @return new array of same type minus elements specified by the set bits in {@code indices}.
6009     */
6010    // package protected for access by unit tests
6011    static Object removeAt(final Object array, final BitSet indices) {
6012        if (array == null) {
6013            return null;
6014        }
6015        final int srcLength = getLength(array);
6016        // No need to check maxIndex here, because method only currently called from removeElements()
6017        // which guarantee to generate only valid bit entries.
6018//        final int maxIndex = indices.length();
6019//        if (maxIndex > srcLength) {
6020//            throw new IndexOutOfBoundsException("Index: " + (maxIndex-1) + ", Length: " + srcLength);
6021//        }
6022        final int removals = indices.cardinality(); // true bits are items to remove
6023        final Object result = Array.newInstance(array.getClass().getComponentType(), srcLength - removals);
6024        int srcIndex = 0;
6025        int destIndex = 0;
6026        int count;
6027        int set;
6028        while ((set = indices.nextSetBit(srcIndex)) != -1) {
6029            count = set - srcIndex;
6030            if (count > 0) {
6031                System.arraycopy(array, srcIndex, result, destIndex, count);
6032                destIndex += count;
6033            }
6034            srcIndex = indices.nextClearBit(set);
6035        }
6036        count = srcLength - srcIndex;
6037        if (count > 0) {
6038            System.arraycopy(array, srcIndex, result, destIndex, count);
6039        }
6040        return result;
6041    }
6042
6043    /**
6044     * Removes the first occurrence of the specified element from the
6045     * specified array. All subsequent elements are shifted to the left
6046     * (subtracts one from their indices). If the array doesn't contain
6047     * such an element, no elements are removed from the array.
6048     * <p>
6049     * This method returns a new array with the same elements of the input
6050     * array except the first occurrence of the specified element. The component
6051     * type of the returned array is always the same as that of the input
6052     * array.
6053     * </p>
6054     * <pre>
6055     * ArrayUtils.removeElement(null, true)                = null
6056     * ArrayUtils.removeElement([], true)                  = []
6057     * ArrayUtils.removeElement([true], false)             = [true]
6058     * ArrayUtils.removeElement([true, false], false)      = [true]
6059     * ArrayUtils.removeElement([true, false, true], true) = [false, true]
6060     * </pre>
6061     *
6062     * @param array The input array, may be {@code null}.
6063     * @param element  The element to be removed.
6064     * @return A new array containing the existing elements except the first
6065     *         occurrence of the specified element.
6066     * @since 2.1
6067     */
6068    public static boolean[] removeElement(final boolean[] array, final boolean element) {
6069        final int index = indexOf(array, element);
6070        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6071    }
6072
6073    /**
6074     * Removes the first occurrence of the specified element from the
6075     * specified array. All subsequent elements are shifted to the left
6076     * (subtracts one from their indices). If the array doesn't contain
6077     * such an element, no elements are removed from the array.
6078     * <p>
6079     * This method returns a new array with the same elements of the input
6080     * array except the first occurrence of the specified element. The component
6081     * type of the returned array is always the same as that of the input
6082     * array.
6083     * </p>
6084     * <pre>
6085     * ArrayUtils.removeElement(null, 1)        = null
6086     * ArrayUtils.removeElement([], 1)          = []
6087     * ArrayUtils.removeElement([1], 0)         = [1]
6088     * ArrayUtils.removeElement([1, 0], 0)      = [1]
6089     * ArrayUtils.removeElement([1, 0, 1], 1)   = [0, 1]
6090     * </pre>
6091     *
6092     * @param array The input array, may be {@code null}.
6093     * @param element  The element to be removed.
6094     * @return A new array containing the existing elements except the first
6095     *         occurrence of the specified element.
6096     * @since 2.1
6097     */
6098    public static byte[] removeElement(final byte[] array, final byte element) {
6099        final int index = indexOf(array, element);
6100        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6101    }
6102
6103    /**
6104     * Removes the first occurrence of the specified element from the
6105     * specified array. All subsequent elements are shifted to the left
6106     * (subtracts one from their indices). If the array doesn't contain
6107     * such an element, no elements are removed from the array.
6108     * <p>
6109     * This method returns a new array with the same elements of the input
6110     * array except the first occurrence of the specified element. The component
6111     * type of the returned array is always the same as that of the input
6112     * array.
6113     * </p>
6114     * <pre>
6115     * ArrayUtils.removeElement(null, 'a')            = null
6116     * ArrayUtils.removeElement([], 'a')              = []
6117     * ArrayUtils.removeElement(['a'], 'b')           = ['a']
6118     * ArrayUtils.removeElement(['a', 'b'], 'a')      = ['b']
6119     * ArrayUtils.removeElement(['a', 'b', 'a'], 'a') = ['b', 'a']
6120     * </pre>
6121     *
6122     * @param array The input array, may be {@code null}.
6123     * @param element  The element to be removed.
6124     * @return A new array containing the existing elements except the first
6125     *         occurrence of the specified element.
6126     * @since 2.1
6127     */
6128    public static char[] removeElement(final char[] array, final char element) {
6129        final int index = indexOf(array, element);
6130        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6131    }
6132
6133    /**
6134     * Removes the first occurrence of the specified element from the
6135     * specified array. All subsequent elements are shifted to the left
6136     * (subtracts one from their indices). If the array doesn't contain
6137     * such an element, no elements are removed from the array.
6138     * <p>
6139     * This method returns a new array with the same elements of the input
6140     * array except the first occurrence of the specified element. The component
6141     * type of the returned array is always the same as that of the input
6142     * array.
6143     * </p>
6144     * <pre>
6145     * ArrayUtils.removeElement(null, 1.1)            = null
6146     * ArrayUtils.removeElement([], 1.1)              = []
6147     * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
6148     * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
6149     * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
6150     * </pre>
6151     *
6152     * @param array The input array, may be {@code null}.
6153     * @param element  The element to be removed.
6154     * @return A new array containing the existing elements except the first
6155     *         occurrence of the specified element.
6156     * @since 2.1
6157     */
6158    public static double[] removeElement(final double[] array, final double element) {
6159        final int index = indexOf(array, element);
6160        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6161    }
6162
6163    /**
6164     * Removes the first occurrence of the specified element from the
6165     * specified array. All subsequent elements are shifted to the left
6166     * (subtracts one from their indices). If the array doesn't contain
6167     * such an element, no elements are removed from the array.
6168     * <p>
6169     * This method returns a new array with the same elements of the input
6170     * array except the first occurrence of the specified element. The component
6171     * type of the returned array is always the same as that of the input
6172     * array.
6173     * </p>
6174     * <pre>
6175     * ArrayUtils.removeElement(null, 1.1)            = null
6176     * ArrayUtils.removeElement([], 1.1)              = []
6177     * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
6178     * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
6179     * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
6180     * </pre>
6181     *
6182     * @param array The input array, may be {@code null}.
6183     * @param element  The element to be removed.
6184     * @return A new array containing the existing elements except the first
6185     *         occurrence of the specified element.
6186     * @since 2.1
6187     */
6188    public static float[] removeElement(final float[] array, final float element) {
6189        final int index = indexOf(array, element);
6190        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6191    }
6192
6193    /**
6194     * Removes the first occurrence of the specified element from the
6195     * specified array. All subsequent elements are shifted to the left
6196     * (subtracts one from their indices). If the array doesn't contain
6197     * such an element, no elements are removed from the array.
6198     * <p>
6199     * This method returns a new array with the same elements of the input
6200     * array except the first occurrence of the specified element. The component
6201     * type of the returned array is always the same as that of the input
6202     * array.
6203     * </p>
6204     * <pre>
6205     * ArrayUtils.removeElement(null, 1)      = null
6206     * ArrayUtils.removeElement([], 1)        = []
6207     * ArrayUtils.removeElement([1], 2)       = [1]
6208     * ArrayUtils.removeElement([1, 3], 1)    = [3]
6209     * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
6210     * </pre>
6211     *
6212     * @param array The input array, may be {@code null}.
6213     * @param element  The element to be removed.
6214     * @return A new array containing the existing elements except the first
6215     *         occurrence of the specified element.
6216     * @since 2.1
6217     */
6218    public static int[] removeElement(final int[] array, final int element) {
6219        final int index = indexOf(array, element);
6220        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6221    }
6222
6223    /**
6224     * Removes the first occurrence of the specified element from the
6225     * specified array. All subsequent elements are shifted to the left
6226     * (subtracts one from their indices). If the array doesn't contain
6227     * such an element, no elements are removed from the array.
6228     * <p>
6229     * This method returns a new array with the same elements of the input
6230     * array except the first occurrence of the specified element. The component
6231     * type of the returned array is always the same as that of the input
6232     * array.
6233     * </p>
6234     * <pre>
6235     * ArrayUtils.removeElement(null, 1)      = null
6236     * ArrayUtils.removeElement([], 1)        = []
6237     * ArrayUtils.removeElement([1], 2)       = [1]
6238     * ArrayUtils.removeElement([1, 3], 1)    = [3]
6239     * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
6240     * </pre>
6241     *
6242     * @param array The input array, may be {@code null}.
6243     * @param element  The element to be removed.
6244     * @return A new array containing the existing elements except the first
6245     *         occurrence of the specified element.
6246     * @since 2.1
6247     */
6248    public static long[] removeElement(final long[] array, final long element) {
6249        final int index = indexOf(array, element);
6250        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6251    }
6252
6253    /**
6254     * Removes the first occurrence of the specified element from the
6255     * specified array. All subsequent elements are shifted to the left
6256     * (subtracts one from their indices). If the array doesn't contain
6257     * such an element, no elements are removed from the array.
6258     * <p>
6259     * This method returns a new array with the same elements of the input
6260     * array except the first occurrence of the specified element. The component
6261     * type of the returned array is always the same as that of the input
6262     * array.
6263     * </p>
6264     * <pre>
6265     * ArrayUtils.removeElement(null, 1)      = null
6266     * ArrayUtils.removeElement([], 1)        = []
6267     * ArrayUtils.removeElement([1], 2)       = [1]
6268     * ArrayUtils.removeElement([1, 3], 1)    = [3]
6269     * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
6270     * </pre>
6271     *
6272     * @param array The input array, may be {@code null}.
6273     * @param element  The element to be removed.
6274     * @return A new array containing the existing elements except the first
6275     *         occurrence of the specified element.
6276     * @since 2.1
6277     */
6278    public static short[] removeElement(final short[] array, final short element) {
6279        final int index = indexOf(array, element);
6280        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6281    }
6282
6283    /**
6284     * Removes the first occurrence of the specified element from the
6285     * specified array. All subsequent elements are shifted to the left
6286     * (subtracts one from their indices). If the array doesn't contain
6287     * such an element, no elements are removed from the array.
6288     * <p>
6289     * This method returns a new array with the same elements of the input
6290     * array except the first occurrence of the specified element. The component
6291     * type of the returned array is always the same as that of the input
6292     * array.
6293     * </p>
6294     * <pre>
6295     * ArrayUtils.removeElement(null, "a")            = null
6296     * ArrayUtils.removeElement([], "a")              = []
6297     * ArrayUtils.removeElement(["a"], "b")           = ["a"]
6298     * ArrayUtils.removeElement(["a", "b"], "a")      = ["b"]
6299     * ArrayUtils.removeElement(["a", "b", "a"], "a") = ["b", "a"]
6300     * </pre>
6301     *
6302     * @param <T> The component type of the array
6303     * @param array The input array, may be {@code null}.
6304     * @param element  The element to be removed, may be {@code null}.
6305     * @return A new array containing the existing elements except the first
6306     *         occurrence of the specified element.
6307     * @since 2.1
6308     */
6309    public static <T> T[] removeElement(final T[] array, final Object element) {
6310        final int index = indexOf(array, element);
6311        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6312    }
6313
6314    /**
6315     * Removes occurrences of specified elements, in specified quantities,
6316     * from the specified array. All subsequent elements are shifted left.
6317     * For any element-to-be-removed specified in greater quantities than
6318     * contained in the original array, no change occurs beyond the
6319     * removal of the existing matching items.
6320     * <p>
6321     * This method returns a new array with the same elements of the input
6322     * array except for the earliest-encountered occurrences of the specified
6323     * elements. The component type of the returned array is always the same
6324     * as that of the input array.
6325     * </p>
6326     * <pre>
6327     * ArrayUtils.removeElements(null, true, false)               = null
6328     * ArrayUtils.removeElements([], true, false)                 = []
6329     * ArrayUtils.removeElements([true], false, false)            = [true]
6330     * ArrayUtils.removeElements([true, false], true, true)       = [false]
6331     * ArrayUtils.removeElements([true, false, true], true)       = [false, true]
6332     * ArrayUtils.removeElements([true, false, true], true, true) = [false]
6333     * </pre>
6334     *
6335     * @param array The input array, will not be modified, and may be {@code null}.
6336     * @param values  The values to be removed.
6337     * @return A new array containing the existing elements except the
6338     *         earliest-encountered occurrences of the specified elements.
6339     * @since 3.0.1
6340     */
6341    public static boolean[] removeElements(final boolean[] array, final boolean... values) {
6342        if (isEmpty(array) || isEmpty(values)) {
6343            return clone(array);
6344        }
6345        final HashMap<Boolean, MutableInt> occurrences = new HashMap<>(2); // only two possible values here
6346        for (final boolean v : values) {
6347            increment(occurrences, Boolean.valueOf(v));
6348        }
6349        final BitSet toRemove = new BitSet();
6350        for (int i = 0; i < array.length; i++) {
6351            final boolean key = array[i];
6352            final MutableInt count = occurrences.get(key);
6353            if (count != null) {
6354                if (count.decrementAndGet() == 0) {
6355                    occurrences.remove(key);
6356                }
6357                toRemove.set(i);
6358            }
6359        }
6360        return (boolean[]) removeAt(array, toRemove);
6361    }
6362
6363    /**
6364     * Removes occurrences of specified elements, in specified quantities,
6365     * from the specified array. All subsequent elements are shifted left.
6366     * For any element-to-be-removed specified in greater quantities than
6367     * contained in the original array, no change occurs beyond the
6368     * removal of the existing matching items.
6369     * <p>
6370     * This method returns a new array with the same elements of the input
6371     * array except for the earliest-encountered occurrences of the specified
6372     * elements. The component type of the returned array is always the same
6373     * as that of the input array.
6374     * </p>
6375     * <pre>
6376     * ArrayUtils.removeElements(null, 1, 2)      = null
6377     * ArrayUtils.removeElements([], 1, 2)        = []
6378     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6379     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6380     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6381     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6382     * </pre>
6383     *
6384     * @param array The input array, will not be modified, and may be {@code null}.
6385     * @param values  The values to be removed.
6386     * @return A new array containing the existing elements except the
6387     *         earliest-encountered occurrences of the specified elements.
6388     * @since 3.0.1
6389     */
6390    public static byte[] removeElements(final byte[] array, final byte... values) {
6391        if (isEmpty(array) || isEmpty(values)) {
6392            return clone(array);
6393        }
6394        final HashMap<Byte, MutableInt> occurrences = new HashMap<>(values.length);
6395        for (final byte v : values) {
6396            increment(occurrences, Byte.valueOf(v));
6397        }
6398        final BitSet toRemove = new BitSet();
6399        for (int i = 0; i < array.length; i++) {
6400            final byte key = array[i];
6401            final MutableInt count = occurrences.get(key);
6402            if (count != null) {
6403                if (count.decrementAndGet() == 0) {
6404                    occurrences.remove(key);
6405                }
6406                toRemove.set(i);
6407            }
6408        }
6409        return (byte[]) removeAt(array, toRemove);
6410    }
6411
6412    /**
6413     * Removes occurrences of specified elements, in specified quantities,
6414     * from the specified array. All subsequent elements are shifted left.
6415     * For any element-to-be-removed specified in greater quantities than
6416     * contained in the original array, no change occurs beyond the
6417     * removal of the existing matching items.
6418     * <p>
6419     * This method returns a new array with the same elements of the input
6420     * array except for the earliest-encountered occurrences of the specified
6421     * elements. The component type of the returned array is always the same
6422     * as that of the input array.
6423     * </p>
6424     * <pre>
6425     * ArrayUtils.removeElements(null, 1, 2)      = null
6426     * ArrayUtils.removeElements([], 1, 2)        = []
6427     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6428     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6429     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6430     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6431     * </pre>
6432     *
6433     * @param array The input array, will not be modified, and may be {@code null}.
6434     * @param values  The values to be removed.
6435     * @return A new array containing the existing elements except the
6436     *         earliest-encountered occurrences of the specified elements.
6437     * @since 3.0.1
6438     */
6439    public static char[] removeElements(final char[] array, final char... values) {
6440        if (isEmpty(array) || isEmpty(values)) {
6441            return clone(array);
6442        }
6443        final HashMap<Character, MutableInt> occurrences = new HashMap<>(values.length);
6444        for (final char v : values) {
6445            increment(occurrences, Character.valueOf(v));
6446        }
6447        final BitSet toRemove = new BitSet();
6448        for (int i = 0; i < array.length; i++) {
6449            final char key = array[i];
6450            final MutableInt count = occurrences.get(key);
6451            if (count != null) {
6452                if (count.decrementAndGet() == 0) {
6453                    occurrences.remove(key);
6454                }
6455                toRemove.set(i);
6456            }
6457        }
6458        return (char[]) removeAt(array, toRemove);
6459    }
6460
6461    /**
6462     * Removes occurrences of specified elements, in specified quantities,
6463     * from the specified array. All subsequent elements are shifted left.
6464     * For any element-to-be-removed specified in greater quantities than
6465     * contained in the original array, no change occurs beyond the
6466     * removal of the existing matching items.
6467     * <p>
6468     * This method returns a new array with the same elements of the input
6469     * array except for the earliest-encountered occurrences of the specified
6470     * elements. The component type of the returned array is always the same
6471     * as that of the input array.
6472     * </p>
6473     * <pre>
6474     * ArrayUtils.removeElements(null, 1, 2)      = null
6475     * ArrayUtils.removeElements([], 1, 2)        = []
6476     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6477     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6478     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6479     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6480     * </pre>
6481     *
6482     * @param array The input array, will not be modified, and may be {@code null}.
6483     * @param values  The values to be removed.
6484     * @return A new array containing the existing elements except the
6485     *         earliest-encountered occurrences of the specified elements.
6486     * @since 3.0.1
6487     */
6488    public static double[] removeElements(final double[] array, final double... values) {
6489        if (isEmpty(array) || isEmpty(values)) {
6490            return clone(array);
6491        }
6492        final HashMap<Double, MutableInt> occurrences = new HashMap<>(values.length);
6493        for (final double v : values) {
6494            increment(occurrences, Double.valueOf(v));
6495        }
6496        final BitSet toRemove = new BitSet();
6497        for (int i = 0; i < array.length; i++) {
6498            final double key = array[i];
6499            final MutableInt count = occurrences.get(key);
6500            if (count != null) {
6501                if (count.decrementAndGet() == 0) {
6502                    occurrences.remove(key);
6503                }
6504                toRemove.set(i);
6505            }
6506        }
6507        return (double[]) removeAt(array, toRemove);
6508    }
6509
6510    /**
6511     * Removes occurrences of specified elements, in specified quantities,
6512     * from the specified array. All subsequent elements are shifted left.
6513     * For any element-to-be-removed specified in greater quantities than
6514     * contained in the original array, no change occurs beyond the
6515     * removal of the existing matching items.
6516     * <p>
6517     * This method returns a new array with the same elements of the input
6518     * array except for the earliest-encountered occurrences of the specified
6519     * elements. The component type of the returned array is always the same
6520     * as that of the input array.
6521     * </p>
6522     * <pre>
6523     * ArrayUtils.removeElements(null, 1, 2)      = null
6524     * ArrayUtils.removeElements([], 1, 2)        = []
6525     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6526     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6527     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6528     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6529     * </pre>
6530     *
6531     * @param array The input array, will not be modified, and may be {@code null}.
6532     * @param values  The values to be removed.
6533     * @return A new array containing the existing elements except the
6534     *         earliest-encountered occurrences of the specified elements.
6535     * @since 3.0.1
6536     */
6537    public static float[] removeElements(final float[] array, final float... values) {
6538        if (isEmpty(array) || isEmpty(values)) {
6539            return clone(array);
6540        }
6541        final HashMap<Float, MutableInt> occurrences = new HashMap<>(values.length);
6542        for (final float v : values) {
6543            increment(occurrences, Float.valueOf(v));
6544        }
6545        final BitSet toRemove = new BitSet();
6546        for (int i = 0; i < array.length; i++) {
6547            final float key = array[i];
6548            final MutableInt count = occurrences.get(key);
6549            if (count != null) {
6550                if (count.decrementAndGet() == 0) {
6551                    occurrences.remove(key);
6552                }
6553                toRemove.set(i);
6554            }
6555        }
6556        return (float[]) removeAt(array, toRemove);
6557    }
6558
6559    /**
6560     * Removes occurrences of specified elements, in specified quantities,
6561     * from the specified array. All subsequent elements are shifted left.
6562     * For any element-to-be-removed specified in greater quantities than
6563     * contained in the original array, no change occurs beyond the
6564     * removal of the existing matching items.
6565     * <p>
6566     * This method returns a new array with the same elements of the input
6567     * array except for the earliest-encountered occurrences of the specified
6568     * elements. The component type of the returned array is always the same
6569     * as that of the input array.
6570     * </p>
6571     * <pre>
6572     * ArrayUtils.removeElements(null, 1, 2)      = null
6573     * ArrayUtils.removeElements([], 1, 2)        = []
6574     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6575     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6576     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6577     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6578     * </pre>
6579     *
6580     * @param array The input array, will not be modified, and may be {@code null}.
6581     * @param values  The values to be removed.
6582     * @return A new array containing the existing elements except the
6583     *         earliest-encountered occurrences of the specified elements.
6584     * @since 3.0.1
6585     */
6586    public static int[] removeElements(final int[] array, final int... values) {
6587        if (isEmpty(array) || isEmpty(values)) {
6588            return clone(array);
6589        }
6590        final HashMap<Integer, MutableInt> occurrences = new HashMap<>(values.length);
6591        for (final int v : values) {
6592            increment(occurrences, Integer.valueOf(v));
6593        }
6594        final BitSet toRemove = new BitSet();
6595        for (int i = 0; i < array.length; i++) {
6596            final int key = array[i];
6597            final MutableInt count = occurrences.get(key);
6598            if (count != null) {
6599                if (count.decrementAndGet() == 0) {
6600                    occurrences.remove(key);
6601                }
6602                toRemove.set(i);
6603            }
6604        }
6605        return (int[]) removeAt(array, toRemove);
6606    }
6607
6608    /**
6609     * Removes occurrences of specified elements, in specified quantities,
6610     * from the specified array. All subsequent elements are shifted left.
6611     * For any element-to-be-removed specified in greater quantities than
6612     * contained in the original array, no change occurs beyond the
6613     * removal of the existing matching items.
6614     * <p>
6615     * This method returns a new array with the same elements of the input
6616     * array except for the earliest-encountered occurrences of the specified
6617     * elements. The component type of the returned array is always the same
6618     * as that of the input array.
6619     * </p>
6620     * <pre>
6621     * ArrayUtils.removeElements(null, 1, 2)      = null
6622     * ArrayUtils.removeElements([], 1, 2)        = []
6623     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6624     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6625     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6626     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6627     * </pre>
6628     *
6629     * @param array The input array, will not be modified, and may be {@code null}.
6630     * @param values  The values to be removed.
6631     * @return A new array containing the existing elements except the
6632     *         earliest-encountered occurrences of the specified elements.
6633     * @since 3.0.1
6634     */
6635    public static long[] removeElements(final long[] array, final long... values) {
6636        if (isEmpty(array) || isEmpty(values)) {
6637            return clone(array);
6638        }
6639        final HashMap<Long, MutableInt> occurrences = new HashMap<>(values.length);
6640        for (final long v : values) {
6641            increment(occurrences, Long.valueOf(v));
6642        }
6643        final BitSet toRemove = new BitSet();
6644        for (int i = 0; i < array.length; i++) {
6645            final long key = array[i];
6646            final MutableInt count = occurrences.get(key);
6647            if (count != null) {
6648                if (count.decrementAndGet() == 0) {
6649                    occurrences.remove(key);
6650                }
6651                toRemove.set(i);
6652            }
6653        }
6654        return (long[]) removeAt(array, toRemove);
6655    }
6656
6657    /**
6658     * Removes occurrences of specified elements, in specified quantities,
6659     * from the specified array. All subsequent elements are shifted left.
6660     * For any element-to-be-removed specified in greater quantities than
6661     * contained in the original array, no change occurs beyond the
6662     * removal of the existing matching items.
6663     * <p>
6664     * This method returns a new array with the same elements of the input
6665     * array except for the earliest-encountered occurrences of the specified
6666     * elements. The component type of the returned array is always the same
6667     * as that of the input array.
6668     * </p>
6669     * <pre>
6670     * ArrayUtils.removeElements(null, 1, 2)      = null
6671     * ArrayUtils.removeElements([], 1, 2)        = []
6672     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6673     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6674     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6675     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6676     * </pre>
6677     *
6678     * @param array The input array, will not be modified, and may be {@code null}.
6679     * @param values  The values to be removed.
6680     * @return A new array containing the existing elements except the
6681     *         earliest-encountered occurrences of the specified elements.
6682     * @since 3.0.1
6683     */
6684    public static short[] removeElements(final short[] array, final short... values) {
6685        if (isEmpty(array) || isEmpty(values)) {
6686            return clone(array);
6687        }
6688        final HashMap<Short, MutableInt> occurrences = new HashMap<>(values.length);
6689        for (final short v : values) {
6690            increment(occurrences, Short.valueOf(v));
6691        }
6692        final BitSet toRemove = new BitSet();
6693        for (int i = 0; i < array.length; i++) {
6694            final short key = array[i];
6695            final MutableInt count = occurrences.get(key);
6696            if (count != null) {
6697                if (count.decrementAndGet() == 0) {
6698                    occurrences.remove(key);
6699                }
6700                toRemove.set(i);
6701            }
6702        }
6703        return (short[]) removeAt(array, toRemove);
6704    }
6705
6706    /**
6707     * Removes occurrences of specified elements, in specified quantities,
6708     * from the specified array. All subsequent elements are shifted left.
6709     * For any element-to-be-removed specified in greater quantities than
6710     * contained in the original array, no change occurs beyond the
6711     * removal of the existing matching items.
6712     * <p>
6713     * This method returns a new array with the same elements of the input
6714     * array except for the earliest-encountered occurrences of the specified
6715     * elements. The component type of the returned array is always the same
6716     * as that of the input array.
6717     * </p>
6718     * <pre>
6719     * ArrayUtils.removeElements(null, "a", "b")            = null
6720     * ArrayUtils.removeElements([], "a", "b")              = []
6721     * ArrayUtils.removeElements(["a"], "b", "c")           = ["a"]
6722     * ArrayUtils.removeElements(["a", "b"], "a", "c")      = ["b"]
6723     * ArrayUtils.removeElements(["a", "b", "a"], "a")      = ["b", "a"]
6724     * ArrayUtils.removeElements(["a", "b", "a"], "a", "a") = ["b"]
6725     * </pre>
6726     *
6727     * @param <T> The component type of the array
6728     * @param array The input array, will not be modified, and may be {@code null}.
6729     * @param values  The values to be removed.
6730     * @return A new array containing the existing elements except the
6731     *         earliest-encountered occurrences of the specified elements.
6732     * @since 3.0.1
6733     */
6734    @SafeVarargs
6735    public static <T> T[] removeElements(final T[] array, final T... values) {
6736        if (isEmpty(array) || isEmpty(values)) {
6737            return clone(array);
6738        }
6739        final HashMap<T, MutableInt> occurrences = new HashMap<>(values.length);
6740        for (final T v : values) {
6741            increment(occurrences, v);
6742        }
6743        final BitSet toRemove = new BitSet();
6744        for (int i = 0; i < array.length; i++) {
6745            final T key = array[i];
6746            final MutableInt count = occurrences.get(key);
6747            if (count != null) {
6748                if (count.decrementAndGet() == 0) {
6749                    occurrences.remove(key);
6750                }
6751                toRemove.set(i);
6752            }
6753        }
6754        @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
6755        final T[] result = (T[]) removeAt(array, toRemove);
6756        return result;
6757    }
6758
6759    /**
6760     * Reverses the order of the given array.
6761     * <p>
6762     * This method does nothing for a {@code null} input array.
6763     * </p>
6764     *
6765     * @param array  The array to reverse, may be {@code null}.
6766     */
6767    public static void reverse(final boolean[] array) {
6768        if (array != null) {
6769            reverse(array, 0, array.length);
6770        }
6771    }
6772
6773    /**
6774     * Reverses the order of the given array in the given range.
6775     * <p>
6776     * This method does nothing for a {@code null} input array.
6777     * </p>
6778     *
6779     * @param array
6780     *            the array to reverse, may be {@code null}.
6781     * @param startIndexInclusive
6782     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6783     *            change.
6784     * @param endIndexExclusive
6785     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6786     *            change. Overvalue (&gt;array.length) is demoted to array length.
6787     * @since 3.2
6788     */
6789    public static void reverse(final boolean[] array, final int startIndexInclusive, final int endIndexExclusive) {
6790        if (array == null) {
6791            return;
6792        }
6793        int i = Math.max(startIndexInclusive, 0);
6794        int j = max0(Math.min(array.length, endIndexExclusive)) - 1;
6795        boolean tmp;
6796        while (j > i) {
6797            tmp = array[j];
6798            array[j] = array[i];
6799            array[i] = tmp;
6800            j--;
6801            i++;
6802        }
6803    }
6804
6805    /**
6806     * Reverses the order of the given array.
6807     * <p>
6808     * This method does nothing for a {@code null} input array.
6809     * </p>
6810     *
6811     * @param array  The array to reverse, may be {@code null}.
6812     */
6813    public static void reverse(final byte[] array) {
6814        if (array != null) {
6815            reverse(array, 0, array.length);
6816        }
6817    }
6818
6819    /**
6820     * Reverses the order of the given array in the given range.
6821     * <p>
6822     * This method does nothing for a {@code null} input array.
6823     * </p>
6824     *
6825     * @param array               The array to reverse, may be {@code null}.
6826     * @param startIndexInclusive The starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no change.
6827     * @param endIndexExclusive   elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no change. Overvalue
6828     *                            (&gt;array.length) is demoted to array length.
6829     * @since 3.2
6830     */
6831    public static void reverse(final byte[] array, final int startIndexInclusive, final int endIndexExclusive) {
6832        if (array == null) {
6833            return;
6834        }
6835        int i = Math.max(startIndexInclusive, 0);
6836        int j = max0(Math.min(array.length, endIndexExclusive)) - 1;
6837        byte tmp;
6838        while (j > i) {
6839            tmp = array[j];
6840            array[j] = array[i];
6841            array[i] = tmp;
6842            j--;
6843            i++;
6844        }
6845    }
6846
6847    /**
6848     * Reverses the order of the given array.
6849     * <p>
6850     * This method does nothing for a {@code null} input array.
6851     * </p>
6852     *
6853     * @param array  The array to reverse, may be {@code null}.
6854     */
6855    public static void reverse(final char[] array) {
6856        if (array != null) {
6857            reverse(array, 0, array.length);
6858        }
6859    }
6860
6861    /**
6862     * Reverses the order of the given array in the given range.
6863     * <p>
6864     * This method does nothing for a {@code null} input array.
6865     * </p>
6866     *
6867     * @param array               The array to reverse, may be {@code null}.
6868     * @param startIndexInclusive The starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no change.
6869     * @param endIndexExclusive   elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no change. Overvalue
6870     *                            (&gt;array.length) is demoted to array length.
6871     * @since 3.2
6872     */
6873    public static void reverse(final char[] array, final int startIndexInclusive, final int endIndexExclusive) {
6874        if (array == null) {
6875            return;
6876        }
6877        int i = Math.max(startIndexInclusive, 0);
6878        int j = max0(Math.min(array.length, endIndexExclusive)) - 1;
6879        char tmp;
6880        while (j > i) {
6881            tmp = array[j];
6882            array[j] = array[i];
6883            array[i] = tmp;
6884            j--;
6885            i++;
6886        }
6887    }
6888
6889    /**
6890     * Reverses the order of the given array.
6891     * <p>
6892     * This method does nothing for a {@code null} input array.
6893     * </p>
6894     *
6895     * @param array  The array to reverse, may be {@code null}
6896     */
6897    public static void reverse(final double[] array) {
6898        if (array != null) {
6899            reverse(array, 0, array.length);
6900        }
6901    }
6902
6903    /**
6904     * Reverses the order of the given array in the given range.
6905     * <p>
6906     * This method does nothing for a {@code null} input array.
6907     * </p>
6908     *
6909     * @param array               The array to reverse, may be {@code null}.
6910     * @param startIndexInclusive The starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no change.
6911     * @param endIndexExclusive   elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no change. Overvalue
6912     *                            (&gt;array.length) is demoted to array length.
6913     * @since 3.2
6914     */
6915    public static void reverse(final double[] array, final int startIndexInclusive, final int endIndexExclusive) {
6916        if (array == null) {
6917            return;
6918        }
6919        int i = Math.max(startIndexInclusive, 0);
6920        int j = max0(Math.min(array.length, endIndexExclusive)) - 1;
6921        double tmp;
6922        while (j > i) {
6923            tmp = array[j];
6924            array[j] = array[i];
6925            array[i] = tmp;
6926            j--;
6927            i++;
6928        }
6929    }
6930
6931    /**
6932     * Reverses the order of the given array.
6933     * <p>
6934     * This method does nothing for a {@code null} input array.
6935     * </p>
6936     *
6937     * @param array  The array to reverse, may be {@code null}.
6938     */
6939    public static void reverse(final float[] array) {
6940        if (array != null) {
6941            reverse(array, 0, array.length);
6942        }
6943    }
6944
6945    /**
6946     * Reverses the order of the given array in the given range.
6947     * <p>
6948     * This method does nothing for a {@code null} input array.
6949     * </p>
6950     *
6951     * @param array               The array to reverse, may be {@code null}.
6952     * @param startIndexInclusive The starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no change.
6953     * @param endIndexExclusive   elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no change. Overvalue
6954     *                            (&gt;array.length) is demoted to array length.
6955     * @since 3.2
6956     */
6957    public static void reverse(final float[] array, final int startIndexInclusive, final int endIndexExclusive) {
6958        if (array == null) {
6959            return;
6960        }
6961        int i = Math.max(startIndexInclusive, 0);
6962        int j = max0(Math.min(array.length, endIndexExclusive)) - 1;
6963        float tmp;
6964        while (j > i) {
6965            tmp = array[j];
6966            array[j] = array[i];
6967            array[i] = tmp;
6968            j--;
6969            i++;
6970        }
6971    }
6972
6973    /**
6974     * Reverses the order of the given array.
6975     * <p>
6976     * This method does nothing for a {@code null} input array.
6977     * </p>
6978     *
6979     * @param array  The array to reverse, may be {@code null}.
6980     */
6981    public static void reverse(final int[] array) {
6982        if (array != null) {
6983            reverse(array, 0, array.length);
6984        }
6985    }
6986
6987    /**
6988     * Reverses the order of the given array in the given range.
6989     * <p>
6990     * This method does nothing for a {@code null} input array.
6991     * </p>
6992     *
6993     * @param array
6994     *            the array to reverse, may be {@code null}.
6995     * @param startIndexInclusive
6996     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6997     *            change.
6998     * @param endIndexExclusive
6999     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
7000     *            change. Overvalue (&gt;array.length) is demoted to array length.
7001     * @since 3.2
7002     */
7003    public static void reverse(final int[] array, final int startIndexInclusive, final int endIndexExclusive) {
7004        if (array == null) {
7005            return;
7006        }
7007        int i = Math.max(startIndexInclusive, 0);
7008        int j = max0(Math.min(array.length, endIndexExclusive)) - 1;
7009        int tmp;
7010        while (j > i) {
7011            tmp = array[j];
7012            array[j] = array[i];
7013            array[i] = tmp;
7014            j--;
7015            i++;
7016        }
7017    }
7018
7019    /**
7020     * Reverses the order of the given array.
7021     * <p>
7022     * This method does nothing for a {@code null} input array.
7023     * </p>
7024     *
7025     * @param array  The array to reverse, may be {@code null}.
7026     */
7027    public static void reverse(final long[] array) {
7028        if (array != null) {
7029            reverse(array, 0, array.length);
7030        }
7031    }
7032
7033    /**
7034     * Reverses the order of the given array in the given range.
7035     * <p>
7036     * This method does nothing for a {@code null} input array.
7037     * </p>
7038     *
7039     * @param array
7040     *            the array to reverse, may be {@code null}.
7041     * @param startIndexInclusive
7042     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7043     *            change.
7044     * @param endIndexExclusive
7045     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
7046     *            change. Overvalue (&gt;array.length) is demoted to array length.
7047     * @since 3.2
7048     */
7049    public static void reverse(final long[] array, final int startIndexInclusive, final int endIndexExclusive) {
7050        if (array == null) {
7051            return;
7052        }
7053        int i = Math.max(startIndexInclusive, 0);
7054        int j = max0(Math.min(array.length, endIndexExclusive)) - 1;
7055        long tmp;
7056        while (j > i) {
7057            tmp = array[j];
7058            array[j] = array[i];
7059            array[i] = tmp;
7060            j--;
7061            i++;
7062        }
7063    }
7064
7065    /**
7066     * Reverses the order of the given array.
7067     * <p>
7068     * There is no special handling for multi-dimensional arrays.
7069     * </p>
7070     * <p>
7071     * This method does nothing for a {@code null} input array.
7072     * </p>
7073     *
7074     * @param array  The array to reverse, may be {@code null}.
7075     */
7076    public static void reverse(final Object[] array) {
7077        if (array != null) {
7078            reverse(array, 0, array.length);
7079        }
7080    }
7081
7082    /**
7083     * Reverses the order of the given array in the given range.
7084     * <p>
7085     * This method does nothing for a {@code null} input array.
7086     * </p>
7087     *
7088     * @param array
7089     *            the array to reverse, may be {@code null}.
7090     * @param startIndexInclusive
7091     *            the starting index. Under value (&lt;0) is promoted to 0, over value (&gt;array.length) results in no
7092     *            change.
7093     * @param endIndexExclusive
7094     *            elements up to endIndex-1 are reversed in the array. Under value (&lt; start index) results in no
7095     *            change. Over value (&gt;array.length) is demoted to array length.
7096     * @since 3.2
7097     */
7098    public static void reverse(final Object[] array, final int startIndexInclusive, final int endIndexExclusive) {
7099        if (array == null) {
7100            return;
7101        }
7102        int i = Math.max(startIndexInclusive, 0);
7103        int j = max0(Math.min(array.length, endIndexExclusive)) - 1;
7104        Object tmp;
7105        while (j > i) {
7106            tmp = array[j];
7107            array[j] = array[i];
7108            array[i] = tmp;
7109            j--;
7110            i++;
7111        }
7112    }
7113
7114    /**
7115     * Reverses the order of the given array.
7116     * <p>
7117     * This method does nothing for a {@code null} input array.
7118     * </p>
7119     *
7120     * @param array  The array to reverse, may be {@code null}.
7121     */
7122    public static void reverse(final short[] array) {
7123        if (array != null) {
7124            reverse(array, 0, array.length);
7125        }
7126    }
7127
7128    /**
7129     * Reverses the order of the given array in the given range.
7130     * <p>
7131     * This method does nothing for a {@code null} input array.
7132     * </p>
7133     *
7134     * @param array
7135     *            the array to reverse, may be {@code null}.
7136     * @param startIndexInclusive
7137     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7138     *            change.
7139     * @param endIndexExclusive
7140     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
7141     *            change. Overvalue (&gt;array.length) is demoted to array length.
7142     * @since 3.2
7143     */
7144    public static void reverse(final short[] array, final int startIndexInclusive, final int endIndexExclusive) {
7145        if (array == null) {
7146            return;
7147        }
7148        int i = Math.max(startIndexInclusive, 0);
7149        int j = max0(Math.min(array.length, endIndexExclusive)) - 1;
7150        short tmp;
7151        while (j > i) {
7152            tmp = array[j];
7153            array[j] = array[i];
7154            array[i] = tmp;
7155            j--;
7156            i++;
7157        }
7158    }
7159
7160    /**
7161     * Sets all elements of the specified array, using the provided generator supplier to compute each element.
7162     * <p>
7163     * If the generator supplier throws an exception, it is relayed to the caller and the array is left in an indeterminate
7164     * state.
7165     * </p>
7166     *
7167     * @param <T> type of elements of the array, may be {@code null}.
7168     * @param array array to be initialized, may be {@code null}.
7169     * @param generator A function accepting an index and producing the desired value for that position.
7170     * @return The input array
7171     * @since 3.13.0
7172     */
7173    public static <T> T[] setAll(final T[] array, final IntFunction<? extends T> generator) {
7174        if (array != null && generator != null) {
7175            Arrays.setAll(array, generator);
7176        }
7177        return array;
7178    }
7179
7180    /**
7181     * Sets all elements of the specified array, using the provided generator supplier to compute each element.
7182     * <p>
7183     * If the generator supplier throws an exception, it is relayed to the caller and the array is left in an indeterminate
7184     * state.
7185     * </p>
7186     *
7187     * @param <T> type of elements of the array, may be {@code null}.
7188     * @param array array to be initialized, may be {@code null}.
7189     * @param generator A function accepting an index and producing the desired value for that position.
7190     * @return The input array
7191     * @since 3.13.0
7192     */
7193    public static <T> T[] setAll(final T[] array, final Supplier<? extends T> generator) {
7194        if (array != null && generator != null) {
7195            for (int i = 0; i < array.length; i++) {
7196                array[i] = generator.get();
7197            }
7198        }
7199        return array;
7200    }
7201
7202    /**
7203     * Shifts the order of the given boolean array.
7204     *
7205     * <p>
7206     * There is no special handling for multi-dimensional arrays. This method
7207     * does nothing for {@code null} or empty input arrays.
7208     * </p>
7209     *
7210     * @param array  The array to shift, may be {@code null}.
7211     * @param offset
7212     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7213     *          rotate, than the effective offset is modulo the number of elements to rotate.
7214     * @since 3.5
7215     */
7216    public static void shift(final boolean[] array, final int offset) {
7217        if (array != null) {
7218            shift(array, 0, array.length, offset);
7219        }
7220    }
7221
7222    /**
7223     * Shifts the order of a series of elements in the given boolean array.
7224     *
7225     * <p>
7226     * There is no special handling for multi-dimensional arrays. This method
7227     * does nothing for {@code null} or empty input arrays.
7228     * </p>
7229     *
7230     * @param array
7231     *            the array to shift, may be {@code null}.
7232     * @param startIndexInclusive
7233     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7234     *            change.
7235     * @param endIndexExclusive
7236     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7237     *            change. Overvalue (&gt;array.length) is demoted to array length.
7238     * @param offset
7239     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7240     *          rotate, than the effective offset is modulo the number of elements to rotate.
7241     * @since 3.5
7242     */
7243    public static void shift(final boolean[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7244        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7245            return;
7246        }
7247        startIndexInclusive = max0(startIndexInclusive);
7248        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7249        int n = endIndexExclusive - startIndexInclusive;
7250        if (n <= 1) {
7251            return;
7252        }
7253        offset %= n;
7254        if (offset < 0) {
7255            offset += n;
7256        }
7257        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7258        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7259        while (n > 1 && offset > 0) {
7260            final int nOffset = n - offset;
7261            if (offset > nOffset) {
7262                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7263                n = offset;
7264                offset -= nOffset;
7265            } else if (offset < nOffset) {
7266                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7267                startIndexInclusive += offset;
7268                n = nOffset;
7269            } else {
7270                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7271                break;
7272            }
7273        }
7274    }
7275
7276    /**
7277     * Shifts the order of the given byte array.
7278     *
7279     * <p>
7280     * There is no special handling for multi-dimensional arrays. This method
7281     * does nothing for {@code null} or empty input arrays.
7282     * </p>
7283     *
7284     * @param array  The array to shift, may be {@code null}.
7285     * @param offset
7286     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7287     *          rotate, than the effective offset is modulo the number of elements to rotate.
7288     * @since 3.5
7289     */
7290    public static void shift(final byte[] array, final int offset) {
7291        if (array != null) {
7292            shift(array, 0, array.length, offset);
7293        }
7294    }
7295
7296    /**
7297     * Shifts the order of a series of elements in the given byte array.
7298     *
7299     * <p>
7300     * There is no special handling for multi-dimensional arrays. This method
7301     * does nothing for {@code null} or empty input arrays.
7302     * </p>
7303     *
7304     * @param array
7305     *            the array to shift, may be {@code null}.
7306     * @param startIndexInclusive
7307     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7308     *            change.
7309     * @param endIndexExclusive
7310     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7311     *            change. Overvalue (&gt;array.length) is demoted to array length.
7312     * @param offset
7313     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7314     *          rotate, than the effective offset is modulo the number of elements to rotate.
7315     * @since 3.5
7316     */
7317    public static void shift(final byte[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7318        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7319            return;
7320        }
7321        startIndexInclusive = max0(startIndexInclusive);
7322        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7323        int n = endIndexExclusive - startIndexInclusive;
7324        if (n <= 1) {
7325            return;
7326        }
7327        offset %= n;
7328        if (offset < 0) {
7329            offset += n;
7330        }
7331        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7332        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7333        while (n > 1 && offset > 0) {
7334            final int nOffset = n - offset;
7335            if (offset > nOffset) {
7336                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7337                n = offset;
7338                offset -= nOffset;
7339            } else if (offset < nOffset) {
7340                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7341                startIndexInclusive += offset;
7342                n = nOffset;
7343            } else {
7344                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7345                break;
7346            }
7347        }
7348    }
7349
7350    /**
7351     * Shifts the order of the given char array.
7352     *
7353     * <p>
7354     * There is no special handling for multi-dimensional arrays. This method
7355     * does nothing for {@code null} or empty input arrays.
7356     * </p>
7357     *
7358     * @param array  The array to shift, may be {@code null}.
7359     * @param offset
7360     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7361     *          rotate, than the effective offset is modulo the number of elements to rotate.
7362     * @since 3.5
7363     */
7364    public static void shift(final char[] array, final int offset) {
7365        if (array != null) {
7366            shift(array, 0, array.length, offset);
7367        }
7368    }
7369
7370    /**
7371     * Shifts the order of a series of elements in the given char array.
7372     *
7373     * <p>
7374     * There is no special handling for multi-dimensional arrays. This method
7375     * does nothing for {@code null} or empty input arrays.
7376     * </p>
7377     *
7378     * @param array
7379     *            the array to shift, may be {@code null}.
7380     * @param startIndexInclusive
7381     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7382     *            change.
7383     * @param endIndexExclusive
7384     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7385     *            change. Overvalue (&gt;array.length) is demoted to array length.
7386     * @param offset
7387     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7388     *          rotate, than the effective offset is modulo the number of elements to rotate.
7389     * @since 3.5
7390     */
7391    public static void shift(final char[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7392        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7393            return;
7394        }
7395        startIndexInclusive = max0(startIndexInclusive);
7396        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7397        int n = endIndexExclusive - startIndexInclusive;
7398        if (n <= 1) {
7399            return;
7400        }
7401        offset %= n;
7402        if (offset < 0) {
7403            offset += n;
7404        }
7405        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7406        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7407        while (n > 1 && offset > 0) {
7408            final int nOffset = n - offset;
7409            if (offset > nOffset) {
7410                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7411                n = offset;
7412                offset -= nOffset;
7413            } else if (offset < nOffset) {
7414                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7415                startIndexInclusive += offset;
7416                n = nOffset;
7417            } else {
7418                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7419                break;
7420            }
7421        }
7422    }
7423
7424    /**
7425     * Shifts the order of the given double array.
7426     *
7427     * <p>
7428     * There is no special handling for multi-dimensional arrays. This method
7429     * does nothing for {@code null} or empty input arrays.
7430     * </p>
7431     *
7432     * @param array  The array to shift, may be {@code null}.
7433     * @param offset
7434     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7435     *          rotate, than the effective offset is modulo the number of elements to rotate.
7436     * @since 3.5
7437     */
7438    public static void shift(final double[] array, final int offset) {
7439        if (array != null) {
7440            shift(array, 0, array.length, offset);
7441        }
7442    }
7443
7444    /**
7445     * Shifts the order of a series of elements in the given double array.
7446     *
7447     * <p>
7448     * There is no special handling for multi-dimensional arrays. This method
7449     * does nothing for {@code null} or empty input arrays.
7450     * </p>
7451     *
7452     * @param array
7453     *            the array to shift, may be {@code null}.
7454     * @param startIndexInclusive
7455     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7456     *            change.
7457     * @param endIndexExclusive
7458     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7459     *            change. Overvalue (&gt;array.length) is demoted to array length.
7460     * @param offset
7461     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7462     *          rotate, than the effective offset is modulo the number of elements to rotate.
7463     * @since 3.5
7464     */
7465    public static void shift(final double[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7466        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7467            return;
7468        }
7469        startIndexInclusive = max0(startIndexInclusive);
7470        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7471        int n = endIndexExclusive - startIndexInclusive;
7472        if (n <= 1) {
7473            return;
7474        }
7475        offset %= n;
7476        if (offset < 0) {
7477            offset += n;
7478        }
7479        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7480        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7481        while (n > 1 && offset > 0) {
7482            final int nOffset = n - offset;
7483            if (offset > nOffset) {
7484                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7485                n = offset;
7486                offset -= nOffset;
7487            } else if (offset < nOffset) {
7488                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7489                startIndexInclusive += offset;
7490                n = nOffset;
7491            } else {
7492                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7493                break;
7494            }
7495        }
7496    }
7497
7498    /**
7499     * Shifts the order of the given float array.
7500     *
7501     * <p>
7502     * There is no special handling for multi-dimensional arrays. This method
7503     * does nothing for {@code null} or empty input arrays.
7504     * </p>
7505     *
7506     * @param array  The array to shift, may be {@code null}.
7507     * @param offset
7508     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7509     *          rotate, than the effective offset is modulo the number of elements to rotate.
7510     * @since 3.5
7511     */
7512    public static void shift(final float[] array, final int offset) {
7513        if (array != null) {
7514            shift(array, 0, array.length, offset);
7515        }
7516    }
7517
7518    /**
7519     * Shifts the order of a series of elements in the given float array.
7520     *
7521     * <p>
7522     * There is no special handling for multi-dimensional arrays. This method
7523     * does nothing for {@code null} or empty input arrays.
7524     * </p>
7525     *
7526     * @param array
7527     *            the array to shift, may be {@code null}.
7528     * @param startIndexInclusive
7529     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7530     *            change.
7531     * @param endIndexExclusive
7532     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7533     *            change. Overvalue (&gt;array.length) is demoted to array length.
7534     * @param offset
7535     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7536     *          rotate, than the effective offset is modulo the number of elements to rotate.
7537     * @since 3.5
7538     */
7539    public static void shift(final float[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7540        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7541            return;
7542        }
7543        startIndexInclusive = max0(startIndexInclusive);
7544        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7545        int n = endIndexExclusive - startIndexInclusive;
7546        if (n <= 1) {
7547            return;
7548        }
7549        offset %= n;
7550        if (offset < 0) {
7551            offset += n;
7552        }
7553        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7554        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7555        while (n > 1 && offset > 0) {
7556            final int nOffset = n - offset;
7557            if (offset > nOffset) {
7558                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7559                n = offset;
7560                offset -= nOffset;
7561            } else if (offset < nOffset) {
7562                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7563                startIndexInclusive += offset;
7564                n = nOffset;
7565            } else {
7566                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7567                break;
7568            }
7569        }
7570    }
7571
7572    /**
7573     * Shifts the order of the given int array.
7574     *
7575     * <p>
7576     * There is no special handling for multi-dimensional arrays. This method
7577     * does nothing for {@code null} or empty input arrays.
7578     * </p>
7579     *
7580     * @param array  The array to shift, may be {@code null}.
7581     * @param offset
7582     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7583     *          rotate, than the effective offset is modulo the number of elements to rotate.
7584     * @since 3.5
7585     */
7586    public static void shift(final int[] array, final int offset) {
7587        if (array != null) {
7588            shift(array, 0, array.length, offset);
7589        }
7590    }
7591
7592    /**
7593     * Shifts the order of a series of elements in the given int array.
7594     *
7595     * <p>
7596     * There is no special handling for multi-dimensional arrays. This method
7597     * does nothing for {@code null} or empty input arrays.
7598     * </p>
7599     *
7600     * @param array
7601     *            the array to shift, may be {@code null}.
7602     * @param startIndexInclusive
7603     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7604     *            change.
7605     * @param endIndexExclusive
7606     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7607     *            change. Overvalue (&gt;array.length) is demoted to array length.
7608     * @param offset
7609     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7610     *          rotate, than the effective offset is modulo the number of elements to rotate.
7611     * @since 3.5
7612     */
7613    public static void shift(final int[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7614        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7615            return;
7616        }
7617        startIndexInclusive = max0(startIndexInclusive);
7618        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7619        int n = endIndexExclusive - startIndexInclusive;
7620        if (n <= 1) {
7621            return;
7622        }
7623        offset %= n;
7624        if (offset < 0) {
7625            offset += n;
7626        }
7627        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7628        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7629        while (n > 1 && offset > 0) {
7630            final int nOffset = n - offset;
7631            if (offset > nOffset) {
7632                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7633                n = offset;
7634                offset -= nOffset;
7635            } else if (offset < nOffset) {
7636                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7637                startIndexInclusive += offset;
7638                n = nOffset;
7639            } else {
7640                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7641                break;
7642            }
7643        }
7644    }
7645
7646    /**
7647     * Shifts the order of the given long array.
7648     *
7649     * <p>
7650     * There is no special handling for multi-dimensional arrays. This method
7651     * does nothing for {@code null} or empty input arrays.
7652     * </p>
7653     *
7654     * @param array  The array to shift, may be {@code null}.
7655     * @param offset
7656     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7657     *          rotate, than the effective offset is modulo the number of elements to rotate.
7658     * @since 3.5
7659     */
7660    public static void shift(final long[] array, final int offset) {
7661        if (array != null) {
7662            shift(array, 0, array.length, offset);
7663        }
7664    }
7665
7666    /**
7667     * Shifts the order of a series of elements in the given long array.
7668     *
7669     * <p>
7670     * There is no special handling for multi-dimensional arrays. This method
7671     * does nothing for {@code null} or empty input arrays.
7672     * </p>
7673     *
7674     * @param array
7675     *            the array to shift, may be {@code null}.
7676     * @param startIndexInclusive
7677     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7678     *            change.
7679     * @param endIndexExclusive
7680     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7681     *            change. Overvalue (&gt;array.length) is demoted to array length.
7682     * @param offset
7683     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7684     *          rotate, than the effective offset is modulo the number of elements to rotate.
7685     * @since 3.5
7686     */
7687    public static void shift(final long[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7688        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7689            return;
7690        }
7691        startIndexInclusive = max0(startIndexInclusive);
7692        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7693        int n = endIndexExclusive - startIndexInclusive;
7694        if (n <= 1) {
7695            return;
7696        }
7697        offset %= n;
7698        if (offset < 0) {
7699            offset += n;
7700        }
7701        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7702        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7703        while (n > 1 && offset > 0) {
7704            final int nOffset = n - offset;
7705            if (offset > nOffset) {
7706                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7707                n = offset;
7708                offset -= nOffset;
7709            } else if (offset < nOffset) {
7710                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7711                startIndexInclusive += offset;
7712                n = nOffset;
7713            } else {
7714                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7715                break;
7716            }
7717        }
7718    }
7719
7720    /**
7721     * Shifts the order of the given array.
7722     *
7723     * <p>
7724     * There is no special handling for multi-dimensional arrays. This method
7725     * does nothing for {@code null} or empty input arrays.
7726     * </p>
7727     *
7728     * @param array  The array to shift, may be {@code null}.
7729     * @param offset
7730     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7731     *          rotate, than the effective offset is modulo the number of elements to rotate.
7732     * @since 3.5
7733     */
7734    public static void shift(final Object[] array, final int offset) {
7735        if (array != null) {
7736            shift(array, 0, array.length, offset);
7737        }
7738    }
7739
7740    /**
7741     * Shifts the order of a series of elements in the given array.
7742     *
7743     * <p>
7744     * There is no special handling for multi-dimensional arrays. This method
7745     * does nothing for {@code null} or empty input arrays.
7746     * </p>
7747     *
7748     * @param array
7749     *            the array to shift, may be {@code null}.
7750     * @param startIndexInclusive
7751     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7752     *            change.
7753     * @param endIndexExclusive
7754     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7755     *            change. Overvalue (&gt;array.length) is demoted to array length.
7756     * @param offset
7757     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7758     *          rotate, than the effective offset is modulo the number of elements to rotate.
7759     * @since 3.5
7760     */
7761    public static void shift(final Object[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7762        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7763            return;
7764        }
7765        startIndexInclusive = max0(startIndexInclusive);
7766        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7767        int n = endIndexExclusive - startIndexInclusive;
7768        if (n <= 1) {
7769            return;
7770        }
7771        offset %= n;
7772        if (offset < 0) {
7773            offset += n;
7774        }
7775        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7776        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7777        while (n > 1 && offset > 0) {
7778            final int nOffset = n - offset;
7779            if (offset > nOffset) {
7780                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7781                n = offset;
7782                offset -= nOffset;
7783            } else if (offset < nOffset) {
7784                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7785                startIndexInclusive += offset;
7786                n = nOffset;
7787            } else {
7788                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7789                break;
7790            }
7791        }
7792    }
7793
7794    /**
7795     * Shifts the order of the given short array.
7796     *
7797     * <p>
7798     * There is no special handling for multi-dimensional arrays. This method
7799     * does nothing for {@code null} or empty input arrays.
7800     * </p>
7801     *
7802     * @param array  The array to shift, may be {@code null}.
7803     * @param offset
7804     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7805     *          rotate, than the effective offset is modulo the number of elements to rotate.
7806     * @since 3.5
7807     */
7808    public static void shift(final short[] array, final int offset) {
7809        if (array != null) {
7810            shift(array, 0, array.length, offset);
7811        }
7812    }
7813
7814    /**
7815     * Shifts the order of a series of elements in the given short array.
7816     *
7817     * <p>
7818     * There is no special handling for multi-dimensional arrays. This method
7819     * does nothing for {@code null} or empty input arrays.
7820     * </p>
7821     *
7822     * @param array
7823     *            the array to shift, may be {@code null}.
7824     * @param startIndexInclusive
7825     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7826     *            change.
7827     * @param endIndexExclusive
7828     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7829     *            change. Overvalue (&gt;array.length) is demoted to array length.
7830     * @param offset
7831     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7832     *          rotate, than the effective offset is modulo the number of elements to rotate.
7833     * @since 3.5
7834     */
7835    public static void shift(final short[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7836        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7837            return;
7838        }
7839        startIndexInclusive = max0(startIndexInclusive);
7840        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7841        int n = endIndexExclusive - startIndexInclusive;
7842        if (n <= 1) {
7843            return;
7844        }
7845        offset %= n;
7846        if (offset < 0) {
7847            offset += n;
7848        }
7849        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7850        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7851        while (n > 1 && offset > 0) {
7852            final int nOffset = n - offset;
7853            if (offset > nOffset) {
7854                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7855                n = offset;
7856                offset -= nOffset;
7857            } else if (offset < nOffset) {
7858                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7859                startIndexInclusive += offset;
7860                n = nOffset;
7861            } else {
7862                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7863                break;
7864            }
7865        }
7866    }
7867
7868    /**
7869     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
7870     * algorithm</a>.
7871     * <p>
7872     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7873     * </p>
7874     * <p>
7875     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7876     * with a {@link SecureRandom} argument.
7877     * </p>
7878     *
7879     * @param array The array to shuffle.
7880     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7881     * @since 3.6
7882     */
7883    public static void shuffle(final boolean[] array) {
7884        shuffle(array, random());
7885    }
7886
7887    /**
7888     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
7889     * algorithm</a>.
7890     *
7891     * @param array  The array to shuffle, no-op if {@code null}.
7892     * @param random The source of randomness used to permute the elements, no-op if {@code null}.
7893     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7894     * @since 3.6
7895     */
7896    public static void shuffle(final boolean[] array, final Random random) {
7897        if (array != null && random != null) {
7898            for (int i = array.length; i > 1; i--) {
7899                swap(array, i - 1, random.nextInt(i), 1);
7900            }
7901        }
7902    }
7903
7904    /**
7905     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
7906     * algorithm</a>.
7907     * <p>
7908     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7909     * </p>
7910     * <p>
7911     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7912     * with a {@link SecureRandom} argument.
7913     * </p>
7914     *
7915     * @param array The array to shuffle.
7916     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7917     * @since 3.6
7918     */
7919    public static void shuffle(final byte[] array) {
7920        shuffle(array, random());
7921    }
7922
7923    /**
7924     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
7925     * algorithm</a>.
7926     *
7927     * @param array  The array to shuffle, no-op if {@code null}.
7928     * @param random The source of randomness used to permute the elements, no-op if {@code null}.
7929     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7930     * @since 3.6
7931     */
7932    public static void shuffle(final byte[] array, final Random random) {
7933        if (array != null && random != null) {
7934            for (int i = array.length; i > 1; i--) {
7935                swap(array, i - 1, random.nextInt(i), 1);
7936            }
7937        }
7938    }
7939
7940    /**
7941     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
7942     * algorithm</a>.
7943     * <p>
7944     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7945     * </p>
7946     * <p>
7947     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7948     * with a {@link SecureRandom} argument.
7949     * </p>
7950     *
7951     * @param array The array to shuffle.
7952     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7953     * @since 3.6
7954     */
7955    public static void shuffle(final char[] array) {
7956        shuffle(array, random());
7957    }
7958
7959    /**
7960     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
7961     * algorithm</a>.
7962     *
7963     * @param array  The array to shuffle, no-op if {@code null}.
7964     * @param random The source of randomness used to permute the elements, no-op if {@code null}.
7965     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7966     * @since 3.6
7967     */
7968    public static void shuffle(final char[] array, final Random random) {
7969        if (array != null && random != null) {
7970            for (int i = array.length; i > 1; i--) {
7971                swap(array, i - 1, random.nextInt(i), 1);
7972            }
7973        }
7974    }
7975
7976    /**
7977     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
7978     * algorithm</a>.
7979     * <p>
7980     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7981     * </p>
7982     * <p>
7983     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7984     * with a {@link SecureRandom} argument.
7985     * </p>
7986     *
7987     * @param array The array to shuffle.
7988     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7989     * @since 3.6
7990     */
7991    public static void shuffle(final double[] array) {
7992        shuffle(array, random());
7993    }
7994
7995    /**
7996     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
7997     * algorithm</a>.
7998     *
7999     * @param array  The array to shuffle, no-op if {@code null}.
8000     * @param random The source of randomness used to permute the elements, no-op if {@code null}.
8001     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8002     * @since 3.6
8003     */
8004    public static void shuffle(final double[] array, final Random random) {
8005        if (array != null && random != null) {
8006            for (int i = array.length; i > 1; i--) {
8007                swap(array, i - 1, random.nextInt(i), 1);
8008            }
8009        }
8010    }
8011
8012    /**
8013     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
8014     * algorithm</a>.
8015     * <p>
8016     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
8017     * </p>
8018     * <p>
8019     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
8020     * with a {@link SecureRandom} argument.
8021     * </p>
8022     *
8023     * @param array The array to shuffle.
8024     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8025     * @since 3.6
8026     */
8027    public static void shuffle(final float[] array) {
8028        shuffle(array, random());
8029    }
8030
8031    /**
8032     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
8033     * algorithm</a>.
8034     *
8035     * @param array  The array to shuffle, no-op if {@code null}.
8036     * @param random The source of randomness used to permute the elements, no-op if {@code null}.
8037     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8038     * @since 3.6
8039     */
8040    public static void shuffle(final float[] array, final Random random) {
8041        if (array != null && random != null) {
8042            for (int i = array.length; i > 1; i--) {
8043                swap(array, i - 1, random.nextInt(i), 1);
8044            }
8045        }
8046    }
8047
8048    /**
8049     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
8050     * algorithm</a>.
8051     * <p>
8052     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
8053     * </p>
8054     * <p>
8055     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
8056     * with a {@link SecureRandom} argument.
8057     * </p>
8058     *
8059     * @param array The array to shuffle.
8060     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8061     * @since 3.6
8062     */
8063    public static void shuffle(final int[] array) {
8064        shuffle(array, random());
8065    }
8066
8067    /**
8068     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
8069     * algorithm</a>.
8070     *
8071     * @param array  The array to shuffle, no-op if {@code null}.
8072     * @param random The source of randomness used to permute the elements, no-op if {@code null}.
8073     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8074     * @since 3.6
8075     */
8076    public static void shuffle(final int[] array, final Random random) {
8077        if (array != null && random != null) {
8078            for (int i = array.length; i > 1; i--) {
8079                swap(array, i - 1, random.nextInt(i), 1);
8080            }
8081        }
8082    }
8083
8084    /**
8085     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
8086     * algorithm</a>.
8087     * <p>
8088     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
8089     * </p>
8090     * <p>
8091     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
8092     * with a {@link SecureRandom} argument.
8093     * </p>
8094     *
8095     * @param array The array to shuffle.
8096     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8097     * @since 3.6
8098     */
8099    public static void shuffle(final long[] array) {
8100        shuffle(array, random());
8101    }
8102
8103    /**
8104     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
8105     * algorithm</a>.
8106     *
8107     * @param array  The array to shuffle, no-op if {@code null}.
8108     * @param random The source of randomness used to permute the elements, no-op if {@code null}.
8109     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8110     * @since 3.6
8111     */
8112    public static void shuffle(final long[] array, final Random random) {
8113        if (array != null && random != null) {
8114            for (int i = array.length; i > 1; i--) {
8115                swap(array, i - 1, random.nextInt(i), 1);
8116            }
8117        }
8118    }
8119
8120    /**
8121     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
8122     * algorithm</a>.
8123     * <p>
8124     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
8125     * </p>
8126     * <p>
8127     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
8128     * with a {@link SecureRandom} argument.
8129     * </p>
8130     *
8131     * @param array The array to shuffle.
8132     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8133     * @since 3.6
8134     */
8135    public static void shuffle(final Object[] array) {
8136        shuffle(array, random());
8137    }
8138
8139    /**
8140     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
8141     * algorithm</a>.
8142     *
8143     * @param array  The array to shuffle, no-op if {@code null}.
8144     * @param random The source of randomness used to permute the elements, no-op if {@code null}.
8145     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8146     * @since 3.6
8147     */
8148    public static void shuffle(final Object[] array, final Random random) {
8149        if (array != null && random != null) {
8150            for (int i = array.length; i > 1; i--) {
8151                swap(array, i - 1, random.nextInt(i), 1);
8152            }
8153        }
8154    }
8155
8156    /**
8157     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
8158     * algorithm</a>.
8159     * <p>
8160     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
8161     * </p>
8162     * <p>
8163     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
8164     * with a {@link SecureRandom} argument.
8165     * </p>
8166     *
8167     * @param array The array to shuffle.
8168     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8169     * @since 3.6
8170     */
8171    public static void shuffle(final short[] array) {
8172        shuffle(array, random());
8173    }
8174
8175    /**
8176     * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
8177     * algorithm</a>.
8178     *
8179     * @param array  The array to shuffle, no-op if {@code null}.
8180     * @param random The source of randomness used to permute the elements, no-op if {@code null}.
8181     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8182     * @since 3.6
8183     */
8184    public static void shuffle(final short[] array, final Random random) {
8185        if (array != null && random != null) {
8186            for (int i = array.length; i > 1; i--) {
8187                swap(array, i - 1, random.nextInt(i), 1);
8188            }
8189        }
8190    }
8191
8192    /**
8193     * Tests whether the given data array starts with an expected array, for example, signature bytes.
8194     * <p>
8195     * If both arrays are null, the method returns true. The method return false when one array is null and the other not.
8196     * </p>
8197     *
8198     * @param data     The data to search, maybe larger than the expected data.
8199     * @param expected The expected data to find.
8200     * @return whether a match was found.
8201     * @since 3.18.0
8202     */
8203    public static boolean startsWith(final byte[] data, final byte[] expected) {
8204        if (data == expected) {
8205            return true;
8206        }
8207        if (data == null || expected == null) {
8208            return false;
8209        }
8210        final int dataLen = data.length;
8211        if (expected.length > dataLen) {
8212            return false;
8213        }
8214        if (expected.length == dataLen) {
8215            // delegate to Arrays.equals() which has optimizations on Java > 8
8216            return Arrays.equals(data, expected);
8217        }
8218        // Once we are on Java 9+ we can delegate to Arrays here as well (or not).
8219        for (int i = 0; i < expected.length; i++) {
8220            if (data[i] != expected[i]) {
8221                return false;
8222            }
8223        }
8224        return true;
8225    }
8226
8227    /**
8228     * Produces a new {@code boolean} array containing the elements between the start and end indices.
8229     * <p>
8230     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8231     * </p>
8232     *
8233     * @param array               The input array.
8234     * @param startIndexInclusive The starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8235     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8236     *                            (&gt;array.length) is demoted to array length.
8237     * @return A new array containing the elements between the start and end indices.
8238     * @since 2.1
8239     * @see Arrays#copyOfRange(boolean[], int, int)
8240     */
8241    public static boolean[] subarray(final boolean[] array, int startIndexInclusive, int endIndexExclusive) {
8242        if (array == null) {
8243            return null;
8244        }
8245        startIndexInclusive = max0(startIndexInclusive);
8246        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8247        final int newSize = endIndexExclusive - startIndexInclusive;
8248        if (newSize <= 0) {
8249            return EMPTY_BOOLEAN_ARRAY;
8250        }
8251        return arraycopy(array, startIndexInclusive, 0, newSize, boolean[]::new);
8252    }
8253
8254    /**
8255     * Produces a new {@code byte} array containing the elements between the start and end indices.
8256     * <p>
8257     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8258     * </p>
8259     *
8260     * @param array               The input array.
8261     * @param startIndexInclusive The starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8262     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8263     *                            (&gt;array.length) is demoted to array length.
8264     * @return A new array containing the elements between the start and end indices.
8265     * @since 2.1
8266     * @see Arrays#copyOfRange(byte[], int, int)
8267     */
8268    public static byte[] subarray(final byte[] array, int startIndexInclusive, int endIndexExclusive) {
8269        if (array == null) {
8270            return null;
8271        }
8272        startIndexInclusive = max0(startIndexInclusive);
8273        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8274        final int newSize = endIndexExclusive - startIndexInclusive;
8275        if (newSize <= 0) {
8276            return EMPTY_BYTE_ARRAY;
8277        }
8278        return arraycopy(array, startIndexInclusive, 0, newSize, byte[]::new);
8279    }
8280
8281    /**
8282     * Produces a new {@code char} array containing the elements between the start and end indices.
8283     * <p>
8284     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8285     * </p>
8286     *
8287     * @param array               The input array.
8288     * @param startIndexInclusive The starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8289     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8290     *                            (&gt;array.length) is demoted to array length.
8291     * @return A new array containing the elements between the start and end indices.
8292     * @since 2.1
8293     * @see Arrays#copyOfRange(char[], int, int)
8294     */
8295    public static char[] subarray(final char[] array, int startIndexInclusive, int endIndexExclusive) {
8296        if (array == null) {
8297            return null;
8298        }
8299        startIndexInclusive = max0(startIndexInclusive);
8300        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8301        final int newSize = endIndexExclusive - startIndexInclusive;
8302        if (newSize <= 0) {
8303            return EMPTY_CHAR_ARRAY;
8304        }
8305        return arraycopy(array, startIndexInclusive, 0, newSize, char[]::new);
8306    }
8307
8308    /**
8309     * Produces a new {@code double} array containing the elements between the start and end indices.
8310     * <p>
8311     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8312     * </p>
8313     *
8314     * @param array               The input array.
8315     * @param startIndexInclusive The starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8316     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8317     *                            (&gt;array.length) is demoted to array length.
8318     * @return A new array containing the elements between the start and end indices.
8319     * @since 2.1
8320     * @see Arrays#copyOfRange(double[], int, int)
8321     */
8322    public static double[] subarray(final double[] array, int startIndexInclusive, int endIndexExclusive) {
8323        if (array == null) {
8324            return null;
8325        }
8326        startIndexInclusive = max0(startIndexInclusive);
8327        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8328        final int newSize = endIndexExclusive - startIndexInclusive;
8329        if (newSize <= 0) {
8330            return EMPTY_DOUBLE_ARRAY;
8331        }
8332        return arraycopy(array, startIndexInclusive, 0, newSize, double[]::new);
8333    }
8334
8335    /**
8336     * Produces a new {@code float} array containing the elements between the start and end indices.
8337     * <p>
8338     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8339     * </p>
8340     *
8341     * @param array               The input array.
8342     * @param startIndexInclusive The starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8343     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8344     *                            (&gt;array.length) is demoted to array length.
8345     * @return A new array containing the elements between the start and end indices.
8346     * @since 2.1
8347     * @see Arrays#copyOfRange(float[], int, int)
8348     */
8349    public static float[] subarray(final float[] array, int startIndexInclusive, int endIndexExclusive) {
8350        if (array == null) {
8351            return null;
8352        }
8353        startIndexInclusive = max0(startIndexInclusive);
8354        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8355        final int newSize = endIndexExclusive - startIndexInclusive;
8356        if (newSize <= 0) {
8357            return EMPTY_FLOAT_ARRAY;
8358        }
8359        return arraycopy(array, startIndexInclusive, 0, newSize, float[]::new);
8360    }
8361
8362    /**
8363     * Produces a new {@code int} array containing the elements between the start and end indices.
8364     * <p>
8365     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8366     * </p>
8367     *
8368     * @param array               The input array.
8369     * @param startIndexInclusive The starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8370     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8371     *                            (&gt;array.length) is demoted to array length.
8372     * @return A new array containing the elements between the start and end indices.
8373     * @since 2.1
8374     * @see Arrays#copyOfRange(int[], int, int)
8375     */
8376    public static int[] subarray(final int[] array, int startIndexInclusive, int endIndexExclusive) {
8377        if (array == null) {
8378            return null;
8379        }
8380        startIndexInclusive = max0(startIndexInclusive);
8381        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8382        final int newSize = endIndexExclusive - startIndexInclusive;
8383        if (newSize <= 0) {
8384            return EMPTY_INT_ARRAY;
8385        }
8386        return arraycopy(array, startIndexInclusive, 0, newSize, int[]::new);
8387    }
8388
8389    /**
8390     * Produces a new {@code long} array containing the elements between the start and end indices.
8391     * <p>
8392     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8393     * </p>
8394     *
8395     * @param array               The input array.
8396     * @param startIndexInclusive The starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8397     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8398     *                            (&gt;array.length) is demoted to array length.
8399     * @return A new array containing the elements between the start and end indices.
8400     * @since 2.1
8401     * @see Arrays#copyOfRange(long[], int, int)
8402     */
8403    public static long[] subarray(final long[] array, int startIndexInclusive, int endIndexExclusive) {
8404        if (array == null) {
8405            return null;
8406        }
8407        startIndexInclusive = max0(startIndexInclusive);
8408        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8409        final int newSize = endIndexExclusive - startIndexInclusive;
8410        if (newSize <= 0) {
8411            return EMPTY_LONG_ARRAY;
8412        }
8413        return arraycopy(array, startIndexInclusive, 0, newSize, long[]::new);
8414    }
8415
8416    /**
8417     * Produces a new {@code short} array containing the elements between the start and end indices.
8418     * <p>
8419     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8420     * </p>
8421     *
8422     * @param array               The input array.
8423     * @param startIndexInclusive The starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8424     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8425     *                            (&gt;array.length) is demoted to array length.
8426     * @return A new array containing the elements between the start and end indices.
8427     * @since 2.1
8428     * @see Arrays#copyOfRange(short[], int, int)
8429     */
8430    public static short[] subarray(final short[] array, int startIndexInclusive, int endIndexExclusive) {
8431        if (array == null) {
8432            return null;
8433        }
8434        startIndexInclusive = max0(startIndexInclusive);
8435        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8436        final int newSize = endIndexExclusive - startIndexInclusive;
8437        if (newSize <= 0) {
8438            return EMPTY_SHORT_ARRAY;
8439        }
8440        return arraycopy(array, startIndexInclusive, 0, newSize, short[]::new);
8441    }
8442
8443    /**
8444     * Produces a new array containing the elements between the start and end indices.
8445     * <p>
8446     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8447     * </p>
8448     * <p>
8449     * The component type of the subarray is always the same as that of the input array. Thus, if the input is an array of type {@link Date}, the following
8450     * usage is envisaged:
8451     * </p>
8452     *
8453     * <pre>
8454     *
8455     * Date[] someDates = (Date[]) ArrayUtils.subarray(allDates, 2, 5);
8456     * </pre>
8457     *
8458     * @param <T>                 the component type of the array.
8459     * @param array               The input array.
8460     * @param startIndexInclusive The starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8461     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8462     *                            (&gt;array.length) is demoted to array length.
8463     * @return A new array containing the elements between the start and end indices.
8464     * @since 2.1
8465     * @see Arrays#copyOfRange(Object[], int, int)
8466     */
8467    public static <T> T[] subarray(final T[] array, int startIndexInclusive, int endIndexExclusive) {
8468        if (array == null) {
8469            return null;
8470        }
8471        startIndexInclusive = max0(startIndexInclusive);
8472        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8473        final int newSize = endIndexExclusive - startIndexInclusive;
8474        final Class<T> type = getComponentType(array);
8475        if (newSize <= 0) {
8476            return newInstance(type, 0);
8477        }
8478        return arraycopy(array, startIndexInclusive, 0, newSize, () -> newInstance(type, newSize));
8479    }
8480
8481    /**
8482     * Swaps two elements in the given boolean array.
8483     *
8484     * <p>
8485     * There is no special handling for multi-dimensional arrays. This method
8486     * does nothing for a {@code null} or empty input array or for overflow indices.
8487     * Negative indices are promoted to 0(zero).
8488     * </p>
8489     *
8490     * Examples:
8491     * <ul>
8492     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8493     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8494     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8495     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8496     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8497     * </ul>
8498     *
8499     * @param array  The array to swap, may be {@code null}.
8500     * @param offset1 The index of the first element to swap.
8501     * @param offset2 The index of the second element to swap.
8502     * @since 3.5
8503     */
8504    public static void swap(final boolean[] array, final int offset1, final int offset2) {
8505        swap(array, offset1, offset2, 1);
8506    }
8507
8508    /**
8509     * Swaps a series of elements in the given boolean array.
8510     *
8511     * <p>
8512     * This method does nothing for a {@code null} or empty input array or
8513     * for overflow indices. Negative indices are promoted to 0(zero). If any
8514     * of the sub-arrays to swap falls outside of the given array, then the
8515     * swap is stopped at the end of the array and as many as possible elements
8516     * are swapped.
8517     * </p>
8518     *
8519     * Examples:
8520     * <ul>
8521     *     <li>ArrayUtils.swap([true, false, true, false], 0, 2, 1) -&gt; [true, false, true, false]</li>
8522     *     <li>ArrayUtils.swap([true, false, true, false], 0, 0, 1) -&gt; [true, false, true, false]</li>
8523     *     <li>ArrayUtils.swap([true, false, true, false], 0, 2, 2) -&gt; [true, false, true, false]</li>
8524     *     <li>ArrayUtils.swap([true, false, true, false], -3, 2, 2) -&gt; [true, false, true, false]</li>
8525     *     <li>ArrayUtils.swap([true, false, true, false], 0, 3, 3) -&gt; [false, false, true, true]</li>
8526     * </ul>
8527     *
8528     * @param array The array to swap, may be {@code null}.
8529     * @param offset1 The index of the first element in the series to swap.
8530     * @param offset2 The index of the second element in the series to swap.
8531     * @param len The number of elements to swap starting with the given indices.
8532     * @since 3.5
8533     */
8534    public static void swap(final boolean[] array, int offset1, int offset2, int len) {
8535        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8536            return;
8537        }
8538        offset1 = max0(offset1);
8539        offset2 = max0(offset2);
8540        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8541        for (int i = 0; i < len; i++, offset1++, offset2++) {
8542            final boolean aux = array[offset1];
8543            array[offset1] = array[offset2];
8544            array[offset2] = aux;
8545        }
8546    }
8547
8548    /**
8549     * Swaps two elements in the given byte array.
8550     *
8551     * <p>
8552     * There is no special handling for multi-dimensional arrays. This method
8553     * does nothing for a {@code null} or empty input array or for overflow indices.
8554     * Negative indices are promoted to 0(zero).
8555     * </p>
8556     *
8557     * Examples:
8558     * <ul>
8559     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8560     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8561     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8562     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8563     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8564     * </ul>
8565     *
8566     * @param array  The array to swap, may be {@code null}.
8567     * @param offset1 The index of the first element to swap.
8568     * @param offset2 The index of the second element to swap.
8569     * @since 3.5
8570     */
8571    public static void swap(final byte[] array, final int offset1, final int offset2) {
8572        swap(array, offset1, offset2, 1);
8573    }
8574
8575    /**
8576     * Swaps a series of elements in the given byte array.
8577     *
8578     * <p>
8579     * This method does nothing for a {@code null} or empty input array or
8580     * for overflow indices. Negative indices are promoted to 0(zero). If any
8581     * of the sub-arrays to swap falls outside of the given array, then the
8582     * swap is stopped at the end of the array and as many as possible elements
8583     * are swapped.
8584     * </p>
8585     *
8586     * Examples:
8587     * <ul>
8588     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8589     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8590     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8591     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8592     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8593     * </ul>
8594     *
8595     * @param array The array to swap, may be {@code null}.
8596     * @param offset1 The index of the first element in the series to swap.
8597     * @param offset2 The index of the second element in the series to swap.
8598     * @param len The number of elements to swap starting with the given indices.
8599     * @since 3.5
8600     */
8601    public static void swap(final byte[] array, int offset1, int offset2, int len) {
8602        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8603            return;
8604        }
8605        offset1 = max0(offset1);
8606        offset2 = max0(offset2);
8607        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8608        for (int i = 0; i < len; i++, offset1++, offset2++) {
8609            final byte aux = array[offset1];
8610            array[offset1] = array[offset2];
8611            array[offset2] = aux;
8612        }
8613    }
8614
8615    /**
8616     * Swaps two elements in the given char array.
8617     *
8618     * <p>
8619     * There is no special handling for multi-dimensional arrays. This method
8620     * does nothing for a {@code null} or empty input array or for overflow indices.
8621     * Negative indices are promoted to 0(zero).
8622     * </p>
8623     *
8624     * Examples:
8625     * <ul>
8626     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8627     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8628     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8629     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8630     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8631     * </ul>
8632     *
8633     * @param array  The array to swap, may be {@code null}.
8634     * @param offset1 The index of the first element to swap.
8635     * @param offset2 The index of the second element to swap.
8636     * @since 3.5
8637     */
8638    public static void swap(final char[] array, final int offset1, final int offset2) {
8639        swap(array, offset1, offset2, 1);
8640    }
8641
8642    /**
8643     * Swaps a series of elements in the given char array.
8644     *
8645     * <p>
8646     * This method does nothing for a {@code null} or empty input array or
8647     * for overflow indices. Negative indices are promoted to 0(zero). If any
8648     * of the sub-arrays to swap falls outside of the given array, then the
8649     * swap is stopped at the end of the array and as many as possible elements
8650     * are swapped.
8651     * </p>
8652     *
8653     * Examples:
8654     * <ul>
8655     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8656     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8657     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8658     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8659     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8660     * </ul>
8661     *
8662     * @param array The array to swap, may be {@code null}.
8663     * @param offset1 The index of the first element in the series to swap.
8664     * @param offset2 The index of the second element in the series to swap.
8665     * @param len The number of elements to swap starting with the given indices.
8666     * @since 3.5
8667     */
8668    public static void swap(final char[] array, int offset1, int offset2, int len) {
8669        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8670            return;
8671        }
8672        offset1 = max0(offset1);
8673        offset2 = max0(offset2);
8674        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8675        for (int i = 0; i < len; i++, offset1++, offset2++) {
8676            final char aux = array[offset1];
8677            array[offset1] = array[offset2];
8678            array[offset2] = aux;
8679        }
8680    }
8681
8682    /**
8683     * Swaps two elements in the given double array.
8684     *
8685     * <p>
8686     * There is no special handling for multi-dimensional arrays. This method
8687     * does nothing for a {@code null} or empty input array or for overflow indices.
8688     * Negative indices are promoted to 0(zero).
8689     * </p>
8690     *
8691     * Examples:
8692     * <ul>
8693     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8694     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8695     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8696     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8697     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8698     * </ul>
8699     *
8700     * @param array  The array to swap, may be {@code null}.
8701     * @param offset1 The index of the first element to swap.
8702     * @param offset2 The index of the second element to swap.
8703     * @since 3.5
8704     */
8705    public static void swap(final double[] array, final int offset1, final int offset2) {
8706        swap(array, offset1, offset2, 1);
8707    }
8708
8709    /**
8710     * Swaps a series of elements in the given double array.
8711     *
8712     * <p>
8713     * This method does nothing for a {@code null} or empty input array or
8714     * for overflow indices. Negative indices are promoted to 0(zero). If any
8715     * of the sub-arrays to swap falls outside of the given array, then the
8716     * swap is stopped at the end of the array and as many as possible elements
8717     * are swapped.
8718     * </p>
8719     *
8720     * Examples:
8721     * <ul>
8722     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8723     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8724     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8725     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8726     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8727     * </ul>
8728     *
8729     * @param array The array to swap, may be {@code null}.
8730     * @param offset1 The index of the first element in the series to swap.
8731     * @param offset2 The index of the second element in the series to swap.
8732     * @param len The number of elements to swap starting with the given indices.
8733     * @since 3.5
8734     */
8735    public static void swap(final double[] array,  int offset1, int offset2, int len) {
8736        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8737            return;
8738        }
8739        offset1 = max0(offset1);
8740        offset2 = max0(offset2);
8741        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8742        for (int i = 0; i < len; i++, offset1++, offset2++) {
8743            final double aux = array[offset1];
8744            array[offset1] = array[offset2];
8745            array[offset2] = aux;
8746        }
8747    }
8748
8749    /**
8750     * Swaps two elements in the given float array.
8751     *
8752     * <p>
8753     * There is no special handling for multi-dimensional arrays. This method
8754     * does nothing for a {@code null} or empty input array or for overflow indices.
8755     * Negative indices are promoted to 0(zero).
8756     * </p>
8757     *
8758     * Examples:
8759     * <ul>
8760     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8761     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8762     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8763     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8764     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8765     * </ul>
8766     *
8767     * @param array  The array to swap, may be {@code null}.
8768     * @param offset1 The index of the first element to swap.
8769     * @param offset2 The index of the second element to swap.
8770     * @since 3.5
8771     */
8772    public static void swap(final float[] array, final int offset1, final int offset2) {
8773        swap(array, offset1, offset2, 1);
8774    }
8775
8776    /**
8777     * Swaps a series of elements in the given float array.
8778     *
8779     * <p>
8780     * This method does nothing for a {@code null} or empty input array or
8781     * for overflow indices. Negative indices are promoted to 0(zero). If any
8782     * of the sub-arrays to swap falls outside of the given array, then the
8783     * swap is stopped at the end of the array and as many as possible elements
8784     * are swapped.
8785     * </p>
8786     *
8787     * Examples:
8788     * <ul>
8789     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8790     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8791     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8792     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8793     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8794     * </ul>
8795     *
8796     * @param array The array to swap, may be {@code null}.
8797     * @param offset1 The index of the first element in the series to swap.
8798     * @param offset2 The index of the second element in the series to swap.
8799     * @param len The number of elements to swap starting with the given indices.
8800     * @since 3.5
8801     */
8802    public static void swap(final float[] array, int offset1, int offset2, int len) {
8803        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8804            return;
8805        }
8806        offset1 = max0(offset1);
8807        offset2 = max0(offset2);
8808        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8809        for (int i = 0; i < len; i++, offset1++, offset2++) {
8810            final float aux = array[offset1];
8811            array[offset1] = array[offset2];
8812            array[offset2] = aux;
8813        }
8814
8815    }
8816
8817    /**
8818     * Swaps two elements in the given int array.
8819     *
8820     * <p>
8821     * There is no special handling for multi-dimensional arrays. This method
8822     * does nothing for a {@code null} or empty input array or for overflow indices.
8823     * Negative indices are promoted to 0(zero).
8824     * </p>
8825     *
8826     * Examples:
8827     * <ul>
8828     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8829     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8830     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8831     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8832     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8833     * </ul>
8834     *
8835     * @param array  The array to swap, may be {@code null}.
8836     * @param offset1 The index of the first element to swap.
8837     * @param offset2 The index of the second element to swap.
8838     * @since 3.5
8839     */
8840    public static void swap(final int[] array, final int offset1, final int offset2) {
8841        swap(array, offset1, offset2, 1);
8842    }
8843
8844    /**
8845     * Swaps a series of elements in the given int array.
8846     *
8847     * <p>
8848     * This method does nothing for a {@code null} or empty input array or
8849     * for overflow indices. Negative indices are promoted to 0(zero). If any
8850     * of the sub-arrays to swap falls outside of the given array, then the
8851     * swap is stopped at the end of the array and as many as possible elements
8852     * are swapped.
8853     * </p>
8854     *
8855     * Examples:
8856     * <ul>
8857     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8858     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8859     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8860     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8861     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8862     * </ul>
8863     *
8864     * @param array The array to swap, may be {@code null}.
8865     * @param offset1 The index of the first element in the series to swap.
8866     * @param offset2 The index of the second element in the series to swap.
8867     * @param len The number of elements to swap starting with the given indices.
8868     * @since 3.5
8869     */
8870    public static void swap(final int[] array,  int offset1, int offset2, int len) {
8871        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8872            return;
8873        }
8874        offset1 = max0(offset1);
8875        offset2 = max0(offset2);
8876        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8877        for (int i = 0; i < len; i++, offset1++, offset2++) {
8878            final int aux = array[offset1];
8879            array[offset1] = array[offset2];
8880            array[offset2] = aux;
8881        }
8882    }
8883
8884    /**
8885     * Swaps two elements in the given long array.
8886     *
8887     * <p>
8888     * There is no special handling for multi-dimensional arrays. This method
8889     * does nothing for a {@code null} or empty input array or for overflow indices.
8890     * Negative indices are promoted to 0(zero).
8891     * </p>
8892     *
8893     * Examples:
8894     * <ul>
8895     *     <li>ArrayUtils.swap([true, false, true], 0, 2) -&gt; [true, false, true]</li>
8896     *     <li>ArrayUtils.swap([true, false, true], 0, 0) -&gt; [true, false, true]</li>
8897     *     <li>ArrayUtils.swap([true, false, true], 1, 0) -&gt; [false, true, true]</li>
8898     *     <li>ArrayUtils.swap([true, false, true], 0, 5) -&gt; [true, false, true]</li>
8899     *     <li>ArrayUtils.swap([true, false, true], -1, 1) -&gt; [false, true, true]</li>
8900     * </ul>
8901     *
8902     * @param array  The array to swap, may be {@code null}.
8903     * @param offset1 The index of the first element to swap.
8904     * @param offset2 The index of the second element to swap.
8905     * @since 3.5
8906     */
8907    public static void swap(final long[] array, final int offset1, final int offset2) {
8908        swap(array, offset1, offset2, 1);
8909    }
8910
8911    /**
8912     * Swaps a series of elements in the given long array.
8913     *
8914     * <p>
8915     * This method does nothing for a {@code null} or empty input array or
8916     * for overflow indices. Negative indices are promoted to 0(zero). If any
8917     * of the sub-arrays to swap falls outside of the given array, then the
8918     * swap is stopped at the end of the array and as many as possible elements
8919     * are swapped.
8920     * </p>
8921     *
8922     * Examples:
8923     * <ul>
8924     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8925     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8926     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8927     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8928     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8929     * </ul>
8930     *
8931     * @param array The array to swap, may be {@code null}.
8932     * @param offset1 The index of the first element in the series to swap.
8933     * @param offset2 The index of the second element in the series to swap.
8934     * @param len The number of elements to swap starting with the given indices.
8935     * @since 3.5
8936     */
8937    public static void swap(final long[] array,  int offset1, int offset2, int len) {
8938        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8939            return;
8940        }
8941        offset1 = max0(offset1);
8942        offset2 = max0(offset2);
8943        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8944        for (int i = 0; i < len; i++, offset1++, offset2++) {
8945            final long aux = array[offset1];
8946            array[offset1] = array[offset2];
8947            array[offset2] = aux;
8948        }
8949    }
8950
8951    /**
8952     * Swaps two elements in the given array.
8953     *
8954     * <p>
8955     * There is no special handling for multi-dimensional arrays. This method
8956     * does nothing for a {@code null} or empty input array or for overflow indices.
8957     * Negative indices are promoted to 0(zero).
8958     * </p>
8959     *
8960     * Examples:
8961     * <ul>
8962     *     <li>ArrayUtils.swap(["1", "2", "3"], 0, 2) -&gt; ["3", "2", "1"]</li>
8963     *     <li>ArrayUtils.swap(["1", "2", "3"], 0, 0) -&gt; ["1", "2", "3"]</li>
8964     *     <li>ArrayUtils.swap(["1", "2", "3"], 1, 0) -&gt; ["2", "1", "3"]</li>
8965     *     <li>ArrayUtils.swap(["1", "2", "3"], 0, 5) -&gt; ["1", "2", "3"]</li>
8966     *     <li>ArrayUtils.swap(["1", "2", "3"], -1, 1) -&gt; ["2", "1", "3"]</li>
8967     * </ul>
8968     *
8969     * @param array The array to swap, may be {@code null}.
8970     * @param offset1 The index of the first element to swap.
8971     * @param offset2 The index of the second element to swap.
8972     * @since 3.5
8973     */
8974    public static void swap(final Object[] array, final int offset1, final int offset2) {
8975        swap(array, offset1, offset2, 1);
8976    }
8977
8978    /**
8979     * Swaps a series of elements in the given array.
8980     *
8981     * <p>
8982     * This method does nothing for a {@code null} or empty input array or
8983     * for overflow indices. Negative indices are promoted to 0(zero). If any
8984     * of the sub-arrays to swap falls outside of the given array, then the
8985     * swap is stopped at the end of the array and as many as possible elements
8986     * are swapped.
8987     * </p>
8988     *
8989     * Examples:
8990     * <ul>
8991     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 0, 2, 1) -&gt; ["3", "2", "1", "4"]</li>
8992     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 0, 0, 1) -&gt; ["1", "2", "3", "4"]</li>
8993     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 2, 0, 2) -&gt; ["3", "4", "1", "2"]</li>
8994     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], -3, 2, 2) -&gt; ["3", "4", "1", "2"]</li>
8995     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 0, 3, 3) -&gt; ["4", "2", "3", "1"]</li>
8996     * </ul>
8997     *
8998     * @param array The array to swap, may be {@code null}.
8999     * @param offset1 The index of the first element in the series to swap.
9000     * @param offset2 The index of the second element in the series to swap.
9001     * @param len The number of elements to swap starting with the given indices.
9002     * @since 3.5
9003     */
9004    public static void swap(final Object[] array,  int offset1, int offset2, int len) {
9005        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
9006            return;
9007        }
9008        offset1 = max0(offset1);
9009        offset2 = max0(offset2);
9010        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
9011        for (int i = 0; i < len; i++, offset1++, offset2++) {
9012            final Object aux = array[offset1];
9013            array[offset1] = array[offset2];
9014            array[offset2] = aux;
9015        }
9016    }
9017
9018    /**
9019     * Swaps two elements in the given short array.
9020     *
9021     * <p>
9022     * There is no special handling for multi-dimensional arrays. This method
9023     * does nothing for a {@code null} or empty input array or for overflow indices.
9024     * Negative indices are promoted to 0(zero).
9025     * </p>
9026     *
9027     * Examples:
9028     * <ul>
9029     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
9030     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
9031     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
9032     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
9033     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
9034     * </ul>
9035     *
9036     * @param array  The array to swap, may be {@code null}.
9037     * @param offset1 The index of the first element to swap.
9038     * @param offset2 The index of the second element to swap.
9039     * @since 3.5
9040     */
9041    public static void swap(final short[] array, final int offset1, final int offset2) {
9042        swap(array, offset1, offset2, 1);
9043    }
9044
9045    /**
9046     * Swaps a series of elements in the given short array.
9047     *
9048     * <p>
9049     * This method does nothing for a {@code null} or empty input array or
9050     * for overflow indices. Negative indices are promoted to 0(zero). If any
9051     * of the sub-arrays to swap falls outside of the given array, then the
9052     * swap is stopped at the end of the array and as many as possible elements
9053     * are swapped.
9054     * </p>
9055     *
9056     * Examples:
9057     * <ul>
9058     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
9059     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
9060     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
9061     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
9062     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
9063     * </ul>
9064     *
9065     * @param array The array to swap, may be {@code null}.
9066     * @param offset1 The index of the first element in the series to swap.
9067     * @param offset2 The index of the second element in the series to swap.
9068     * @param len The number of elements to swap starting with the given indices.
9069     * @since 3.5
9070     */
9071    public static void swap(final short[] array, int offset1, int offset2, int len) {
9072        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
9073            return;
9074        }
9075        offset1 = max0(offset1);
9076        offset2 = max0(offset2);
9077        if (offset1 == offset2) {
9078            return;
9079        }
9080        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
9081        for (int i = 0; i < len; i++, offset1++, offset2++) {
9082            final short aux = array[offset1];
9083            array[offset1] = array[offset2];
9084            array[offset2] = aux;
9085        }
9086    }
9087
9088    /**
9089     * Create a type-safe generic array.
9090     * <p>
9091     * The Java language does not allow an array to be created from a generic type:
9092     * </p>
9093     * <pre>
9094    public static &lt;T&gt; T[] createAnArray(int size) {
9095        return new T[size]; // compiler error here
9096    }
9097    public static &lt;T&gt; T[] createAnArray(int size) {
9098        return (T[]) new Object[size]; // ClassCastException at runtime
9099    }
9100     * </pre>
9101     * <p>
9102     * Therefore new arrays of generic types can be created with this method.
9103     * For example, an array of Strings can be created:
9104     * </p>
9105     * <pre>{@code
9106     * String[] array = ArrayUtils.toArray("1", "2");
9107     * String[] emptyArray = ArrayUtils.<String>toArray();
9108     * }</pre>
9109     * <p>
9110     * The method is typically used in scenarios, where the caller itself uses generic types
9111     * that have to be combined into an array.
9112     * </p>
9113     * <p>
9114     * Note, this method makes only sense to provide arguments of the same type so that the
9115     * compiler can deduce the type of the array itself. While it is possible to select the
9116     * type explicitly like in
9117     * {@code Number[] array = ArrayUtils.<Number>toArray(Integer.valueOf(42), Double.valueOf(Math.PI))},
9118     * there is no real advantage when compared to
9119     * {@code new Number[] {Integer.valueOf(42), Double.valueOf(Math.PI)}}.
9120     * </p>
9121     *
9122     * @param  <T>   the array's element type.
9123     * @param  items  the varargs array items, null allowed.
9124     * @return The array, not null unless a null array is passed in.
9125     * @since 3.0
9126     */
9127    public static <T> T[] toArray(@SuppressWarnings("unchecked") final T... items) {
9128        return items;
9129    }
9130
9131    /**
9132     * Converts the given array into a {@link java.util.Map}. Each element of the array must be either a {@link java.util.Map.Entry} or an Array, containing at
9133     * least two elements, where the first element is used as key and the second as value.
9134     * <p>
9135     * This method can be used to initialize:
9136     * </p>
9137     *
9138     * <pre>
9139     *
9140     * // Create a Map mapping colors.
9141     * Map colorMap = ArrayUtils.toMap(new String[][] { { "RED", "#FF0000" }, { "GREEN", "#00FF00" }, { "BLUE", "#0000FF" } });
9142     * </pre>
9143     * <p>
9144     * This method returns {@code null} for a {@code null} input array.
9145     * </p>
9146     *
9147     * @param array An array whose elements are either a {@link java.util.Map.Entry} or an Array containing at least two elements, may be {@code null}.
9148     * @return A {@link Map} that was created from the array.
9149     * @throws IllegalArgumentException Thrown if one element of this Array is itself an Array containing less than two elements.
9150     * @throws IllegalArgumentException Thrown if the array contains elements other than {@link java.util.Map.Entry} and an Array.
9151     */
9152    public static Map<Object, Object> toMap(final Object[] array) {
9153        if (array == null) {
9154            return null;
9155        }
9156        final Map<Object, Object> map = new HashMap<>((int) (array.length * 1.5));
9157        for (int i = 0; i < array.length; i++) {
9158            final Object object = array[i];
9159            if (object instanceof Map.Entry<?, ?>) {
9160                final Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
9161                map.put(entry.getKey(), entry.getValue());
9162            } else if (object instanceof Object[]) {
9163                final Object[] entry = (Object[]) object;
9164                if (entry.length < 2) {
9165                    throw new IllegalArgumentException("Array element " + i + ", '"
9166                        + object
9167                        + "', has a length less than 2");
9168                }
9169                map.put(entry[0], entry[1]);
9170            } else {
9171                throw new IllegalArgumentException("Array element " + i + ", '"
9172                        + object
9173                        + "', is neither of type Map.Entry nor an Array");
9174            }
9175        }
9176        return map;
9177    }
9178
9179    /**
9180     * Converts an array of primitive booleans to objects.
9181     *
9182     * <p>
9183     * This method returns {@code null} for a {@code null} input array.
9184     * </p>
9185     *
9186     * @param array  A {@code boolean} array.
9187     * @return A {@link Boolean} array, {@code null} if null array input.
9188     */
9189    public static Boolean[] toObject(final boolean[] array) {
9190        if (array == null) {
9191            return null;
9192        }
9193        if (array.length == 0) {
9194            return EMPTY_BOOLEAN_OBJECT_ARRAY;
9195        }
9196        return setAll(new Boolean[array.length], i -> array[i] ? Boolean.TRUE : Boolean.FALSE);
9197    }
9198
9199    /**
9200     * Converts an array of primitive bytes to objects.
9201     *
9202     * <p>
9203     * This method returns {@code null} for a {@code null} input array.
9204     * </p>
9205     *
9206     * @param array  A {@code byte} array.
9207     * @return A {@link Byte} array, {@code null} if null array input.
9208     */
9209    public static Byte[] toObject(final byte[] array) {
9210        if (array == null) {
9211            return null;
9212        }
9213        if (array.length == 0) {
9214            return EMPTY_BYTE_OBJECT_ARRAY;
9215        }
9216        return setAll(new Byte[array.length], i -> Byte.valueOf(array[i]));
9217    }
9218
9219    /**
9220     * Converts an array of primitive chars to objects.
9221     *
9222     * <p>
9223     * This method returns {@code null} for a {@code null} input array.
9224     * </p>
9225     *
9226     * @param array A {@code char} array.
9227     * @return A {@link Character} array, {@code null} if null array input.
9228     */
9229    public static Character[] toObject(final char[] array) {
9230        if (array == null) {
9231            return null;
9232        }
9233        if (array.length == 0) {
9234            return EMPTY_CHARACTER_OBJECT_ARRAY;
9235        }
9236        return setAll(new Character[array.length], i -> Character.valueOf(array[i]));
9237     }
9238
9239    /**
9240     * Converts an array of primitive doubles to objects.
9241     *
9242     * <p>
9243     * This method returns {@code null} for a {@code null} input array.
9244     * </p>
9245     *
9246     * @param array  A {@code double} array.
9247     * @return A {@link Double} array, {@code null} if null array input.
9248     */
9249    public static Double[] toObject(final double[] array) {
9250        if (array == null) {
9251            return null;
9252        }
9253        if (array.length == 0) {
9254            return EMPTY_DOUBLE_OBJECT_ARRAY;
9255        }
9256        return setAll(new Double[array.length], i -> Double.valueOf(array[i]));
9257    }
9258
9259    /**
9260     * Converts an array of primitive floats to objects.
9261     *
9262     * <p>
9263     * This method returns {@code null} for a {@code null} input array.
9264     * </p>
9265     *
9266     * @param array  A {@code float} array.
9267     * @return A {@link Float} array, {@code null} if null array input.
9268     */
9269    public static Float[] toObject(final float[] array) {
9270        if (array == null) {
9271            return null;
9272        }
9273        if (array.length == 0) {
9274            return EMPTY_FLOAT_OBJECT_ARRAY;
9275        }
9276        return setAll(new Float[array.length], i -> Float.valueOf(array[i]));
9277    }
9278
9279    /**
9280     * Converts an array of primitive ints to objects.
9281     *
9282     * <p>
9283     * This method returns {@code null} for a {@code null} input array.
9284     * </p>
9285     *
9286     * @param array  An {@code int} array.
9287     * @return An {@link Integer} array, {@code null} if null array input.
9288     */
9289    public static Integer[] toObject(final int[] array) {
9290        if (array == null) {
9291            return null;
9292        }
9293        if (array.length == 0) {
9294            return EMPTY_INTEGER_OBJECT_ARRAY;
9295        }
9296        return setAll(new Integer[array.length], i -> Integer.valueOf(array[i]));
9297    }
9298
9299    /**
9300     * Converts an array of primitive longs to objects.
9301     *
9302     * <p>
9303     * This method returns {@code null} for a {@code null} input array.
9304     * </p>
9305     *
9306     * @param array  A {@code long} array.
9307     * @return A {@link Long} array, {@code null} if null array input.
9308     */
9309    public static Long[] toObject(final long[] array) {
9310        if (array == null) {
9311            return null;
9312        }
9313        if (array.length == 0) {
9314            return EMPTY_LONG_OBJECT_ARRAY;
9315        }
9316        return setAll(new Long[array.length], i -> Long.valueOf(array[i]));
9317    }
9318
9319    /**
9320     * Converts an array of primitive shorts to objects.
9321     *
9322     * <p>
9323     * This method returns {@code null} for a {@code null} input array.
9324     * </p>
9325     *
9326     * @param array  A {@code short} array.
9327     * @return A {@link Short} array, {@code null} if null array input.
9328     */
9329    public static Short[] toObject(final short[] array) {
9330        if (array == null) {
9331            return null;
9332        }
9333        if (array.length == 0) {
9334            return EMPTY_SHORT_OBJECT_ARRAY;
9335        }
9336        return setAll(new Short[array.length], i -> Short.valueOf(array[i]));
9337    }
9338
9339    /**
9340     * Converts an array of object Booleans to primitives.
9341     * <p>
9342     * This method returns {@code null} for a {@code null} input array.
9343     * </p>
9344     * <p>
9345     * Null array elements map to false, like {@code Boolean.parseBoolean(null)} and its callers return false.
9346     * </p>
9347     *
9348     * @param array A {@link Boolean} array, may be {@code null}.
9349     * @return A {@code boolean} array, {@code null} if null array input.
9350     */
9351    public static boolean[] toPrimitive(final Boolean[] array) {
9352        return toPrimitive(array, false);
9353    }
9354
9355    /**
9356     * Converts an array of object Booleans to primitives handling {@code null}.
9357     * <p>
9358     * This method returns {@code null} for a {@code null} input array.
9359     * </p>
9360     *
9361     * @param array  A {@link Boolean} array, may be {@code null}.
9362     * @param valueForNull  The value to insert if {@code null} found.
9363     * @return A {@code boolean} array, {@code null} if null array input.
9364     */
9365    public static boolean[] toPrimitive(final Boolean[] array, final boolean valueForNull) {
9366        if (array == null) {
9367            return null;
9368        }
9369        if (array.length == 0) {
9370            return EMPTY_BOOLEAN_ARRAY;
9371        }
9372        final boolean[] result = new boolean[array.length];
9373        for (int i = 0; i < array.length; i++) {
9374            final Boolean b = array[i];
9375            result[i] = b == null ? valueForNull : b.booleanValue();
9376        }
9377        return result;
9378    }
9379
9380    /**
9381     * Converts an array of object Bytes to primitives.
9382     * <p>
9383     * This method returns {@code null} for a {@code null} input array.
9384     * </p>
9385     *
9386     * @param array  A {@link Byte} array, may be {@code null}.
9387     * @return A {@code byte} array, {@code null} if null array input.
9388     * @throws NullPointerException Thrown if an array element is {@code null}.
9389     */
9390    public static byte[] toPrimitive(final Byte[] array) {
9391        if (array == null) {
9392            return null;
9393        }
9394        if (array.length == 0) {
9395            return EMPTY_BYTE_ARRAY;
9396        }
9397        final byte[] result = new byte[array.length];
9398        for (int i = 0; i < array.length; i++) {
9399            result[i] = array[i].byteValue();
9400        }
9401        return result;
9402    }
9403
9404    /**
9405     * Converts an array of object Bytes to primitives handling {@code null}.
9406     * <p>
9407     * This method returns {@code null} for a {@code null} input array.
9408     * </p>
9409     *
9410     * @param array  A {@link Byte} array, may be {@code null}.
9411     * @param valueForNull  The value to insert if {@code null} found.
9412     * @return A {@code byte} array, {@code null} if null array input.
9413     */
9414    public static byte[] toPrimitive(final Byte[] array, final byte valueForNull) {
9415        if (array == null) {
9416            return null;
9417        }
9418        if (array.length == 0) {
9419            return EMPTY_BYTE_ARRAY;
9420        }
9421        final byte[] result = new byte[array.length];
9422        for (int i = 0; i < array.length; i++) {
9423            final Byte b = array[i];
9424            result[i] = b == null ? valueForNull : b.byteValue();
9425        }
9426        return result;
9427    }
9428
9429    /**
9430     * Converts an array of object Characters to primitives.
9431     * <p>
9432     * This method returns {@code null} for a {@code null} input array.
9433     * </p>
9434     *
9435     * @param array  A {@link Character} array, may be {@code null}.
9436     * @return A {@code char} array, {@code null} if null array input.
9437     * @throws NullPointerException Thrown if an array element is {@code null}.
9438     */
9439    public static char[] toPrimitive(final Character[] array) {
9440        if (array == null) {
9441            return null;
9442        }
9443        if (array.length == 0) {
9444            return EMPTY_CHAR_ARRAY;
9445        }
9446        final char[] result = new char[array.length];
9447        for (int i = 0; i < array.length; i++) {
9448            result[i] = array[i].charValue();
9449        }
9450        return result;
9451    }
9452
9453    /**
9454     * Converts an array of object Character to primitives handling {@code null}.
9455     * <p>
9456     * This method returns {@code null} for a {@code null} input array.
9457     * </p>
9458     *
9459     * @param array  A {@link Character} array, may be {@code null}.
9460     * @param valueForNull  The value to insert if {@code null} found.
9461     * @return A {@code char} array, {@code null} if null array input.
9462     */
9463    public static char[] toPrimitive(final Character[] array, final char valueForNull) {
9464        if (array == null) {
9465            return null;
9466        }
9467        if (array.length == 0) {
9468            return EMPTY_CHAR_ARRAY;
9469        }
9470        final char[] result = new char[array.length];
9471        for (int i = 0; i < array.length; i++) {
9472            final Character b = array[i];
9473            result[i] = b == null ? valueForNull : b.charValue();
9474        }
9475        return result;
9476    }
9477
9478    /**
9479     * Converts an array of object Doubles to primitives.
9480     * <p>
9481     * This method returns {@code null} for a {@code null} input array.
9482     * </p>
9483     *
9484     * @param array  A {@link Double} array, may be {@code null}.
9485     * @return A {@code double} array, {@code null} if null array input.
9486     * @throws NullPointerException Thrown if an array element is {@code null}.
9487     */
9488    public static double[] toPrimitive(final Double[] array) {
9489        if (array == null) {
9490            return null;
9491        }
9492        if (array.length == 0) {
9493            return EMPTY_DOUBLE_ARRAY;
9494        }
9495        final double[] result = new double[array.length];
9496        for (int i = 0; i < array.length; i++) {
9497            result[i] = array[i].doubleValue();
9498        }
9499        return result;
9500    }
9501
9502    /**
9503     * Converts an array of object Doubles to primitives handling {@code null}.
9504     * <p>
9505     * This method returns {@code null} for a {@code null} input array.
9506     * </p>
9507     *
9508     * @param array  A {@link Double} array, may be {@code null}.
9509     * @param valueForNull  The value to insert if {@code null} found.
9510     * @return A {@code double} array, {@code null} if null array input.
9511     */
9512    public static double[] toPrimitive(final Double[] array, final double valueForNull) {
9513        if (array == null) {
9514            return null;
9515        }
9516        if (array.length == 0) {
9517            return EMPTY_DOUBLE_ARRAY;
9518        }
9519        final double[] result = new double[array.length];
9520        for (int i = 0; i < array.length; i++) {
9521            final Double b = array[i];
9522            result[i] = b == null ? valueForNull : b.doubleValue();
9523        }
9524        return result;
9525    }
9526
9527    /**
9528     * Converts an array of object Floats to primitives.
9529     * <p>
9530     * This method returns {@code null} for a {@code null} input array.
9531     * </p>
9532     *
9533     * @param array  A {@link Float} array, may be {@code null}.
9534     * @return A {@code float} array, {@code null} if null array input.
9535     * @throws NullPointerException Thrown if an array element is {@code null}.
9536     */
9537    public static float[] toPrimitive(final Float[] array) {
9538        if (array == null) {
9539            return null;
9540        }
9541        if (array.length == 0) {
9542            return EMPTY_FLOAT_ARRAY;
9543        }
9544        final float[] result = new float[array.length];
9545        for (int i = 0; i < array.length; i++) {
9546            result[i] = array[i].floatValue();
9547        }
9548        return result;
9549    }
9550
9551    /**
9552     * Converts an array of object Floats to primitives handling {@code null}.
9553     * <p>
9554     * This method returns {@code null} for a {@code null} input array.
9555     * </p>
9556     *
9557     * @param array  A {@link Float} array, may be {@code null}.
9558     * @param valueForNull  The value to insert if {@code null} found.
9559     * @return A {@code float} array, {@code null} if null array input.
9560     */
9561    public static float[] toPrimitive(final Float[] array, final float valueForNull) {
9562        if (array == null) {
9563            return null;
9564        }
9565        if (array.length == 0) {
9566            return EMPTY_FLOAT_ARRAY;
9567        }
9568        final float[] result = new float[array.length];
9569        for (int i = 0; i < array.length; i++) {
9570            final Float b = array[i];
9571            result[i] = b == null ? valueForNull : b.floatValue();
9572        }
9573        return result;
9574    }
9575
9576    /**
9577     * Converts an array of object Integers to primitives.
9578     * <p>
9579     * This method returns {@code null} for a {@code null} input array.
9580     * </p>
9581     *
9582     * @param array  A {@link Integer} array, may be {@code null}.
9583     * @return An {@code int} array, {@code null} if null array input.
9584     * @throws NullPointerException Thrown if an array element is {@code null}.
9585     */
9586    public static int[] toPrimitive(final Integer[] array) {
9587        if (array == null) {
9588            return null;
9589        }
9590        if (array.length == 0) {
9591            return EMPTY_INT_ARRAY;
9592        }
9593        final int[] result = new int[array.length];
9594        for (int i = 0; i < array.length; i++) {
9595            result[i] = array[i].intValue();
9596        }
9597        return result;
9598    }
9599
9600    /**
9601     * Converts an array of object Integer to primitives handling {@code null}.
9602     * <p>
9603     * This method returns {@code null} for a {@code null} input array.
9604     * </p>
9605     *
9606     * @param array  A {@link Integer} array, may be {@code null}.
9607     * @param valueForNull  The value to insert if {@code null} found.
9608     * @return An {@code int} array, {@code null} if null array input.
9609     */
9610    public static int[] toPrimitive(final Integer[] array, final int valueForNull) {
9611        if (array == null) {
9612            return null;
9613        }
9614        if (array.length == 0) {
9615            return EMPTY_INT_ARRAY;
9616        }
9617        final int[] result = new int[array.length];
9618        for (int i = 0; i < array.length; i++) {
9619            final Integer b = array[i];
9620            result[i] = b == null ? valueForNull : b.intValue();
9621        }
9622        return result;
9623    }
9624
9625    /**
9626     * Converts an array of object Longs to primitives.
9627     * <p>
9628     * This method returns {@code null} for a {@code null} input array.
9629     * </p>
9630     *
9631     * @param array  A {@link Long} array, may be {@code null}.
9632     * @return A {@code long} array, {@code null} if null array input.
9633     * @throws NullPointerException Thrown if an array element is {@code null}.
9634     */
9635    public static long[] toPrimitive(final Long[] array) {
9636        if (array == null) {
9637            return null;
9638        }
9639        if (array.length == 0) {
9640            return EMPTY_LONG_ARRAY;
9641        }
9642        final long[] result = new long[array.length];
9643        for (int i = 0; i < array.length; i++) {
9644            result[i] = array[i].longValue();
9645        }
9646        return result;
9647    }
9648
9649    /**
9650     * Converts an array of object Long to primitives handling {@code null}.
9651     * <p>
9652     * This method returns {@code null} for a {@code null} input array.
9653     * </p>
9654     *
9655     * @param array  A {@link Long} array, may be {@code null}.
9656     * @param valueForNull  The value to insert if {@code null} found.
9657     * @return A {@code long} array, {@code null} if null array input.
9658     */
9659    public static long[] toPrimitive(final Long[] array, final long valueForNull) {
9660        if (array == null) {
9661            return null;
9662        }
9663        if (array.length == 0) {
9664            return EMPTY_LONG_ARRAY;
9665        }
9666        final long[] result = new long[array.length];
9667        for (int i = 0; i < array.length; i++) {
9668            final Long b = array[i];
9669            result[i] = b == null ? valueForNull : b.longValue();
9670        }
9671        return result;
9672    }
9673
9674    /**
9675     * Create an array of primitive type from an array of wrapper types.
9676     * <p>
9677     * This method returns {@code null} for a {@code null} input array.
9678     * </p>
9679     *
9680     * @param array  An array of wrapper object.
9681     * @return An array of the corresponding primitive type, or the original array.
9682     * @since 3.5
9683     */
9684    public static Object toPrimitive(final Object array) {
9685        if (array == null) {
9686            return null;
9687        }
9688        final Class<?> ct = array.getClass().getComponentType();
9689        final Class<?> pt = ClassUtils.wrapperToPrimitive(ct);
9690        if (Boolean.TYPE.equals(pt)) {
9691            return toPrimitive((Boolean[]) array);
9692        }
9693        if (Character.TYPE.equals(pt)) {
9694            return toPrimitive((Character[]) array);
9695        }
9696        if (Byte.TYPE.equals(pt)) {
9697            return toPrimitive((Byte[]) array);
9698        }
9699        if (Integer.TYPE.equals(pt)) {
9700            return toPrimitive((Integer[]) array);
9701        }
9702        if (Long.TYPE.equals(pt)) {
9703            return toPrimitive((Long[]) array);
9704        }
9705        if (Short.TYPE.equals(pt)) {
9706            return toPrimitive((Short[]) array);
9707        }
9708        if (Double.TYPE.equals(pt)) {
9709            return toPrimitive((Double[]) array);
9710        }
9711        if (Float.TYPE.equals(pt)) {
9712            return toPrimitive((Float[]) array);
9713        }
9714        return array;
9715    }
9716
9717    /**
9718     * Converts an array of object Shorts to primitives.
9719     * <p>
9720     * This method returns {@code null} for a {@code null} input array.
9721     * </p>
9722     *
9723     * @param array  A {@link Short} array, may be {@code null}.
9724     * @return A {@code byte} array, {@code null} if null array input.
9725     * @throws NullPointerException Thrown if an array element is {@code null}.
9726     */
9727    public static short[] toPrimitive(final Short[] array) {
9728        if (array == null) {
9729            return null;
9730        }
9731        if (array.length == 0) {
9732            return EMPTY_SHORT_ARRAY;
9733        }
9734        final short[] result = new short[array.length];
9735        for (int i = 0; i < array.length; i++) {
9736            result[i] = array[i].shortValue();
9737        }
9738        return result;
9739    }
9740
9741    /**
9742     * Converts an array of object Short to primitives handling {@code null}.
9743     * <p>
9744     * This method returns {@code null} for a {@code null} input array.
9745     * </p>
9746     *
9747     * @param array  A {@link Short} array, may be {@code null}.
9748     * @param valueForNull  The value to insert if {@code null} found.
9749     * @return A {@code byte} array, {@code null} if null array input.
9750     */
9751    public static short[] toPrimitive(final Short[] array, final short valueForNull) {
9752        if (array == null) {
9753            return null;
9754        }
9755        if (array.length == 0) {
9756            return EMPTY_SHORT_ARRAY;
9757        }
9758        final short[] result = new short[array.length];
9759        for (int i = 0; i < array.length; i++) {
9760            final Short b = array[i];
9761            result[i] = b == null ? valueForNull : b.shortValue();
9762        }
9763        return result;
9764    }
9765
9766    /**
9767     * Outputs an array as a String, treating {@code null} as an empty array.
9768     * <p>
9769     * Multi-dimensional arrays are handled correctly, including
9770     * multi-dimensional primitive arrays.
9771     * </p>
9772     * <p>
9773     * The format is that of Java source code, for example {@code {a,b}}.
9774     * </p>
9775     *
9776     * @param array  The array to get a toString for, may be {@code null}.
9777     * @return A String representation of the array, '{}' if null array input.
9778     */
9779    public static String toString(final Object array) {
9780        return toString(array, "{}");
9781    }
9782
9783    /**
9784     * Outputs an array as a String handling {@code null}s.
9785     * <p>
9786     * Multi-dimensional arrays are handled correctly, including
9787     * multi-dimensional primitive arrays.
9788     * </p>
9789     * <p>
9790     * The format is that of Java source code, for example {@code {a,b}}.
9791     * </p>
9792     *
9793     * @param array  The array to get a toString for, may be {@code null}.
9794     * @param stringIfNull  The String to return if the array is {@code null}.
9795     * @return A String representation of the array.
9796     */
9797    public static String toString(final Object array, final String stringIfNull) {
9798        return array != null ? new ToStringBuilder(array, ToStringStyle.SIMPLE_STYLE).append(array).toString() : stringIfNull;
9799    }
9800
9801    /**
9802     * Returns an array containing the string representation of each element in the argument array.
9803     * <p>
9804     * This method returns {@code null} for a {@code null} input array.
9805     * </p>
9806     *
9807     * @param array The {@code Object[]} to be processed, may be {@code null}.
9808     * @return {@code String[]} of the same size as the source with its element's string representation, {@code null} if null array input.
9809     * @since 3.6
9810     */
9811    public static String[] toStringArray(final Object[] array) {
9812        return toStringArray(array, "null");
9813    }
9814
9815    /**
9816     * Returns an array containing the string representation of each element in the argument array handling {@code null} elements.
9817     * <p>
9818     * This method returns {@code null} for a {@code null} input array.
9819     * </p>
9820     *
9821     * @param array                The Object[] to be processed, may be {@code null}.
9822     * @param valueForNullElements The value to insert if {@code null} is found.
9823     * @return A {@link String} array, {@code null} if null array input.
9824     * @since 3.6
9825     */
9826    public static String[] toStringArray(final Object[] array, final String valueForNullElements) {
9827        if (array == null) {
9828            return null;
9829        }
9830        if (array.length == 0) {
9831            return EMPTY_STRING_ARRAY;
9832        }
9833        return map(array, String.class, e -> Objects.toString(e, valueForNullElements));
9834    }
9835
9836    /**
9837     * ArrayUtils instances should NOT be constructed in standard programming. Instead, the class should be used as {@code ArrayUtils.clone(new int[] {2})}.
9838     * <p>
9839     * This constructor is public to permit tools that require a JavaBean instance to operate.
9840     * </p>
9841     *
9842     * @deprecated TODO Make private in 4.0.
9843     */
9844    @Deprecated
9845    public ArrayUtils() {
9846        // empty
9847    }
9848}