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 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 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 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 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 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 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 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 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 if the index is out of range (index &lt; 0 || index &gt; array.length).
791     * @throws IllegalArgumentException 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 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     * @since 2.1
873     */
874    public static boolean[] addAll(final boolean[] array1, final boolean... array2) {
875        if (array1 == null) {
876            return clone(array2);
877        }
878        if (array2 == null) {
879            return clone(array1);
880        }
881        final boolean[] joinedArray = new boolean[array1.length + array2.length];
882        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
883        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
884        return joinedArray;
885    }
886
887    /**
888     * Adds all the elements of the given arrays into a new array.
889     * <p>
890     * The new array contains all of the element of {@code array1} followed
891     * by all of the elements {@code array2}. When an array is returned, it is always
892     * a new array.
893     * </p>
894     * <pre>
895     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
896     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
897     * ArrayUtils.addAll([], [])         = []
898     * ArrayUtils.addAll(null, null)     = null
899     * </pre>
900     *
901     * @param array1  the first array whose elements are added to the new array.
902     * @param array2  the second array whose elements are added to the new array.
903     * @return The new byte[] array or {@code null}.
904     * @since 2.1
905     */
906    public static byte[] addAll(final byte[] array1, final byte... array2) {
907        if (array1 == null) {
908            return clone(array2);
909        }
910        if (array2 == null) {
911            return clone(array1);
912        }
913        final byte[] joinedArray = new byte[array1.length + array2.length];
914        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
915        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
916        return joinedArray;
917    }
918
919    /**
920     * Adds all the elements of the given arrays into a new array.
921     * <p>
922     * The new array contains all of the element of {@code array1} followed
923     * by all of the elements {@code array2}. When an array is returned, it is always
924     * a new array.
925     * </p>
926     * <pre>
927     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
928     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
929     * ArrayUtils.addAll([], [])         = []
930     * ArrayUtils.addAll(null, null)     = null
931     * </pre>
932     *
933     * @param array1  the first array whose elements are added to the new array.
934     * @param array2  the second array whose elements are added to the new array.
935     * @return The new char[] array or {@code null}.
936     * @since 2.1
937     */
938    public static char[] addAll(final char[] array1, final char... array2) {
939        if (array1 == null) {
940            return clone(array2);
941        }
942        if (array2 == null) {
943            return clone(array1);
944        }
945        final char[] joinedArray = new char[array1.length + array2.length];
946        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
947        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
948        return joinedArray;
949    }
950
951    /**
952     * Adds all the elements of the given arrays into a new array.
953     * <p>
954     * The new array contains all of the element of {@code array1} followed
955     * by all of the elements {@code array2}. When an array is returned, it is always
956     * a new array.
957     * </p>
958     * <pre>
959     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
960     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
961     * ArrayUtils.addAll([], [])         = []
962     * ArrayUtils.addAll(null, null)     = null
963     * </pre>
964     *
965     * @param array1  the first array whose elements are added to the new array.
966     * @param array2  the second array whose elements are added to the new array.
967     * @return The new double[] array or {@code null}.
968     * @since 2.1
969     */
970    public static double[] addAll(final double[] array1, final double... array2) {
971        if (array1 == null) {
972            return clone(array2);
973        }
974        if (array2 == null) {
975            return clone(array1);
976        }
977        final double[] joinedArray = new double[array1.length + array2.length];
978        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
979        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
980        return joinedArray;
981    }
982
983    /**
984     * Adds all the elements of the given arrays into a new array.
985     * <p>
986     * The new array contains all of the element of {@code array1} followed
987     * by all of the elements {@code array2}. When an array is returned, it is always
988     * a new array.
989     * </p>
990     * <pre>
991     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
992     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
993     * ArrayUtils.addAll([], [])         = []
994     * ArrayUtils.addAll(null, null)     = null
995     * </pre>
996     *
997     * @param array1  the first array whose elements are added to the new array.
998     * @param array2  the second array whose elements are added to the new array.
999     * @return The new float[] array or {@code null}.
1000     * @since 2.1
1001     */
1002    public static float[] addAll(final float[] array1, final float... array2) {
1003        if (array1 == null) {
1004            return clone(array2);
1005        }
1006        if (array2 == null) {
1007            return clone(array1);
1008        }
1009        final float[] joinedArray = new float[array1.length + array2.length];
1010        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1011        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1012        return joinedArray;
1013    }
1014
1015    /**
1016     * Adds all the elements of the given arrays into a new array.
1017     * <p>
1018     * The new array contains all of the element of {@code array1} followed
1019     * by all of the elements {@code array2}. When an array is returned, it is always
1020     * a new array.
1021     * </p>
1022     * <pre>
1023     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1024     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1025     * ArrayUtils.addAll([], [])         = []
1026     * ArrayUtils.addAll(null, null)     = null
1027     * </pre>
1028     *
1029     * @param array1  the first array whose elements are added to the new array.
1030     * @param array2  the second array whose elements are added to the new array.
1031     * @return The new int[] array or {@code null}.
1032     * @since 2.1
1033     */
1034    public static int[] addAll(final int[] array1, final int... array2) {
1035        if (array1 == null) {
1036            return clone(array2);
1037        }
1038        if (array2 == null) {
1039            return clone(array1);
1040        }
1041        final int[] joinedArray = new int[array1.length + array2.length];
1042        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1043        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1044        return joinedArray;
1045    }
1046
1047    /**
1048     * Adds all the elements of the given arrays into a new array.
1049     * <p>
1050     * The new array contains all of the element of {@code array1} followed
1051     * by all of the elements {@code array2}. When an array is returned, it is always
1052     * a new array.
1053     * </p>
1054     * <pre>
1055     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1056     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1057     * ArrayUtils.addAll([], [])         = []
1058     * ArrayUtils.addAll(null, null)     = null
1059     * </pre>
1060     *
1061     * @param array1  the first array whose elements are added to the new array.
1062     * @param array2  the second array whose elements are added to the new array.
1063     * @return The new long[] array or {@code null}.
1064     * @since 2.1
1065     */
1066    public static long[] addAll(final long[] array1, final long... array2) {
1067        if (array1 == null) {
1068            return clone(array2);
1069        }
1070        if (array2 == null) {
1071            return clone(array1);
1072        }
1073        final long[] joinedArray = new long[array1.length + array2.length];
1074        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1075        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1076        return joinedArray;
1077    }
1078
1079    /**
1080     * Adds all the elements of the given arrays into a new array.
1081     * <p>
1082     * The new array contains all of the element of {@code array1} followed
1083     * by all of the elements {@code array2}. When an array is returned, it is always
1084     * a new array.
1085     * </p>
1086     * <pre>
1087     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1088     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1089     * ArrayUtils.addAll([], [])         = []
1090     * ArrayUtils.addAll(null, null)     = null
1091     * </pre>
1092     *
1093     * @param array1  the first array whose elements are added to the new array.
1094     * @param array2  the second array whose elements are added to the new array.
1095     * @return The new short[] array or {@code null}.
1096     * @since 2.1
1097     */
1098    public static short[] addAll(final short[] array1, final short... array2) {
1099        if (array1 == null) {
1100            return clone(array2);
1101        }
1102        if (array2 == null) {
1103            return clone(array1);
1104        }
1105        final short[] joinedArray = new short[array1.length + array2.length];
1106        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1107        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1108        return joinedArray;
1109    }
1110
1111    /**
1112     * Adds all the elements of the given arrays into a new array.
1113     * <p>
1114     * The new array contains all of the element of {@code array1} followed
1115     * by all of the elements {@code array2}. When an array is returned, it is always
1116     * a new array.
1117     * </p>
1118     * <pre>
1119     * ArrayUtils.addAll(null, null)     = null
1120     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1121     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1122     * ArrayUtils.addAll([], [])         = []
1123     * ArrayUtils.addAll(null, null)     = null
1124     * ArrayUtils.addAll([null], [null]) = [null, null]
1125     * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
1126     * </pre>
1127     *
1128     * @param <T> the component type of the array.
1129     * @param array1  the first array whose elements are added to the new array, may be {@code null}.
1130     * @param array2  the second array whose elements are added to the new array, may be {@code null}.
1131     * @return The new array, {@code null} if both arrays are {@code null}.
1132     *      The type of the new array is the type of the first array,
1133     *      unless the first array is null, in which case the type is the same as the second array.
1134     * @throws IllegalArgumentException if the array types are incompatible.
1135     * @since 2.1
1136     */
1137    public static <T> T[] addAll(final T[] array1, @SuppressWarnings("unchecked") final T... array2) {
1138        if (array1 == null) {
1139            return clone(array2);
1140        }
1141        if (array2 == null) {
1142            return clone(array1);
1143        }
1144        final Class<T> type1 = getComponentType(array1);
1145        final T[] joinedArray = arraycopy(array1, 0, 0, array1.length, () -> newInstance(type1, array1.length + array2.length));
1146        try {
1147            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1148        } catch (final ArrayStoreException ase) {
1149            // Check if problem was due to incompatible types
1150            /*
1151             * 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
1152             * strict
1153             */
1154            final Class<?> type2 = array2.getClass().getComponentType();
1155            if (!type1.isAssignableFrom(type2)) {
1156                throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of " + type1.getName(), ase);
1157            }
1158            throw ase; // No, so rethrow original
1159        }
1160        return joinedArray;
1161    }
1162
1163    /**
1164     * Safely adds the length of an array to a running total, checking for overflow.
1165     *
1166     * @param totalLength the current accumulated length
1167     * @param array the array whose length should be added (can be {@code null},
1168     *              in which case its length is considered 0)
1169     * @return the new total length after adding the array's length
1170     * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1171     */
1172    private static int addExact(final int totalLength, final Object array) {
1173        try {
1174            final int length = MathBridge.addExact(totalLength, getLength(array));
1175            if (length > SAFE_MAX_ARRAY_LENGTH) {
1176                throw new IllegalArgumentException("Total arrays length exceed " + SAFE_MAX_ARRAY_LENGTH);
1177            }
1178            return length;
1179        } catch (final ArithmeticException exception) {
1180            throw new IllegalArgumentException("Total arrays length exceed " + SAFE_MAX_ARRAY_LENGTH);
1181        }
1182    }
1183
1184    /**
1185     * Copies the given array and adds the given element at the beginning of the new array.
1186     * <p>
1187     * The new array contains the same elements of the input array plus the given element in the first position. The
1188     * component type of the new array is the same as that of the input array.
1189     * </p>
1190     * <p>
1191     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1192     * element.
1193     * </p>
1194     * <pre>
1195     * ArrayUtils.addFirst(null, true)          = [true]
1196     * ArrayUtils.addFirst([true], false)       = [false, true]
1197     * ArrayUtils.addFirst([true, false], true) = [true, true, false]
1198     * </pre>
1199     *
1200     * @param array the array to "add" the element to, may be {@code null}.
1201     * @param element the object to add.
1202     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1203     *         the input array (unless null), in which case it will have the same type as the element.
1204     * @since 3.10
1205     */
1206    public static boolean[] addFirst(final boolean[] array, final boolean element) {
1207        return array == null ? add(array, element) : insert(0, array, element);
1208    }
1209
1210    /**
1211     * Copies the given array and adds the given element at the beginning of the new array.
1212     * <p>
1213     * The new array contains the same elements of the input array plus the given element in the first position. The
1214     * component type of the new array is the same as that of the input array.
1215     * </p>
1216     * <p>
1217     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1218     * element.
1219     * </p>
1220     * <pre>
1221     * ArrayUtils.addFirst(null, 1)   = [1]
1222     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1223     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1224     * </pre>
1225     *
1226     * @param array the array to "add" the element to, may be {@code null}.
1227     * @param element the object to add.
1228     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1229     *         the input array (unless null), in which case it will have the same type as the element.
1230     * @since 3.10
1231     */
1232    public static byte[] addFirst(final byte[] array, final byte element) {
1233        return array == null ? add(array, element) : insert(0, array, element);
1234    }
1235
1236    /**
1237     * Copies the given array and adds the given element at the beginning of the new array.
1238     * <p>
1239     * The new array contains the same elements of the input array plus the given element in the first position. The
1240     * component type of the new array is the same as that of the input array.
1241     * </p>
1242     * <p>
1243     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1244     * element.
1245     * </p>
1246     * <pre>
1247     * ArrayUtils.addFirst(null, '1')       = ['1']
1248     * ArrayUtils.addFirst(['1'], '0')      = ['0', '1']
1249     * ArrayUtils.addFirst(['1', '0'], '1') = ['1', '1', '0']
1250     * </pre>
1251     *
1252     * @param array the array to "add" the element to, may be {@code null}.
1253     * @param element the object to add.
1254     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1255     *         the input array (unless null), in which case it will have the same type as the element.
1256     * @since 3.10
1257     */
1258    public static char[] addFirst(final char[] array, final char element) {
1259        return array == null ? add(array, element) : insert(0, array, element);
1260    }
1261
1262    /**
1263     * Copies the given array and adds the given element at the beginning of the new array.
1264     * <p>
1265     * The new array contains the same elements of the input array plus the given element in the first position. The
1266     * component type of the new array is the same as that of the input array.
1267     * </p>
1268     * <p>
1269     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1270     * element.
1271     * </p>
1272     * <pre>
1273     * ArrayUtils.addFirst(null, 1)   = [1]
1274     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1275     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1276     * </pre>
1277     *
1278     * @param array the array to "add" the element to, may be {@code null}.
1279     * @param element the object to add.
1280     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1281     *         the input array (unless null), in which case it will have the same type as the element.
1282     * @since 3.10
1283     */
1284    public static double[] addFirst(final double[] array, final double element) {
1285        return array == null ? add(array, element) : insert(0, array, element);
1286    }
1287
1288    /**
1289     * Copies the given array and adds the given element at the beginning of the new array.
1290     * <p>
1291     * The new array contains the same elements of the input array plus the given element in the first position. The
1292     * component type of the new array is the same as that of the input array.
1293     * </p>
1294     * <p>
1295     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1296     * element.
1297     * </p>
1298     * <pre>
1299     * ArrayUtils.addFirst(null, 1)   = [1]
1300     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1301     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1302     * </pre>
1303     *
1304     * @param array the array to "add" the element to, may be {@code null}.
1305     * @param element the object to add.
1306     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1307     *         the input array (unless null), in which case it will have the same type as the element.
1308     * @since 3.10
1309     */
1310    public static float[] addFirst(final float[] array, final float element) {
1311        return array == null ? add(array, element) : insert(0, array, element);
1312    }
1313
1314    /**
1315     * Copies the given array and adds the given element at the beginning of the new array.
1316     * <p>
1317     * The new array contains the same elements of the input array plus the given element in the first position. The
1318     * component type of the new array is the same as that of the input array.
1319     * </p>
1320     * <p>
1321     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1322     * element.
1323     * </p>
1324     * <pre>
1325     * ArrayUtils.addFirst(null, 1)   = [1]
1326     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1327     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1328     * </pre>
1329     *
1330     * @param array the array to "add" the element to, may be {@code null}.
1331     * @param element the object to add.
1332     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1333     *         the input array (unless null), in which case it will have the same type as the element.
1334     * @since 3.10
1335     */
1336    public static int[] addFirst(final int[] array, final int element) {
1337        return array == null ? add(array, element) : insert(0, array, element);
1338    }
1339
1340    /**
1341     * Copies the given array and adds the given element at the beginning of the new array.
1342     * <p>
1343     * The new array contains the same elements of the input array plus the given element in the first position. The
1344     * component type of the new array is the same as that of the input array.
1345     * </p>
1346     * <p>
1347     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1348     * element.
1349     * </p>
1350     * <pre>
1351     * ArrayUtils.addFirst(null, 1)   = [1]
1352     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1353     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1354     * </pre>
1355     *
1356     * @param array the array to "add" the element to, may be {@code null}.
1357     * @param element the object to add.
1358     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1359     *         the input array (unless null), in which case it will have the same type as the element.
1360     * @since 3.10
1361     */
1362    public static long[] addFirst(final long[] array, final long element) {
1363        return array == null ? add(array, element) : insert(0, array, element);
1364    }
1365
1366    /**
1367     * Copies the given array and adds the given element at the beginning of the new array.
1368     * <p>
1369     * The new array contains the same elements of the input array plus the given element in the first position. The
1370     * component type of the new array is the same as that of the input array.
1371     * </p>
1372     * <p>
1373     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1374     * element.
1375     * </p>
1376     * <pre>
1377     * ArrayUtils.addFirst(null, 1)   = [1]
1378     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1379     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1380     * </pre>
1381     *
1382     * @param array the array to "add" the element to, may be {@code null}.
1383     * @param element the object to add.
1384     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1385     *         the input array (unless null), in which case it will have the same type as the element.
1386     * @since 3.10
1387     */
1388    public static short[] addFirst(final short[] array, final short element) {
1389        return array == null ? add(array, element) : insert(0, array, element);
1390    }
1391
1392    /**
1393     * Copies the given array and adds the given element at the beginning of the new array.
1394     * <p>
1395     * The new array contains the same elements of the input array plus the given element in the first position. The
1396     * component type of the new array is the same as that of the input array.
1397     * </p>
1398     * <p>
1399     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1400     * element, unless the element itself is null, in which case the return type is Object[]
1401     * </p>
1402     * <pre>
1403     * ArrayUtils.addFirst(null, null)      = Throws {@link IllegalArgumentException}
1404     * ArrayUtils.addFirst(null, "a")       = ["a"]
1405     * ArrayUtils.addFirst(["a"], null)     = [null, "a"]
1406     * ArrayUtils.addFirst(["a"], "b")      = ["b", "a"]
1407     * ArrayUtils.addFirst(["a", "b"], "c") = ["c", "a", "b"]
1408     * </pre>
1409     *
1410     * @param <T> the component type of the array.
1411     * @param array the array to "add" the element to, may be {@code null}.
1412     * @param element the object to add, may be {@code null}.
1413     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1414     *         the input array (unless null), in which case it will have the same type as the element. If both are null,
1415     *         an IllegalArgumentException is thrown.
1416     * @throws IllegalArgumentException if both arguments are null.
1417     * @since 3.10
1418     */
1419    public static <T> T[] addFirst(final T[] array, final T element) {
1420        return array == null ? add(array, element) : insert(0, array, element);
1421    }
1422
1423    /**
1424     * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array.
1425     *
1426     * @param <T>       the type.
1427     * @param source    the source array.
1428     * @param sourcePos starting position in the source array.
1429     * @param destPos   starting position in the destination data.
1430     * @param length    the number of array elements to be copied.
1431     * @param allocator allocates the array to populate and return.
1432     * @return dest
1433     * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds.
1434     * @throws ArrayStoreException       if an element in the {@code src} array could not be stored into the {@code dest} array because of a type
1435     *                                   mismatch.
1436     * @throws NullPointerException      if either {@code src} or {@code dest} is {@code null}.
1437     * @since 3.15.0
1438     */
1439    public static <T> T arraycopy(final T source, final int sourcePos, final int destPos, final int length, final Function<Integer, T> allocator) {
1440        return arraycopy(source, sourcePos, allocator.apply(length), destPos, length);
1441    }
1442
1443    /**
1444     * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array.
1445     *
1446     * @param <T>       the type.
1447     * @param source    the source array.
1448     * @param sourcePos starting position in the source array.
1449     * @param destPos   starting position in the destination data.
1450     * @param length    the number of array elements to be copied.
1451     * @param allocator allocates the array to populate and return.
1452     * @return dest
1453     * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds.
1454     * @throws ArrayStoreException       if an element in the {@code src} array could not be stored into the {@code dest} array because of a type
1455     *                                   mismatch.
1456     * @throws NullPointerException      if either {@code src} or {@code dest} is {@code null}.
1457     * @since 3.15.0
1458     */
1459    public static <T> T arraycopy(final T source, final int sourcePos, final int destPos, final int length, final Supplier<T> allocator) {
1460        return arraycopy(source, sourcePos, allocator.get(), destPos, length);
1461    }
1462
1463    /**
1464     * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array.
1465     *
1466     * @param <T>       the type.
1467     * @param source    the source array.
1468     * @param sourcePos starting position in the source array.
1469     * @param dest      the destination array.
1470     * @param destPos   starting position in the destination data.
1471     * @param length    the number of array elements to be copied.
1472     * @return dest
1473     * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds.
1474     * @throws ArrayStoreException       if an element in the {@code src} array could not be stored into the {@code dest} array because of a type
1475     *                                   mismatch.
1476     * @throws NullPointerException      if either {@code src} or {@code dest} is {@code null}.
1477     * @since 3.15.0
1478     */
1479    public static <T> T arraycopy(final T source, final int sourcePos, final T dest, final int destPos, final int length) {
1480        System.arraycopy(source, sourcePos, dest, destPos, length);
1481        return dest;
1482    }
1483
1484    /**
1485     * Clones an array or returns {@code null}.
1486     * <p>
1487     * This method returns {@code null} for a {@code null} input array.
1488     * </p>
1489     *
1490     * @param array the array to clone, may be {@code null}.
1491     * @return the cloned array, {@code null} if {@code null} input.
1492     */
1493    public static boolean[] clone(final boolean[] array) {
1494        return array != null ? array.clone() : null;
1495    }
1496
1497    /**
1498     * Clones an array or returns {@code null}.
1499     * <p>
1500     * This method returns {@code null} for a {@code null} input array.
1501     * </p>
1502     *
1503     * @param array the array to clone, may be {@code null}.
1504     * @return the cloned array, {@code null} if {@code null} input.
1505     */
1506    public static byte[] clone(final byte[] array) {
1507        return array != null ? array.clone() : null;
1508    }
1509
1510    /**
1511     * Clones an array or returns {@code null}.
1512     * <p>
1513     * This method returns {@code null} for a {@code null} input array.
1514     * </p>
1515     *
1516     * @param array the array to clone, may be {@code null}.
1517     * @return the cloned array, {@code null} if {@code null} input.
1518     */
1519    public static char[] clone(final char[] array) {
1520        return array != null ? array.clone() : null;
1521    }
1522
1523    /**
1524     * Clones an array or returns {@code null}.
1525     * <p>
1526     * This method returns {@code null} for a {@code null} input array.
1527     * </p>
1528     *
1529     * @param array the array to clone, may be {@code null}.
1530     * @return the cloned array, {@code null} if {@code null} input.
1531     */
1532    public static double[] clone(final double[] array) {
1533        return array != null ? array.clone() : null;
1534    }
1535
1536    /**
1537     * Clones an array or returns {@code null}.
1538     * <p>
1539     * This method returns {@code null} for a {@code null} input array.
1540     * </p>
1541     *
1542     * @param array the array to clone, may be {@code null}.
1543     * @return the cloned array, {@code null} if {@code null} input.
1544     */
1545    public static float[] clone(final float[] array) {
1546        return array != null ? array.clone() : null;
1547    }
1548
1549    /**
1550     * Clones an array or returns {@code null}.
1551     * <p>
1552     * This method returns {@code null} for a {@code null} input array.
1553     * </p>
1554     *
1555     * @param array the array to clone, may be {@code null}.
1556     * @return the cloned array, {@code null} if {@code null} input.
1557     */
1558    public static int[] clone(final int[] array) {
1559        return array != null ? array.clone() : null;
1560    }
1561
1562    /**
1563     * Clones an array or returns {@code null}.
1564     * <p>
1565     * This method returns {@code null} for a {@code null} input array.
1566     * </p>
1567     *
1568     * @param array the array to clone, may be {@code null}.
1569     * @return the cloned array, {@code null} if {@code null} input.
1570     */
1571    public static long[] clone(final long[] array) {
1572        return array != null ? array.clone() : null;
1573    }
1574
1575    /**
1576     * Clones an array or returns {@code null}.
1577     * <p>
1578     * This method returns {@code null} for a {@code null} input array.
1579     * </p>
1580     *
1581     * @param array the array to clone, may be {@code null}.
1582     * @return the cloned array, {@code null} if {@code null} input.
1583     */
1584    public static short[] clone(final short[] array) {
1585        return array != null ? array.clone() : null;
1586    }
1587
1588    /**
1589     * Shallow clones an array or returns {@code null}.
1590     * <p>
1591     * The objects in the array are not cloned, thus there is no special handling for multi-dimensional arrays.
1592     * </p>
1593     * <p>
1594     * This method returns {@code null} for a {@code null} input array.
1595     * </p>
1596     *
1597     * @param <T>   the component type of the array.
1598     * @param array the array to shallow clone, may be {@code null}.
1599     * @return the cloned array, {@code null} if {@code null} input.
1600     */
1601    public static <T> T[] clone(final T[] array) {
1602        return array != null ? array.clone() : null;
1603    }
1604
1605    /**
1606     * Concatenates multiple boolean arrays into a single array.
1607     * <p>
1608     * This method combines all input arrays in the order they are provided,
1609     * creating a new array that contains all elements from the input arrays.
1610     * The resulting array length is the sum of lengths of all non-null input arrays.
1611     * </p>
1612     *
1613     * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1614     *               or be null itself (treated as empty varargs).
1615     * @return a new boolean array containing all elements from the input arrays
1616     *         in the order they appear, or an empty array if no elements are present.
1617     * @throws NullPointerException if the input array of arrays is null.
1618     * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1619     * @since 3.21.0
1620     */
1621    public static boolean[] concat(boolean[]... arrays) {
1622        int totalLength = 0;
1623        for (boolean[] array : arrays) {
1624            totalLength = addExact(totalLength, array);
1625        }
1626        final boolean[] result = new boolean[totalLength];
1627        int currentPos = 0;
1628        for (boolean[] array : arrays) {
1629            if (array != null && array.length > 0) {
1630                System.arraycopy(array, 0, result, currentPos, array.length);
1631                currentPos += array.length;
1632            }
1633        }
1634        return result;
1635    }
1636
1637    /**
1638     * Concatenates multiple byte arrays into a single array.
1639     * <p>
1640     * This method combines all input arrays in the order they are provided,
1641     * creating a new array that contains all elements from the input arrays.
1642     * The resulting array length is the sum of lengths of all non-null input arrays.
1643     * </p>
1644     *
1645     * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1646     *               or be null itself (treated as empty varargs).
1647     * @return a new byte array containing all elements from the input arrays
1648     *         in the order they appear, or an empty array if no elements are present.
1649     * @throws NullPointerException if the input array of arrays is null.
1650     * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1651     * @since 3.21.0
1652     */
1653    public static byte[] concat(byte[]... arrays) {
1654        int totalLength = 0;
1655        for (byte[] array : arrays) {
1656            totalLength = addExact(totalLength, array);
1657        }
1658        final byte[] result = new byte[totalLength];
1659        int currentPos = 0;
1660        for (byte[] array : arrays) {
1661            if (array != null && array.length > 0) {
1662                System.arraycopy(array, 0, result, currentPos, array.length);
1663                currentPos += array.length;
1664            }
1665        }
1666        return result;
1667    }
1668
1669    /**
1670     * Concatenates multiple char arrays into a single array.
1671     * <p>
1672     * This method combines all input arrays in the order they are provided,
1673     * creating a new array that contains all elements from the input arrays.
1674     * The resulting array length is the sum of lengths of all non-null input arrays.
1675     * </p>
1676     *
1677     * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1678     *               or be null itself (treated as empty varargs).
1679     * @return a new char array containing all elements from the input arrays
1680     *         in the order they appear, or an empty array if no elements are present.
1681     * @throws NullPointerException if the input array of arrays is null.
1682     * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1683     * @since 3.21.0
1684     */
1685    public static char[] concat(char[]... arrays) {
1686        int totalLength = 0;
1687        for (char[] array : arrays) {
1688            totalLength = addExact(totalLength, array);
1689        }
1690        final char[] result = new char[totalLength];
1691        int currentPos = 0;
1692        for (char[] array : arrays) {
1693            if (array != null && array.length > 0) {
1694                System.arraycopy(array, 0, result, currentPos, array.length);
1695                currentPos += array.length;
1696            }
1697        }
1698        return result;
1699    }
1700
1701    /**
1702     * Concatenates multiple double arrays into a single array.
1703     * <p>
1704     * This method combines all input arrays in the order they are provided,
1705     * creating a new array that contains all elements from the input arrays.
1706     * The resulting array length is the sum of lengths of all non-null input arrays.
1707     * </p>
1708     *
1709     * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1710     *               or be null itself (treated as empty varargs).
1711     * @return a new double array containing all elements from the input arrays
1712     *         in the order they appear, or an empty array if no elements are present.
1713     * @throws NullPointerException if the input array of arrays is null.
1714     * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1715     * @since 3.21.0
1716     */
1717    public static double[] concat(double[]... arrays) {
1718        int totalLength = 0;
1719        for (double[] array : arrays) {
1720            totalLength = addExact(totalLength, array);
1721        }
1722        final double[] result = new double[totalLength];
1723        int currentPos = 0;
1724        for (double[] array : arrays) {
1725            if (array != null && array.length > 0) {
1726                System.arraycopy(array, 0, result, currentPos, array.length);
1727                currentPos += array.length;
1728            }
1729        }
1730        return result;
1731    }
1732
1733    /**
1734     * Concatenates multiple float arrays into a single array.
1735     * <p>
1736     * This method combines all input arrays in the order they are provided,
1737     * creating a new array that contains all elements from the input arrays.
1738     * The resulting array length is the sum of lengths of all non-null input arrays.
1739     * </p>
1740     *
1741     * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1742     *               or be null itself (treated as empty varargs).
1743     * @return a new float array containing all elements from the input arrays
1744     *         in the order they appear, or an empty array if no elements are present.
1745     * @throws NullPointerException if the input array of arrays is null.
1746     * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1747     * @since 3.21.0
1748     */
1749    public static float[] concat(float[]... arrays) {
1750        int totalLength = 0;
1751        for (float[] array : arrays) {
1752            totalLength = addExact(totalLength, array);
1753        }
1754        final float[] result = new float[totalLength];
1755        int currentPos = 0;
1756        for (float[] array : arrays) {
1757            if (array != null && array.length > 0) {
1758                System.arraycopy(array, 0, result, currentPos, array.length);
1759                currentPos += array.length;
1760            }
1761        }
1762        return result;
1763    }
1764
1765    /**
1766     * Concatenates multiple int arrays into a single array.
1767     * <p>
1768     * This method combines all input arrays in the order they are provided,
1769     * creating a new array that contains all elements from the input arrays.
1770     * The resulting array length is the sum of lengths of all non-null input arrays.
1771     * </p>
1772     *
1773     * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1774     *               or be null itself (treated as empty varargs).
1775     * @return a new int array containing all elements from the input arrays
1776     *         in the order they appear, or an empty array if no elements are present.
1777     * @throws NullPointerException if the input array of arrays is null.
1778     * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1779     * @since 3.21.0
1780     */
1781    public static int[] concat(int[]... arrays) {
1782        int totalLength = 0;
1783        for (int[] array : arrays) {
1784            totalLength = addExact(totalLength, array);
1785        }
1786        final int[] result = new int[totalLength];
1787        int currentPos = 0;
1788        for (int[] array : arrays) {
1789            if (array != null && array.length > 0) {
1790                System.arraycopy(array, 0, result, currentPos, array.length);
1791                currentPos += array.length;
1792            }
1793        }
1794        return result;
1795    }
1796
1797    /**
1798     * Concatenates multiple long arrays into a single array.
1799     * <p>
1800     * This method combines all input arrays in the order they are provided,
1801     * creating a new array that contains all elements from the input arrays.
1802     * The resulting array length is the sum of lengths of all non-null input arrays.
1803     * </p>
1804     *
1805     * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1806     *               or be null itself (treated as empty varargs).
1807     * @return a new long array containing all elements from the input arrays
1808     *         in the order they appear, or an empty array if no elements are present.
1809     * @throws NullPointerException if the input array of arrays is null.
1810     * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1811     * @since 3.21.0
1812     */
1813    public static long[] concat(long[]... arrays) {
1814        int totalLength = 0;
1815        for (long[] array : arrays) {
1816            totalLength = addExact(totalLength, array);
1817        }
1818        final long[] result = new long[totalLength];
1819        int currentPos = 0;
1820        for (long[] array : arrays) {
1821            if (array != null && array.length > 0) {
1822                System.arraycopy(array, 0, result, currentPos, array.length);
1823                currentPos += array.length;
1824            }
1825        }
1826        return result;
1827    }
1828
1829    /**
1830     * Concatenates multiple short arrays into a single array.
1831     * <p>
1832     * This method combines all input arrays in the order they are provided,
1833     * creating a new array that contains all elements from the input arrays.
1834     * The resulting array length is the sum of lengths of all non-null input arrays.
1835     * </p>
1836     *
1837     * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1838     *               or be null itself (treated as empty varargs).
1839     * @return a new short array containing all elements from the input arrays
1840     *         in the order they appear, or an empty array if no elements are present.
1841     * @throws NullPointerException if the input array of arrays is null.
1842     * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1843     * @since 3.21.0
1844     */
1845    public static short[] concat(short[]... arrays) {
1846        int totalLength = 0;
1847        for (short[] array : arrays) {
1848            totalLength = addExact(totalLength, array);
1849        }
1850        final short[] result = new short[totalLength];
1851        int currentPos = 0;
1852        for (short[] array : arrays) {
1853            if (array != null && array.length > 0) {
1854                System.arraycopy(array, 0, result, currentPos, array.length);
1855                currentPos += array.length;
1856            }
1857        }
1858        return result;
1859    }
1860
1861    /**
1862     * Checks if the value is in the given array.
1863     * <p>
1864     * The method returns {@code false} if a {@code null} array is passed in.
1865     * </p>
1866     *
1867     * @param array  the array to search.
1868     * @param valueToFind  the value to find.
1869     * @return {@code true} if the array contains the object.
1870     */
1871    public static boolean contains(final boolean[] array, final boolean valueToFind) {
1872        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1873    }
1874
1875    /**
1876     * Checks if the value is in the given array.
1877     * <p>
1878     * The method returns {@code false} if a {@code null} array is passed in.
1879     * </p>
1880     * <p>
1881     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1882     * {@link Arrays#sort(byte[])} and {@link Arrays#binarySearch(byte[], byte)}.
1883     * </p>
1884     *
1885     * @param array  the array to search.
1886     * @param valueToFind  the value to find.
1887     * @return {@code true} if the array contains the object.
1888     */
1889    public static boolean contains(final byte[] array, final byte valueToFind) {
1890        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1891    }
1892
1893    /**
1894     * Checks if the value is in the given array.
1895     * <p>
1896     * The method returns {@code false} if a {@code null} array is passed in.
1897     * </p>
1898     * <p>
1899     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1900     * {@link Arrays#sort(char[])} and {@link Arrays#binarySearch(char[], char)}.
1901     * </p>
1902     *
1903     * @param array  the array to search.
1904     * @param valueToFind  the value to find.
1905     * @return {@code true} if the array contains the object.
1906     * @since 2.1
1907     */
1908    public static boolean contains(final char[] array, final char valueToFind) {
1909        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1910    }
1911
1912    /**
1913     * Checks if the value is in the given array.
1914     * <p>
1915     * The method returns {@code false} if a {@code null} array is passed in.
1916     * </p>
1917     * <p>
1918     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1919     * {@link Arrays#sort(double[])} and {@link Arrays#binarySearch(double[], double)}.
1920     * </p>
1921     *
1922     * @param array  the array to search.
1923     * @param valueToFind  the value to find.
1924     * @return {@code true} if the array contains the object.
1925     */
1926    public static boolean contains(final double[] array, final double valueToFind) {
1927        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1928    }
1929
1930    /**
1931     * Checks if a value falling within the given tolerance is in the
1932     * given array.  If the array contains a value within the inclusive range
1933     * defined by (value - tolerance) to (value + tolerance).
1934     * <p>
1935     * The method returns {@code false} if a {@code null} array
1936     * is passed in.
1937     * </p>
1938     * <p>
1939     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1940     * {@link Arrays#sort(double[])} and {@link Arrays#binarySearch(double[], double)}.
1941     * </p>
1942     *
1943     * @param array  the array to search.
1944     * @param valueToFind  the value to find.
1945     * @param tolerance  the array contains the tolerance of the search.
1946     * @return true if value falling within tolerance is in array.
1947     */
1948    public static boolean contains(final double[] array, final double valueToFind, final double tolerance) {
1949        return indexOf(array, valueToFind, 0, tolerance) != INDEX_NOT_FOUND;
1950    }
1951
1952    /**
1953     * Checks if the value is in the given array.
1954     * <p>
1955     * The method returns {@code false} if a {@code null} array is passed in.
1956     * </p>
1957     * <p>
1958     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1959     * {@link Arrays#sort(float[])} and {@link Arrays#binarySearch(float[], float)}.
1960     * </p>
1961     *
1962     * @param array  the array to search.
1963     * @param valueToFind  the value to find.
1964     * @return {@code true} if the array contains the object.
1965     */
1966    public static boolean contains(final float[] array, final float valueToFind) {
1967        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1968    }
1969
1970    /**
1971     * Checks if the value is in the given array.
1972     * <p>
1973     * The method returns {@code false} if a {@code null} array is passed in.
1974     * </p>
1975     * <p>
1976     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1977     * {@link Arrays#sort(int[])} and {@link Arrays#binarySearch(int[], int)}.
1978     * </p>
1979     *
1980     * @param array  the array to search.
1981     * @param valueToFind  the value to find.
1982     * @return {@code true} if the array contains the object.
1983     */
1984    public static boolean contains(final int[] array, final int valueToFind) {
1985        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1986    }
1987
1988    /**
1989     * Checks if the value is in the given array.
1990     * <p>
1991     * The method returns {@code false} if a {@code null} array is passed in.
1992     * </p>
1993     * <p>
1994     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1995     * {@link Arrays#sort(long[])} and {@link Arrays#binarySearch(long[], long)}.
1996     * </p>
1997     *
1998     * @param array  the array to search.
1999     * @param valueToFind  the value to find.
2000     * @return {@code true} if the array contains the object.
2001     */
2002    public static boolean contains(final long[] array, final long valueToFind) {
2003        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2004    }
2005
2006    /**
2007     * Checks if the object is in the given array.
2008     * <p>
2009     * The method returns {@code false} if a {@code null} array is passed in.
2010     * </p>
2011     * <p>
2012     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
2013     * {@link Arrays#sort(Object[], Comparator)} and {@link Arrays#binarySearch(Object[], Object)}.
2014     * </p>
2015     *
2016     * @param array  the array to search, may be {@code null}.
2017     * @param objectToFind  the object to find, may be {@code null}.
2018     * @return {@code true} if the array contains the object.
2019     */
2020    public static boolean contains(final Object[] array, final Object objectToFind) {
2021        return indexOf(array, objectToFind) != INDEX_NOT_FOUND;
2022    }
2023
2024    /**
2025     * Checks if the value is in the given array.
2026     * <p>
2027     * The method returns {@code false} if a {@code null} array is passed in.
2028     * </p>
2029     * <p>
2030     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
2031     * {@link Arrays#sort(short[])} and {@link Arrays#binarySearch(short[], short)}.
2032     * </p>
2033     *
2034     * @param array  the array to search.
2035     * @param valueToFind  the value to find.
2036     * @return {@code true} if the array contains the object.
2037     */
2038    public static boolean contains(final short[] array, final short valueToFind) {
2039        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2040    }
2041
2042    /**
2043     * Checks if any of the ints are in the given array.
2044     * <p>
2045     * The method returns {@code false} if a {@code null} array is passed in.
2046     * </p>
2047     * <p>
2048     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
2049     * {@link Arrays#sort(int[])} and {@link Arrays#binarySearch(int[], int)}.
2050     * </p>
2051     *
2052     * @param array         the array to search.
2053     * @param objectsToFind any of the ints to find.
2054     * @return {@code true} if the array contains any of the ints.
2055     * @since 3.18.0
2056     */
2057    public static boolean containsAny(final int[] array, final int... objectsToFind) {
2058        return IntStreams.of(objectsToFind).anyMatch(e -> contains(array, e));
2059    }
2060
2061    /**
2062     * Checks if any of the objects are in the given array.
2063     * <p>
2064     * The method returns {@code false} if a {@code null} array is passed in.
2065     * </p>
2066     * <p>
2067     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
2068     * {@link Arrays#sort(Object[], Comparator)} and {@link Arrays#binarySearch(Object[], Object)}.
2069     * </p>
2070     *
2071     * @param array         the array to search, may be {@code null}.
2072     * @param objectsToFind any of the objects to find, may be {@code null}.
2073     * @return {@code true} if the array contains any of the objects.
2074     * @since 3.13.0
2075     */
2076    public static boolean containsAny(final Object[] array, final Object... objectsToFind) {
2077        return Streams.of(objectsToFind).anyMatch(e -> contains(array, e));
2078    }
2079
2080    /**
2081     * Returns a copy of the given array of size 1 greater than the argument.
2082     * The last value of the array is left to the default value.
2083     *
2084     * @param array The array to copy, must not be {@code null}.
2085     * @param newArrayComponentType If {@code array} is {@code null}, create a
2086     * size 1 array of this type.
2087     * @return A new copy of the array of size 1 greater than the input.
2088     */
2089    private static Object copyArrayGrow1(final Object array, final Class<?> newArrayComponentType) {
2090        if (array != null) {
2091            final int arrayLength = Array.getLength(array);
2092            final Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
2093            System.arraycopy(array, 0, newArray, 0, arrayLength);
2094            return newArray;
2095        }
2096        return Array.newInstance(newArrayComponentType, 1);
2097    }
2098
2099    /**
2100     * Gets the nTh element of an array or null if the index is out of bounds or the array is null.
2101     *
2102     * @param <T> The type of array elements.
2103     * @param array The array to index.
2104     * @param index The index.
2105     * @return the nTh element of an array or null if the index is out of bounds or the array is null.
2106     * @since 3.11
2107     */
2108    public static <T> T get(final T[] array, final int index) {
2109        return get(array, index, null);
2110    }
2111
2112    /**
2113     * Gets the nTh element of an array or a default value if the index is out of bounds.
2114     *
2115     * @param <T> The type of array elements.
2116     * @param array The array to index.
2117     * @param index The index.
2118     * @param defaultValue The return value of the given index is out of bounds.
2119     * @return the nTh element of an array or a default value if the index is out of bounds.
2120     * @since 3.11
2121     */
2122    public static <T> T get(final T[] array, final int index, final T defaultValue) {
2123        return isArrayIndexValid(array, index) ? array[index] : defaultValue;
2124    }
2125
2126    /**
2127     * Gets an array's component type.
2128     *
2129     * @param <T> The array type.
2130     * @param array The array.
2131     * @return The component type.
2132     * @since 3.13.0
2133     */
2134    public static <T> Class<T> getComponentType(final T[] array) {
2135        return ClassUtils.getComponentType(ObjectUtils.getClass(array));
2136    }
2137
2138    /**
2139     * Gets the number of dimensions of an array.
2140     * <p>
2141     * 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.
2142     * </p>
2143     *
2144     * @param array the array, may be {@code null}.
2145     * @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.
2146     * @since 3.21.0
2147     * @see <a href="https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.3">JVM specification Field Descriptors</a>
2148     */
2149    public static int getDimensions(final Object array) {
2150        int dimensions = 0;
2151        if (array != null) {
2152            Class<?> arrayClass = array.getClass();
2153            while (arrayClass.isArray()) {
2154                dimensions++;
2155                arrayClass = arrayClass.getComponentType();
2156            }
2157        }
2158        return dimensions;
2159    }
2160
2161    /**
2162     * Gets the length of the specified array.
2163     * This method handles {@link Object} arrays and primitive arrays.
2164     * <p>
2165     * If the input array is {@code null}, {@code 0} is returned.
2166     * </p>
2167     * <pre>
2168     * ArrayUtils.getLength(null)            = 0
2169     * ArrayUtils.getLength([])              = 0
2170     * ArrayUtils.getLength([null])          = 1
2171     * ArrayUtils.getLength([true, false])   = 2
2172     * ArrayUtils.getLength([1, 2, 3])       = 3
2173     * ArrayUtils.getLength(["a", "b", "c"]) = 3
2174     * </pre>
2175     *
2176     * @param array  the array to retrieve the length from, may be {@code null}.
2177     * @return The length of the array, or {@code 0} if the array is {@code null}.
2178     * @throws IllegalArgumentException if the object argument is not an array.
2179     * @since 2.1
2180     */
2181    public static int getLength(final Object array) {
2182        return array != null ? Array.getLength(array) : 0;
2183    }
2184
2185    /**
2186     * Gets a hash code for an array handling multidimensional arrays correctly.
2187     * <p>
2188     * Multi-dimensional primitive arrays are also handled correctly by this method.
2189     * </p>
2190     *
2191     * @param array  the array to get a hash code for, {@code null} returns zero.
2192     * @return a hash code for the array.
2193     */
2194    public static int hashCode(final Object array) {
2195        return new HashCodeBuilder().append(array).toHashCode();
2196    }
2197
2198    static <K> void increment(final Map<K, MutableInt> occurrences, final K boxed) {
2199        occurrences.computeIfAbsent(boxed, k -> new MutableInt()).increment();
2200    }
2201
2202    /**
2203     * Finds the indices of the given value in the array.
2204     * <p>
2205     * This method returns an empty BitSet for a {@code null} input array.
2206     * </p>
2207     *
2208     * @param array  the array to search for the object, may be {@code null}.
2209     * @param valueToFind  the value to find.
2210     * @return a BitSet of all the indices of the value within the array,
2211     *  an empty BitSet if not found or {@code null} array input.
2212     * @since 3.10
2213     */
2214    public static BitSet indexesOf(final boolean[] array, final boolean valueToFind) {
2215        return indexesOf(array, valueToFind, 0);
2216    }
2217
2218    /**
2219     * Finds the indices of the given value in the array starting at the given index.
2220     * <p>
2221     * This method returns an empty BitSet for a {@code null} input array.
2222     * </p>
2223     * <p>
2224     * A negative startIndex is treated as zero. A startIndex larger than the array length will return an empty BitSet ({@code -1}).
2225     * </p>
2226     *
2227     * @param array       the array to search for the object, may be {@code null}.
2228     * @param valueToFind the value to find.
2229     * @param startIndex  the index to start searching.
2230     * @return a BitSet of all the indices of the value within the array, an empty BitSet if not found or {@code null} array input.
2231     * @since 3.10
2232     */
2233    public static BitSet indexesOf(final boolean[] array, final boolean valueToFind, int startIndex) {
2234        final BitSet bitSet = new BitSet();
2235        if (array != null) {
2236            while (startIndex < array.length) {
2237                startIndex = indexOf(array, valueToFind, startIndex);
2238                if (startIndex == INDEX_NOT_FOUND) {
2239                    break;
2240                }
2241                bitSet.set(startIndex);
2242                ++startIndex;
2243            }
2244        }
2245        return bitSet;
2246    }
2247
2248    /**
2249     * Finds the indices of the given value in the array.
2250     *
2251     * <p>
2252     * This method returns an empty BitSet for a {@code null} input array.
2253     * </p>
2254     *
2255     * @param array       the array to search for the object, may be {@code null}.
2256     * @param valueToFind the value to find.
2257     * @return a BitSet of all the indices of the value within the array, an empty BitSet if not found or {@code null} array input.
2258     * @since 3.10
2259     */
2260    public static BitSet indexesOf(final byte[] array, final byte valueToFind) {
2261        return indexesOf(array, valueToFind, 0);
2262    }
2263
2264    /**
2265     * Finds the indices of the given value in the array starting at the given index.
2266     *
2267     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2268     *
2269     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2270     * length will return an empty BitSet.</p>
2271     *
2272     * @param array  the array to search for the object, may be {@code null}.
2273     * @param valueToFind  the value to find.
2274     * @param startIndex  the index to start searching.
2275     * @return a BitSet of all the indices of the value within the array,
2276     *  an empty BitSet if not found or {@code null} array input.
2277     * @since 3.10
2278     */
2279    public static BitSet indexesOf(final byte[] array, final byte valueToFind, int startIndex) {
2280        final BitSet bitSet = new BitSet();
2281        if (array != null) {
2282            while (startIndex < array.length) {
2283                startIndex = indexOf(array, valueToFind, startIndex);
2284                if (startIndex == INDEX_NOT_FOUND) {
2285                    break;
2286                }
2287                bitSet.set(startIndex);
2288                ++startIndex;
2289            }
2290        }
2291        return bitSet;
2292    }
2293
2294    /**
2295     * Finds the indices of the given value in the array.
2296     *
2297     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2298     *
2299     * @param array  the array to search for the object, may be {@code null}.
2300     * @param valueToFind  the value to find.
2301     * @return a BitSet of all the indices of the value within the array,
2302     *  an empty BitSet if not found or {@code null} array input.
2303     * @since 3.10
2304     */
2305    public static BitSet indexesOf(final char[] array, final char valueToFind) {
2306        return indexesOf(array, valueToFind, 0);
2307    }
2308
2309    /**
2310     * Finds the indices of the given value in the array starting at the given index.
2311     *
2312     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2313     *
2314     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2315     * length will return an empty BitSet.</p>
2316     *
2317     * @param array  the array to search for the object, may be {@code null}.
2318     * @param valueToFind  the value to find.
2319     * @param startIndex  the index to start searching.
2320     * @return a BitSet of all the indices of the value within the array,
2321     *  an empty BitSet if not found or {@code null} array input.
2322     * @since 3.10
2323     */
2324    public static BitSet indexesOf(final char[] array, final char valueToFind, int startIndex) {
2325        final BitSet bitSet = new BitSet();
2326        if (array != null) {
2327            while (startIndex < array.length) {
2328                startIndex = indexOf(array, valueToFind, startIndex);
2329                if (startIndex == INDEX_NOT_FOUND) {
2330                    break;
2331                }
2332                bitSet.set(startIndex);
2333                ++startIndex;
2334            }
2335        }
2336        return bitSet;
2337    }
2338
2339    /**
2340     * Finds the indices of the given value in the array.
2341     *
2342     * <p>This method returns empty BitSet for a {@code null} input array.</p>
2343     *
2344     * @param array  the array to search for the object, may be {@code null}.
2345     * @param valueToFind  the value to find.
2346     * @return a BitSet of all the indices of the value within the array,
2347     *  an empty BitSet if not found or {@code null} array input.
2348     * @since 3.10
2349     */
2350    public static BitSet indexesOf(final double[] array, final double valueToFind) {
2351        return indexesOf(array, valueToFind, 0);
2352    }
2353
2354    /**
2355     * Finds the indices of the given value within a given tolerance in the array.
2356     *
2357     * <p>
2358     * This method will return all the indices of the value which fall between the region
2359     * defined by valueToFind - tolerance and valueToFind + tolerance, each time between the nearest integers.
2360     * </p>
2361     *
2362     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2363     *
2364     * @param array  the array to search for the object, may be {@code null}.
2365     * @param valueToFind  the value to find.
2366     * @param tolerance tolerance of the search.
2367     * @return a BitSet of all the indices of the value within the array,
2368     *  an empty BitSet if not found or {@code null} array input.
2369     * @since 3.10
2370     */
2371    public static BitSet indexesOf(final double[] array, final double valueToFind, final double tolerance) {
2372        return indexesOf(array, valueToFind, 0, tolerance);
2373    }
2374
2375    /**
2376     * Finds the indices of the given value in the array starting at the given index.
2377     *
2378     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2379     *
2380     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2381     * length will return an empty BitSet.</p>
2382     *
2383     * @param array  the array to search for the object, may be {@code null}.
2384     * @param valueToFind  the value to find.
2385     * @param startIndex  the index to start searching.
2386     * @return a BitSet of the indices of the value within the array,
2387     *  an empty BitSet if not found or {@code null} array input.
2388     * @since 3.10
2389     */
2390    public static BitSet indexesOf(final double[] array, final double valueToFind, int startIndex) {
2391        final BitSet bitSet = new BitSet();
2392        if (array != null) {
2393            while (startIndex < array.length) {
2394                startIndex = indexOf(array, valueToFind, startIndex);
2395                if (startIndex == INDEX_NOT_FOUND) {
2396                    break;
2397                }
2398                bitSet.set(startIndex);
2399                ++startIndex;
2400            }
2401        }
2402        return bitSet;
2403    }
2404
2405    /**
2406     * Finds the indices of the given value in the array starting at the given index.
2407     *
2408     * <p>
2409     * This method will return the indices of the values which fall between the region
2410     * defined by valueToFind - tolerance and valueToFind + tolerance, between the nearest integers.
2411     * </p>
2412     *
2413     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2414     *
2415     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2416     * length will return an empty BitSet.</p>
2417     *
2418     * @param array  the array to search for the object, may be {@code null}.
2419     * @param valueToFind  the value to find.
2420     * @param startIndex  the index to start searching.
2421     * @param tolerance tolerance of the search.
2422     * @return a BitSet of the indices of the value within the array,
2423     *  an empty BitSet if not found or {@code null} array input.
2424     * @since 3.10
2425     */
2426    public static BitSet indexesOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
2427        final BitSet bitSet = new BitSet();
2428        if (array != null) {
2429            while (startIndex < array.length) {
2430                startIndex = indexOf(array, valueToFind, startIndex, tolerance);
2431                if (startIndex == INDEX_NOT_FOUND) {
2432                    break;
2433                }
2434                bitSet.set(startIndex);
2435                ++startIndex;
2436            }
2437        }
2438        return bitSet;
2439    }
2440
2441    /**
2442     * Finds the indices of the given value in the array.
2443     *
2444     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2445     *
2446     * @param array  the array to search for the object, may be {@code null}.
2447     * @param valueToFind  the value to find.
2448     * @return a BitSet of all the indices of the value within the array,
2449     *  an empty BitSet if not found or {@code null} array input.
2450     * @since 3.10
2451     */
2452    public static BitSet indexesOf(final float[] array, final float valueToFind) {
2453        return indexesOf(array, valueToFind, 0);
2454    }
2455
2456    /**
2457     * Finds the indices of the given value in the array starting at the given index.
2458     *
2459     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2460     *
2461     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2462     * length will return empty BitSet.</p>
2463     *
2464     * @param array  the array to search for the object, may be {@code null}.
2465     * @param valueToFind  the value to find.
2466     * @param startIndex  the index to start searching.
2467     * @return a BitSet of all the indices of the value within the array,
2468     *  an empty BitSet if not found or {@code null} array input.
2469     * @since 3.10
2470     */
2471    public static BitSet indexesOf(final float[] array, final float valueToFind, int startIndex) {
2472        final BitSet bitSet = new BitSet();
2473        if (array != null) {
2474            while (startIndex < array.length) {
2475                startIndex = indexOf(array, valueToFind, startIndex);
2476                if (startIndex == INDEX_NOT_FOUND) {
2477                    break;
2478                }
2479                bitSet.set(startIndex);
2480                ++startIndex;
2481            }
2482        }
2483        return bitSet;
2484    }
2485
2486    /**
2487     * Finds the indices of the given value in the array.
2488     *
2489     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2490     *
2491     * @param array  the array to search for the object, may be {@code null}.
2492     * @param valueToFind  the value to find.
2493     * @return a BitSet of all the indices of the value within the array,
2494     *  an empty BitSet if not found or {@code null} array input.
2495     * @since 3.10
2496     */
2497    public static BitSet indexesOf(final int[] array, final int valueToFind) {
2498        return indexesOf(array, valueToFind, 0);
2499    }
2500
2501    /**
2502     * Finds the indices of the given value in the array starting at the given index.
2503     *
2504     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2505     *
2506     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2507     * length will return an empty BitSet.</p>
2508     *
2509     * @param array  the array to search for the object, may be {@code null}.
2510     * @param valueToFind  the value to find.
2511     * @param startIndex  the index to start searching.
2512     * @return a BitSet of all the indices of the value within the array,
2513     *  an empty BitSet if not found or {@code null} array input.
2514     * @since 3.10
2515     */
2516    public static BitSet indexesOf(final int[] array, final int valueToFind, int startIndex) {
2517        final BitSet bitSet = new BitSet();
2518        if (array != null) {
2519            while (startIndex < array.length) {
2520                startIndex = indexOf(array, valueToFind, startIndex);
2521                if (startIndex == INDEX_NOT_FOUND) {
2522                    break;
2523                }
2524                bitSet.set(startIndex);
2525                ++startIndex;
2526            }
2527        }
2528        return bitSet;
2529    }
2530
2531    /**
2532     * Finds the indices of the given value in the array.
2533     *
2534     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2535     *
2536     * @param array  the array to search for the object, may be {@code null}.
2537     * @param valueToFind  the value to find.
2538     * @return a BitSet of all the indices of the value within the array,
2539     *  an empty BitSet if not found or {@code null} array input.
2540     * @since 3.10
2541     */
2542    public static BitSet indexesOf(final long[] array, final long valueToFind) {
2543        return indexesOf(array, valueToFind, 0);
2544    }
2545
2546    /**
2547     * Finds the indices of the given value in the array starting at the given index.
2548     *
2549     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2550     *
2551     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2552     * length will return an empty BitSet.</p>
2553     *
2554     * @param array  the array to search for the object, may be {@code null}.
2555     * @param valueToFind  the value to find.
2556     * @param startIndex  the index to start searching.
2557     * @return a BitSet of all the indices of the value within the array,
2558     *  an empty BitSet if not found or {@code null} array input.
2559     * @since 3.10
2560     */
2561    public static BitSet indexesOf(final long[] array, final long valueToFind, int startIndex) {
2562        final BitSet bitSet = new BitSet();
2563        if (array != null) {
2564            while (startIndex < array.length) {
2565                startIndex = indexOf(array, valueToFind, startIndex);
2566                if (startIndex == INDEX_NOT_FOUND) {
2567                    break;
2568                }
2569                bitSet.set(startIndex);
2570                ++startIndex;
2571            }
2572        }
2573        return bitSet;
2574    }
2575
2576    /**
2577     * Finds the indices of the given object in the array.
2578     *
2579     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2580     *
2581     * @param array  the array to search for the object, may be {@code null}.
2582     * @param objectToFind  the object to find, may be {@code null}.
2583     * @return a BitSet of all the indices of the object within the array,
2584     *  an empty BitSet if not found or {@code null} array input.
2585     * @since 3.10
2586     */
2587    public static BitSet indexesOf(final Object[] array, final Object objectToFind) {
2588        return indexesOf(array, objectToFind, 0);
2589    }
2590
2591    /**
2592     * Finds the indices of the given object in the array starting at the given index.
2593     *
2594     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2595     *
2596     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2597     * length will return an empty BitSet.</p>
2598     *
2599     * @param array  the array to search for the object, may be {@code null}.
2600     * @param objectToFind  the object to find, may be {@code null}.
2601     * @param startIndex  the index to start searching.
2602     * @return a BitSet of all the indices of the object within the array starting at the index,
2603     *  an empty BitSet if not found or {@code null} array input.
2604     * @since 3.10
2605     */
2606    public static BitSet indexesOf(final Object[] array, final Object objectToFind, int startIndex) {
2607        final BitSet bitSet = new BitSet();
2608        if (array != null) {
2609            while (startIndex < array.length) {
2610                startIndex = indexOf(array, objectToFind, startIndex);
2611                if (startIndex == INDEX_NOT_FOUND) {
2612                    break;
2613                }
2614                bitSet.set(startIndex);
2615                ++startIndex;
2616            }
2617        }
2618        return bitSet;
2619    }
2620
2621    /**
2622     * Finds the indices of the given value in the array.
2623     *
2624     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2625     *
2626     * @param array  the array to search for the object, may be {@code null}.
2627     * @param valueToFind  the value to find.
2628     * @return a BitSet of all the indices of the value within the array,
2629     *  an empty BitSet if not found or {@code null} array input.
2630     * @since 3.10
2631     */
2632    public static BitSet indexesOf(final short[] array, final short valueToFind) {
2633        return indexesOf(array, valueToFind, 0);
2634    }
2635
2636    /**
2637     * Finds the indices of the given value in the array starting at the given index.
2638     *
2639     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2640     *
2641     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2642     * length will return an empty BitSet.</p>
2643     *
2644     * @param array  the array to search for the object, may be {@code null}.
2645     * @param valueToFind  the value to find.
2646     * @param startIndex  the index to start searching.
2647     * @return a BitSet of all the indices of the value within the array,
2648     *  an empty BitSet if not found or {@code null} array input.
2649     * @since 3.10
2650     */
2651    public static BitSet indexesOf(final short[] array, final short valueToFind, int startIndex) {
2652        final BitSet bitSet = new BitSet();
2653        if (array != null) {
2654            while (startIndex < array.length) {
2655                startIndex = indexOf(array, valueToFind, startIndex);
2656                if (startIndex == INDEX_NOT_FOUND) {
2657                    break;
2658                }
2659                bitSet.set(startIndex);
2660                ++startIndex;
2661            }
2662        }
2663        return bitSet;
2664    }
2665
2666    /**
2667     * Finds the index of the given value in the array.
2668     * <p>
2669     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2670     * </p>
2671     *
2672     * @param array       the array to search for the object, may be {@code null}.
2673     * @param valueToFind the value to find.
2674     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2675     */
2676    public static int indexOf(final boolean[] array, final boolean valueToFind) {
2677        return indexOf(array, valueToFind, 0);
2678    }
2679
2680    /**
2681     * Finds the index of the given value in the array starting at the given index.
2682     * <p>
2683     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2684     * </p>
2685     * <p>
2686     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2687     * </p>
2688     *
2689     * @param array       the array to search for the object, may be {@code null}.
2690     * @param valueToFind the value to find.
2691     * @param startIndex  the index to start searching.
2692     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2693     */
2694    public static int indexOf(final boolean[] array, final boolean valueToFind, final int startIndex) {
2695        if (isEmpty(array)) {
2696            return INDEX_NOT_FOUND;
2697        }
2698        for (int i = max0(startIndex); i < array.length; i++) {
2699            if (valueToFind == array[i]) {
2700                return i;
2701            }
2702        }
2703        return INDEX_NOT_FOUND;
2704    }
2705
2706    /**
2707     * Finds the index of the given value in the array.
2708     * <p>
2709     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2710     * </p>
2711     *
2712     * @param array       the array to search for the object, may be {@code null}.
2713     * @param valueToFind the value to find.
2714     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2715     */
2716    public static int indexOf(final byte[] array, final byte valueToFind) {
2717        return indexOf(array, valueToFind, 0);
2718    }
2719
2720    /**
2721     * Finds the index of the given value in the array starting at the given index.
2722     * <p>
2723     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2724     * </p>
2725     * <p>
2726     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2727     * </p>
2728     *
2729     * @param array       the array to search for the object, may be {@code null}.
2730     * @param valueToFind the value to find.
2731     * @param startIndex  the index to start searching.
2732     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2733     */
2734    public static int indexOf(final byte[] array, final byte valueToFind, final int startIndex) {
2735        if (isEmpty(array)) {
2736            return INDEX_NOT_FOUND;
2737        }
2738        for (int i = max0(startIndex); i < array.length; i++) {
2739            if (valueToFind == array[i]) {
2740                return i;
2741            }
2742        }
2743        return INDEX_NOT_FOUND;
2744    }
2745
2746    /**
2747     * Finds the index of the given value in the array.
2748     * <p>
2749     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2750     * </p>
2751     *
2752     * @param array       the array to search for the object, may be {@code null}.
2753     * @param valueToFind the value to find.
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     * @since 2.1
2756     */
2757    public static int indexOf(final char[] array, final char valueToFind) {
2758        return indexOf(array, valueToFind, 0);
2759    }
2760
2761    /**
2762     * Finds the index of the given value in the array starting at the given index.
2763     * <p>
2764     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2765     * </p>
2766     * <p>
2767     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2768     * </p>
2769     *
2770     * @param array       the array to search for the object, may be {@code null}.
2771     * @param valueToFind the value to find.
2772     * @param startIndex  the index to start searching.
2773     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2774     * @since 2.1
2775     */
2776    public static int indexOf(final char[] array, final char valueToFind, final int startIndex) {
2777        if (isEmpty(array)) {
2778            return INDEX_NOT_FOUND;
2779        }
2780        for (int i = max0(startIndex); i < array.length; i++) {
2781            if (valueToFind == array[i]) {
2782                return i;
2783            }
2784        }
2785        return INDEX_NOT_FOUND;
2786    }
2787
2788    /**
2789     * Finds the index of the given value in the array.
2790     * <p>
2791     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2792     * </p>
2793     *
2794     * @param array       the array to search for the object, may be {@code null}.
2795     * @param valueToFind the value to find.
2796     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2797     */
2798    public static int indexOf(final double[] array, final double valueToFind) {
2799        return indexOf(array, valueToFind, 0);
2800    }
2801
2802    /**
2803     * 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
2804     * region defined by valueToFind - tolerance and valueToFind + tolerance.
2805     * <p>
2806     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2807     * </p>
2808     *
2809     * @param array       the array to search for the object, may be {@code null}.
2810     * @param valueToFind the value to find.
2811     * @param tolerance   tolerance of the search.
2812     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2813     */
2814    public static int indexOf(final double[] array, final double valueToFind, final double tolerance) {
2815        return indexOf(array, valueToFind, 0, tolerance);
2816    }
2817
2818    /**
2819     * Finds the index of the given value in the array starting at the given index.
2820     * <p>
2821     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2822     * </p>
2823     * <p>
2824     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2825     * </p>
2826     *
2827     * @param array       the array to search for the object, may be {@code null}.
2828     * @param valueToFind the value to find.
2829     * @param startIndex  the index to start searching.
2830     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2831     */
2832    public static int indexOf(final double[] array, final double valueToFind, final int startIndex) {
2833        if (Double.isNaN(valueToFind)) {
2834            return indexOfNaN(array, startIndex);
2835        }
2836        if (isEmpty(array)) {
2837            return INDEX_NOT_FOUND;
2838        }
2839        for (int i = max0(startIndex); i < array.length; i++) {
2840            if (valueToFind == array[i]) {
2841                return i;
2842            }
2843        }
2844        return INDEX_NOT_FOUND;
2845    }
2846
2847    /**
2848     * 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
2849     * region defined by valueToFind - tolerance and valueToFind + tolerance.
2850     * <p>
2851     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2852     * </p>
2853     * <p>
2854     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2855     * </p>
2856     *
2857     * @param array       the array to search for the object, may be {@code null}.
2858     * @param valueToFind the value to find.
2859     * @param startIndex  the index to start searching.
2860     * @param tolerance   tolerance of the search.
2861     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2862     */
2863    public static int indexOf(final double[] array, final double valueToFind, final int startIndex, final double tolerance) {
2864        if (Double.isNaN(valueToFind)) {
2865            return indexOfNaN(array, startIndex);
2866        }
2867        if (isEmpty(array)) {
2868            return INDEX_NOT_FOUND;
2869        }
2870        final double min = valueToFind - tolerance;
2871        final double max = valueToFind + tolerance;
2872        for (int i = max0(startIndex); i < array.length; i++) {
2873            if (array[i] >= min && array[i] <= max) {
2874                return i;
2875            }
2876        }
2877        return INDEX_NOT_FOUND;
2878    }
2879
2880    /**
2881     * Finds the index of the given value in the array.
2882     * <p>
2883     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2884     * </p>
2885     *
2886     * @param array       the array to search for the object, may be {@code null}.
2887     * @param valueToFind the value to find.
2888     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2889     */
2890    public static int indexOf(final float[] array, final float valueToFind) {
2891        return indexOf(array, valueToFind, 0);
2892    }
2893
2894    /**
2895     * Finds the index of the given value in the array starting at the given index.
2896     * <p>
2897     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2898     * </p>
2899     * <p>
2900     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2901     * </p>
2902     *
2903     * @param array       the array to search for the object, may be {@code null}.
2904     * @param valueToFind the value to find.
2905     * @param startIndex  the index to start searching.
2906     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2907     */
2908    public static int indexOf(final float[] array, final float valueToFind, final int startIndex) {
2909        if (isEmpty(array)) {
2910            return INDEX_NOT_FOUND;
2911        }
2912        final boolean searchNaN = Float.isNaN(valueToFind);
2913        for (int i = max0(startIndex); i < array.length; i++) {
2914            final float element = array[i];
2915            if (valueToFind == element || searchNaN && Float.isNaN(element)) {
2916                return i;
2917            }
2918        }
2919        return INDEX_NOT_FOUND;
2920    }
2921
2922    /**
2923     * Finds the index of the given value in the array.
2924     * <p>
2925     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2926     * </p>
2927     *
2928     * @param array       the array to search for the object, may be {@code null}.
2929     * @param valueToFind the value to find.
2930     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2931     */
2932    public static int indexOf(final int[] array, final int valueToFind) {
2933        return indexOf(array, valueToFind, 0);
2934    }
2935
2936    /**
2937     * Finds the index of the given value in the array starting at the given index.
2938     * <p>
2939     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2940     * </p>
2941     * <p>
2942     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2943     * </p>
2944     *
2945     * @param array       the array to search for the object, may be {@code null}.
2946     * @param valueToFind the value to find.
2947     * @param startIndex  the index to start searching.
2948     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2949     */
2950    public static int indexOf(final int[] array, final int valueToFind, final int startIndex) {
2951        if (isEmpty(array)) {
2952            return INDEX_NOT_FOUND;
2953        }
2954        for (int i = max0(startIndex); i < array.length; i++) {
2955            if (valueToFind == array[i]) {
2956                return i;
2957            }
2958        }
2959        return INDEX_NOT_FOUND;
2960    }
2961
2962    /**
2963     * Finds the index of the given value in the array.
2964     * <p>
2965     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2966     * </p>
2967     *
2968     * @param array       the array to search for the object, may be {@code null}.
2969     * @param valueToFind the value to find.
2970     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2971     */
2972    public static int indexOf(final long[] array, final long valueToFind) {
2973        return indexOf(array, valueToFind, 0);
2974    }
2975
2976    /**
2977     * Finds the index of the given value in the array starting at the given index.
2978     * <p>
2979     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2980     * </p>
2981     * <p>
2982     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2983     * </p>
2984     *
2985     * @param array       the array to search for the object, may be {@code null}.
2986     * @param valueToFind the value to find.
2987     * @param startIndex  the index to start searching.
2988     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2989     */
2990    public static int indexOf(final long[] array, final long valueToFind, final int startIndex) {
2991        if (isEmpty(array)) {
2992            return INDEX_NOT_FOUND;
2993        }
2994        for (int i = max0(startIndex); i < array.length; i++) {
2995            if (valueToFind == array[i]) {
2996                return i;
2997            }
2998        }
2999        return INDEX_NOT_FOUND;
3000    }
3001
3002    /**
3003     * Finds the index of the given object in the array.
3004     * <p>
3005     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3006     * </p>
3007     *
3008     * @param array        the array to search for the object, may be {@code null}.
3009     * @param objectToFind the object to find, may be {@code null}.
3010     * @return the index of the object within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3011     */
3012    public static int indexOf(final Object[] array, final Object objectToFind) {
3013        return indexOf(array, objectToFind, 0);
3014    }
3015
3016    /**
3017     * Finds the index of the given object in the array starting at the given index.
3018     * <p>
3019     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3020     * </p>
3021     * <p>
3022     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3023     * </p>
3024     *
3025     * @param array        the array to search for the object, may be {@code null}.
3026     * @param objectToFind the object to find, may be {@code null}.
3027     * @param startIndex   the index to start searching.
3028     * @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.
3029     */
3030    public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
3031        if (isEmpty(array)) {
3032            return INDEX_NOT_FOUND;
3033        }
3034        startIndex = max0(startIndex);
3035        if (objectToFind == null) {
3036            for (int i = startIndex; i < array.length; i++) {
3037                if (array[i] == null) {
3038                    return i;
3039                }
3040            }
3041        } else {
3042            for (int i = startIndex; i < array.length; i++) {
3043                if (objectToFind.equals(array[i])) {
3044                    return i;
3045                }
3046            }
3047        }
3048        return INDEX_NOT_FOUND;
3049    }
3050
3051    /**
3052     * Finds the index of the given value in the array.
3053     * <p>
3054     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3055     * </p>
3056     *
3057     * @param array       the array to search for the object, may be {@code null}
3058     * @param valueToFind the value to find.
3059     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3060     */
3061    public static int indexOf(final short[] array, final short valueToFind) {
3062        return indexOf(array, valueToFind, 0);
3063    }
3064
3065    /**
3066     * Finds the index of the given value in the array starting at the given index.
3067     * <p>
3068     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3069     * </p>
3070     * <p>
3071     * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3072     * </p>
3073     *
3074     * @param array       the array to search for the object, may be {@code null}.
3075     * @param valueToFind the value to find.
3076     * @param startIndex  the index to start searching.
3077     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3078     */
3079    public static int indexOf(final short[] array, final short valueToFind, final int startIndex) {
3080        if (isEmpty(array)) {
3081            return INDEX_NOT_FOUND;
3082        }
3083        for (int i = max0(startIndex); i < array.length; i++) {
3084            if (valueToFind == array[i]) {
3085                return i;
3086            }
3087        }
3088        return INDEX_NOT_FOUND;
3089    }
3090
3091    /**
3092     * Finds the index of the NaN value in a double array.
3093     * @param array the array to search for NaN, may be {@code null}.
3094     * @param startIndex the index to start searching.
3095     * @return the index of the NaN value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3096     */
3097    private static int indexOfNaN(final double[] array, final int startIndex) {
3098        if (isEmpty(array)) {
3099            return INDEX_NOT_FOUND;
3100        }
3101        for (int i = max0(startIndex); i < array.length; i++) {
3102            if (Double.isNaN(array[i])) {
3103                return i;
3104            }
3105        }
3106        return INDEX_NOT_FOUND;
3107    }
3108
3109    /**
3110     * Inserts elements into an array at the given index (starting from zero).
3111     *
3112     * <p>
3113     * When an array is returned, it is always a new array.
3114     * </p>
3115     *
3116     * <pre>
3117     * ArrayUtils.insert(index, null, null)      = null
3118     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3119     * ArrayUtils.insert(index, null, values)    = null
3120     * </pre>
3121     *
3122     * @param index  the position within {@code array} to insert the new values.
3123     * @param array  the array to insert the values into, may be {@code null}.
3124     * @param values the new values to insert, may be {@code null}.
3125     * @return The new array or {@code null} if the given array is {@code null}.
3126     * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3127     * @since 3.6
3128     */
3129    public static boolean[] insert(final int index, final boolean[] array, final boolean... values) {
3130        if (array == null) {
3131            return null;
3132        }
3133        if (isEmpty(values)) {
3134            return clone(array);
3135        }
3136        if (index < 0 || index > array.length) {
3137            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3138        }
3139        final boolean[] result = new boolean[array.length + values.length];
3140        System.arraycopy(values, 0, result, index, values.length);
3141        if (index > 0) {
3142            System.arraycopy(array, 0, result, 0, index);
3143        }
3144        if (index < array.length) {
3145            System.arraycopy(array, index, result, index + values.length, array.length - index);
3146        }
3147        return result;
3148    }
3149
3150    /**
3151     * Inserts elements into an array at the given index (starting from zero).
3152     *
3153     * <p>
3154     * When an array is returned, it is always a new array.
3155     * </p>
3156     *
3157     * <pre>
3158     * ArrayUtils.insert(index, null, null)      = null
3159     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3160     * ArrayUtils.insert(index, null, values)    = null
3161     * </pre>
3162     *
3163     * @param index  the position within {@code array} to insert the new values.
3164     * @param array  the array to insert the values into, may be {@code null}.
3165     * @param values the new values to insert, may be {@code null}.
3166     * @return The new array or {@code null} if the given array is {@code null}.
3167     * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3168     * @since 3.6
3169     */
3170    public static byte[] insert(final int index, final byte[] array, final byte... values) {
3171        if (array == null) {
3172            return null;
3173        }
3174        if (isEmpty(values)) {
3175            return clone(array);
3176        }
3177        if (index < 0 || index > array.length) {
3178            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3179        }
3180        final byte[] result = new byte[array.length + values.length];
3181        System.arraycopy(values, 0, result, index, values.length);
3182        if (index > 0) {
3183            System.arraycopy(array, 0, result, 0, index);
3184        }
3185        if (index < array.length) {
3186            System.arraycopy(array, index, result, index + values.length, array.length - index);
3187        }
3188        return result;
3189    }
3190
3191    /**
3192     * Inserts elements into an array at the given index (starting from zero).
3193     *
3194     * <p>
3195     * When an array is returned, it is always a new array.
3196     * </p>
3197     *
3198     * <pre>
3199     * ArrayUtils.insert(index, null, null)      = null
3200     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3201     * ArrayUtils.insert(index, null, values)    = null
3202     * </pre>
3203     *
3204     * @param index  the position within {@code array} to insert the new values.
3205     * @param array  the array to insert the values into, may be {@code null}.
3206     * @param values the new values to insert, may be {@code null}.
3207     * @return The new array or {@code null} if the given array is {@code null}.
3208     * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3209     * @since 3.6
3210     */
3211    public static char[] insert(final int index, final char[] array, final char... values) {
3212        if (array == null) {
3213            return null;
3214        }
3215        if (isEmpty(values)) {
3216            return clone(array);
3217        }
3218        if (index < 0 || index > array.length) {
3219            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3220        }
3221        final char[] result = new char[array.length + values.length];
3222        System.arraycopy(values, 0, result, index, values.length);
3223        if (index > 0) {
3224            System.arraycopy(array, 0, result, 0, index);
3225        }
3226        if (index < array.length) {
3227            System.arraycopy(array, index, result, index + values.length, array.length - index);
3228        }
3229        return result;
3230    }
3231
3232    /**
3233     * Inserts elements into an array at the given index (starting from zero).
3234     *
3235     * <p>
3236     * When an array is returned, it is always a new array.
3237     * </p>
3238     *
3239     * <pre>
3240     * ArrayUtils.insert(index, null, null)      = null
3241     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3242     * ArrayUtils.insert(index, null, values)    = null
3243     * </pre>
3244     *
3245     * @param index  the position within {@code array} to insert the new values.
3246     * @param array  the array to insert the values into, may be {@code null}.
3247     * @param values the new values to insert, may be {@code null}.
3248     * @return The new array or {@code null} if the given array is {@code null}.
3249     * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3250     * @since 3.6
3251     */
3252    public static double[] insert(final int index, final double[] array, final double... values) {
3253        if (array == null) {
3254            return null;
3255        }
3256        if (isEmpty(values)) {
3257            return clone(array);
3258        }
3259        if (index < 0 || index > array.length) {
3260            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3261        }
3262        final double[] result = new double[array.length + values.length];
3263        System.arraycopy(values, 0, result, index, values.length);
3264        if (index > 0) {
3265            System.arraycopy(array, 0, result, 0, index);
3266        }
3267        if (index < array.length) {
3268            System.arraycopy(array, index, result, index + values.length, array.length - index);
3269        }
3270        return result;
3271    }
3272
3273    /**
3274     * Inserts elements into an array at the given index (starting from zero).
3275     *
3276     * <p>
3277     * When an array is returned, it is always a new array.
3278     * </p>
3279     *
3280     * <pre>
3281     * ArrayUtils.insert(index, null, null)      = null
3282     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3283     * ArrayUtils.insert(index, null, values)    = null
3284     * </pre>
3285     *
3286     * @param index  the position within {@code array} to insert the new values.
3287     * @param array  the array to insert the values into, may be {@code null}.
3288     * @param values the new values to insert, may be {@code null}.
3289     * @return The new array or {@code null} if the given array is {@code null}.
3290     * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3291     * @since 3.6
3292     */
3293    public static float[] insert(final int index, final float[] array, final float... values) {
3294        if (array == null) {
3295            return null;
3296        }
3297        if (isEmpty(values)) {
3298            return clone(array);
3299        }
3300        if (index < 0 || index > array.length) {
3301            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3302        }
3303        final float[] result = new float[array.length + values.length];
3304        System.arraycopy(values, 0, result, index, values.length);
3305        if (index > 0) {
3306            System.arraycopy(array, 0, result, 0, index);
3307        }
3308        if (index < array.length) {
3309            System.arraycopy(array, index, result, index + values.length, array.length - index);
3310        }
3311        return result;
3312    }
3313
3314    /**
3315     * Inserts elements into an array at the given index (starting from zero).
3316     *
3317     * <p>
3318     * When an array is returned, it is always a new array.
3319     * </p>
3320     *
3321     * <pre>
3322     * ArrayUtils.insert(index, null, null)      = null
3323     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3324     * ArrayUtils.insert(index, null, values)    = null
3325     * </pre>
3326     *
3327     * @param index  the position within {@code array} to insert the new values.
3328     * @param array  the array to insert the values into, may be {@code null}.
3329     * @param values the new values to insert, may be {@code null}.
3330     * @return The new array or {@code null} if the given array is {@code null}.
3331     * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3332     * @since 3.6
3333     */
3334    public static int[] insert(final int index, final int[] array, final int... values) {
3335        if (array == null) {
3336            return null;
3337        }
3338        if (isEmpty(values)) {
3339            return clone(array);
3340        }
3341        if (index < 0 || index > array.length) {
3342            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3343        }
3344        final int[] result = new int[array.length + values.length];
3345        System.arraycopy(values, 0, result, index, values.length);
3346        if (index > 0) {
3347            System.arraycopy(array, 0, result, 0, index);
3348        }
3349        if (index < array.length) {
3350            System.arraycopy(array, index, result, index + values.length, array.length - index);
3351        }
3352        return result;
3353    }
3354
3355    /**
3356     * Inserts elements into an array at the given index (starting from zero).
3357     *
3358     * <p>
3359     * When an array is returned, it is always a new array.
3360     * </p>
3361     *
3362     * <pre>
3363     * ArrayUtils.insert(index, null, null)      = null
3364     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3365     * ArrayUtils.insert(index, null, values)    = null
3366     * </pre>
3367     *
3368     * @param index  the position within {@code array} to insert the new values.
3369     * @param array  the array to insert the values into, may be {@code null}.
3370     * @param values the new values to insert, may be {@code null}.
3371     * @return The new array or {@code null} if the given array is {@code null}.
3372     * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3373     * @since 3.6
3374     */
3375    public static long[] insert(final int index, final long[] array, final long... values) {
3376        if (array == null) {
3377            return null;
3378        }
3379        if (isEmpty(values)) {
3380            return clone(array);
3381        }
3382        if (index < 0 || index > array.length) {
3383            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3384        }
3385        final long[] result = new long[array.length + values.length];
3386        System.arraycopy(values, 0, result, index, values.length);
3387        if (index > 0) {
3388            System.arraycopy(array, 0, result, 0, index);
3389        }
3390        if (index < array.length) {
3391            System.arraycopy(array, index, result, index + values.length, array.length - index);
3392        }
3393        return result;
3394    }
3395
3396    /**
3397     * Inserts elements into an array at the given index (starting from zero).
3398     *
3399     * <p>
3400     * When an array is returned, it is always a new array.
3401     * </p>
3402     *
3403     * <pre>
3404     * ArrayUtils.insert(index, null, null)      = null
3405     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3406     * ArrayUtils.insert(index, null, values)    = null
3407     * </pre>
3408     *
3409     * @param index  the position within {@code array} to insert the new values.
3410     * @param array  the array to insert the values into, may be {@code null}.
3411     * @param values the new values to insert, may be {@code null}.
3412     * @return The new array or {@code null} if the given array is {@code null}.
3413     * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3414     * @since 3.6
3415     */
3416    public static short[] insert(final int index, final short[] array, final short... values) {
3417        if (array == null) {
3418            return null;
3419        }
3420        if (isEmpty(values)) {
3421            return clone(array);
3422        }
3423        if (index < 0 || index > array.length) {
3424            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3425        }
3426        final short[] result = new short[array.length + values.length];
3427        System.arraycopy(values, 0, result, index, values.length);
3428        if (index > 0) {
3429            System.arraycopy(array, 0, result, 0, index);
3430        }
3431        if (index < array.length) {
3432            System.arraycopy(array, index, result, index + values.length, array.length - index);
3433        }
3434        return result;
3435    }
3436
3437    /**
3438     * Inserts elements into an array at the given index (starting from zero).
3439     *
3440     * <p>
3441     * When an array is returned, it is always a new array.
3442     * </p>
3443     *
3444     * <pre>
3445     * ArrayUtils.insert(index, null, null)      = null
3446     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3447     * ArrayUtils.insert(index, null, values)    = null
3448     * </pre>
3449     *
3450     * @param <T>    The type of elements in {@code array} and {@code values}.
3451     * @param index  the position within {@code array} to insert the new values.
3452     * @param array  the array to insert the values into, may be {@code null}.
3453     * @param values the new values to insert, may be {@code null}.
3454     * @return The new array or {@code null} if the given array is {@code null}.
3455     * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3456     * @since 3.6
3457     */
3458    @SafeVarargs
3459    public static <T> T[] insert(final int index, final T[] array, final T... values) {
3460        /*
3461         * Note on use of @SafeVarargs:
3462         *
3463         * By returning null when 'array' is null, we avoid returning the vararg
3464         * array to the caller. We also avoid relying on the type of the vararg
3465         * array, by inspecting the component type of 'array'.
3466         */
3467        if (array == null) {
3468            return null;
3469        }
3470        if (isEmpty(values)) {
3471            return clone(array);
3472        }
3473        if (index < 0 || index > array.length) {
3474            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3475        }
3476        final Class<T> type = getComponentType(array);
3477        final int length = array.length + values.length;
3478        final T[] result = newInstance(type, length);
3479        System.arraycopy(values, 0, result, index, values.length);
3480        if (index > 0) {
3481            System.arraycopy(array, 0, result, 0, index);
3482        }
3483        if (index < array.length) {
3484            System.arraycopy(array, index, result, index + values.length, array.length - index);
3485        }
3486        return result;
3487    }
3488
3489    /**
3490     * Checks if an array is empty or {@code null}.
3491     *
3492     * @param array the array to test.
3493     * @return {@code true} if the array is empty or {@code null}.
3494     */
3495    private static boolean isArrayEmpty(final Object array) {
3496        return getLength(array) == 0;
3497    }
3498
3499    /**
3500     * Tests whether a given array can safely be accessed at the given index.
3501     *
3502     * <pre>
3503     * ArrayUtils.isArrayIndexValid(null, 0)       = false
3504     * ArrayUtils.isArrayIndexValid([], 0)         = false
3505     * ArrayUtils.isArrayIndexValid(["a"], 0)      = true
3506     * </pre>
3507     *
3508     * @param <T> the component type of the array.
3509     * @param array the array to inspect, may be {@code null}.
3510     * @param index the index of the array to be inspected.
3511     * @return Whether the given index is safely-accessible in the given array.
3512     * @since 3.8
3513     */
3514    public static <T> boolean isArrayIndexValid(final T[] array, final int index) {
3515        return index >= 0 && getLength(array) > index;
3516    }
3517
3518    /**
3519     * Tests whether an array of primitive booleans is empty or {@code null}.
3520     *
3521     * @param array  the array to test.
3522     * @return {@code true} if the array is empty or {@code null}.
3523     * @since 2.1
3524     */
3525    public static boolean isEmpty(final boolean[] array) {
3526        return isArrayEmpty(array);
3527    }
3528
3529    /**
3530     * Tests whether an array of primitive bytes is empty or {@code null}.
3531     *
3532     * @param array  the array to test.
3533     * @return {@code true} if the array is empty or {@code null}.
3534     * @since 2.1
3535     */
3536    public static boolean isEmpty(final byte[] array) {
3537        return isArrayEmpty(array);
3538    }
3539
3540    /**
3541     * Tests whether an array of primitive chars is empty or {@code null}.
3542     *
3543     * @param array  the array to test.
3544     * @return {@code true} if the array is empty or {@code null}.
3545     * @since 2.1
3546     */
3547    public static boolean isEmpty(final char[] array) {
3548        return isArrayEmpty(array);
3549    }
3550
3551    /**
3552     * Tests whether an array of primitive doubles is empty or {@code null}.
3553     *
3554     * @param array  the array to test.
3555     * @return {@code true} if the array is empty or {@code null}.
3556     * @since 2.1
3557     */
3558    public static boolean isEmpty(final double[] array) {
3559        return isArrayEmpty(array);
3560    }
3561
3562    /**
3563     * Tests whether an array of primitive floats is empty or {@code null}.
3564     *
3565     * @param array  the array to test.
3566     * @return {@code true} if the array is empty or {@code null}.
3567     * @since 2.1
3568     */
3569    public static boolean isEmpty(final float[] array) {
3570        return isArrayEmpty(array);
3571    }
3572
3573    /**
3574     * Tests whether an array of primitive ints is empty or {@code null}.
3575     *
3576     * @param array  the array to test.
3577     * @return {@code true} if the array is empty or {@code null}.
3578     * @since 2.1
3579     */
3580    public static boolean isEmpty(final int[] array) {
3581        return isArrayEmpty(array);
3582    }
3583
3584    /**
3585     * Tests whether an array of primitive longs is empty or {@code null}.
3586     *
3587     * @param array  the array to test.
3588     * @return {@code true} if the array is empty or {@code null}.
3589     * @since 2.1
3590     */
3591    public static boolean isEmpty(final long[] array) {
3592        return isArrayEmpty(array);
3593    }
3594
3595    /**
3596     * Tests whether an array of Objects is empty or {@code null}.
3597     *
3598     * @param array  the array to test.
3599     * @return {@code true} if the array is empty or {@code null}.
3600     * @since 2.1
3601     */
3602    public static boolean isEmpty(final Object[] array) {
3603        return isArrayEmpty(array);
3604    }
3605
3606    /**
3607     * Tests whether an array of primitive shorts is empty or {@code null}.
3608     *
3609     * @param array  the array to test.
3610     * @return {@code true} if the array is empty or {@code null}.
3611     * @since 2.1
3612     */
3613    public static boolean isEmpty(final short[] array) {
3614        return isArrayEmpty(array);
3615    }
3616
3617     /**
3618     * Tests whether two arrays have equal content, using equals(), handling multidimensional arrays
3619     * correctly.
3620     * <p>
3621     * Multi-dimensional primitive arrays are also handled correctly by this method.
3622     * </p>
3623     *
3624     * @param array1  the left-hand side array to compare, may be {@code null}.
3625     * @param array2  the right-hand side array to compare, may be {@code null}.
3626     * @return {@code true} if the arrays are equal.
3627     * @deprecated Replaced by {@code java.util.Objects.deepEquals(Object, Object)} and will be
3628     * removed from future releases.
3629     */
3630    @Deprecated
3631    public static boolean isEquals(final Object array1, final Object array2) {
3632        return new EqualsBuilder().append(array1, array2).isEquals();
3633    }
3634
3635    /**
3636     * Tests whether an array of primitive booleans is not empty and not {@code null}.
3637     *
3638     * @param array  the array to test.
3639     * @return {@code true} if the array is not empty and not {@code null}.
3640     * @since 2.5
3641     */
3642    public static boolean isNotEmpty(final boolean[] array) {
3643        return !isEmpty(array);
3644    }
3645
3646    /**
3647     * Tests whether an array of primitive bytes is not empty and not {@code null}.
3648     *
3649     * @param array  the array to test.
3650     * @return {@code true} if the array is not empty and not {@code null}.
3651     * @since 2.5
3652     */
3653    public static boolean isNotEmpty(final byte[] array) {
3654        return !isEmpty(array);
3655    }
3656
3657    /**
3658     * Tests whether an array of primitive chars is not empty and not {@code null}.
3659     *
3660     * @param array  the array to test.
3661     * @return {@code true} if the array is not empty and not {@code null}.
3662     * @since 2.5
3663     */
3664    public static boolean isNotEmpty(final char[] array) {
3665        return !isEmpty(array);
3666    }
3667
3668    /**
3669     * Tests whether an array of primitive doubles is not empty and not {@code null}.
3670     *
3671     * @param array  the array to test.
3672     * @return {@code true} if the array is not empty and not {@code null}.
3673     * @since 2.5
3674     */
3675    public static boolean isNotEmpty(final double[] array) {
3676        return !isEmpty(array);
3677    }
3678
3679    /**
3680     * Tests whether an array of primitive floats is not empty and not {@code null}.
3681     *
3682     * @param array  the array to test.
3683     * @return {@code true} if the array is not empty and not {@code null}.
3684     * @since 2.5
3685     */
3686    public static boolean isNotEmpty(final float[] array) {
3687        return !isEmpty(array);
3688    }
3689
3690    /**
3691     * Tests whether an array of primitive ints is not empty and not {@code null}.
3692     *
3693     * @param array  the array to test.
3694     * @return {@code true} if the array is not empty and not {@code null}.
3695     * @since 2.5
3696     */
3697    public static boolean isNotEmpty(final int[] array) {
3698        return !isEmpty(array);
3699    }
3700
3701    /**
3702     * Tests whether an array of primitive longs is not empty and not {@code null}.
3703     *
3704     * @param array  the array to test.
3705     * @return {@code true} if the array is not empty and not {@code null}.
3706     * @since 2.5
3707     */
3708    public static boolean isNotEmpty(final long[] array) {
3709        return !isEmpty(array);
3710    }
3711
3712    /**
3713     * Tests whether an array of primitive shorts is not empty and not {@code null}.
3714     *
3715     * @param array  the array to test.
3716     * @return {@code true} if the array is not empty and not {@code null}.
3717     * @since 2.5
3718     */
3719    public static boolean isNotEmpty(final short[] array) {
3720        return !isEmpty(array);
3721    }
3722
3723    /**
3724     * Tests whether an array of Objects is not empty and not {@code null}.
3725     *
3726     * @param <T> the component type of the array
3727     * @param array  the array to test.
3728     * @return {@code true} if the array is not empty and not {@code null}.
3729     * @since 2.5
3730     */
3731     public static <T> boolean isNotEmpty(final T[] array) {
3732         return !isEmpty(array);
3733     }
3734
3735    /**
3736      * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3737      *
3738      * @param array1 the first array, may be {@code null}.
3739      * @param array2 the second array, may be {@code null}.
3740      * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3741      */
3742     public static boolean isSameLength(final boolean[] array1, final boolean[] array2) {
3743        return getLength(array1) == getLength(array2);
3744    }
3745
3746    /**
3747     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3748     *
3749     * @param array1 the first array, may be {@code null}.
3750     * @param array2 the second array, may be {@code null}.
3751     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3752     */
3753    public static boolean isSameLength(final byte[] array1, final byte[] array2) {
3754        return getLength(array1) == getLength(array2);
3755    }
3756
3757    /**
3758     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3759     *
3760     * @param array1 the first array, may be {@code null}.
3761     * @param array2 the second array, may be {@code null}.
3762     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3763     */
3764    public static boolean isSameLength(final char[] array1, final char[] array2) {
3765        return getLength(array1) == getLength(array2);
3766    }
3767
3768    /**
3769     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3770     *
3771     * @param array1 the first array, may be {@code null}.
3772     * @param array2 the second array, may be {@code null}.
3773     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3774     */
3775    public static boolean isSameLength(final double[] array1, final double[] array2) {
3776        return getLength(array1) == getLength(array2);
3777    }
3778
3779    /**
3780     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3781     *
3782     * @param array1 the first array, may be {@code null}.
3783     * @param array2 the second array, may be {@code null}.
3784     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3785     */
3786    public static boolean isSameLength(final float[] array1, final float[] array2) {
3787        return getLength(array1) == getLength(array2);
3788    }
3789
3790    /**
3791     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3792     *
3793     * @param array1 the first array, may be {@code null}.
3794     * @param array2 the second array, may be {@code null}.
3795     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3796     */
3797    public static boolean isSameLength(final int[] array1, final int[] array2) {
3798        return getLength(array1) == getLength(array2);
3799    }
3800
3801    /**
3802     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3803     *
3804     * @param array1 the first array, may be {@code null}.
3805     * @param array2 the second array, may be {@code null}.
3806     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3807     */
3808    public static boolean isSameLength(final long[] array1, final long[] array2) {
3809        return getLength(array1) == getLength(array2);
3810    }
3811
3812    /**
3813     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3814     * <p>
3815     * Any multi-dimensional aspects of the arrays are ignored.
3816     * </p>
3817     *
3818     * @param array1 the first array, may be {@code null}.
3819     * @param array2 the second array, may be {@code null}.
3820     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3821     * @since 3.11
3822     */
3823    public static boolean isSameLength(final Object array1, final Object array2) {
3824        return getLength(array1) == getLength(array2);
3825    }
3826
3827    /**
3828     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3829     * <p>
3830     * Any multi-dimensional aspects of the arrays are ignored.
3831     * </p>
3832     *
3833     * @param array1 the first array, may be {@code null}.
3834     * @param array2 the second array, may be {@code null}.
3835     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3836     */
3837    public static boolean isSameLength(final Object[] array1, final Object[] array2) {
3838        return getLength(array1) == getLength(array2);
3839    }
3840
3841    /**
3842     * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3843     *
3844     * @param array1 the first array, may be {@code null}.
3845     * @param array2 the second array, may be {@code null}.
3846     * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3847     */
3848    public static boolean isSameLength(final short[] array1, final short[] array2) {
3849        return getLength(array1) == getLength(array2);
3850    }
3851
3852    /**
3853     * Tests whether two arrays are the same type taking into account multidimensional arrays.
3854     *
3855     * @param array1 the first array, must not be {@code null}.
3856     * @param array2 the second array, must not be {@code null}.
3857     * @return {@code true} if type of arrays matches.
3858     * @throws IllegalArgumentException if either array is {@code null}.
3859     */
3860    public static boolean isSameType(final Object array1, final Object array2) {
3861        if (array1 == null || array2 == null) {
3862            throw new IllegalArgumentException("The Array must not be null");
3863        }
3864        return array1.getClass().getName().equals(array2.getClass().getName());
3865    }
3866
3867    /**
3868     * Tests whether whether the provided array is sorted according to natural ordering ({@code false} before {@code true}).
3869     *
3870     * @param array the array to check.
3871     * @return whether the array is sorted according to natural ordering.
3872     * @since 3.4
3873     */
3874    public static boolean isSorted(final boolean[] array) {
3875        if (getLength(array) < 2) {
3876            return true;
3877        }
3878        boolean previous = array[0];
3879        final int n = array.length;
3880        for (int i = 1; i < n; i++) {
3881            final boolean current = array[i];
3882            if (BooleanUtils.compare(previous, current) > 0) {
3883                return false;
3884            }
3885            previous = current;
3886        }
3887        return true;
3888    }
3889
3890    /**
3891     * Tests whether the provided array is sorted according to natural ordering.
3892     *
3893     * @param array the array to check.
3894     * @return whether the array is sorted according to natural ordering.
3895     * @since 3.4
3896     */
3897    public static boolean isSorted(final byte[] array) {
3898        if (getLength(array) < 2) {
3899            return true;
3900        }
3901        byte previous = array[0];
3902        final int n = array.length;
3903        for (int i = 1; i < n; i++) {
3904            final byte current = array[i];
3905            if (Byte.compare(previous, current) > 0) {
3906                return false;
3907            }
3908            previous = current;
3909        }
3910        return true;
3911    }
3912
3913    /**
3914     * Tests whether the provided array is sorted according to natural ordering.
3915     *
3916     * @param array the array to check.
3917     * @return whether the array is sorted according to natural ordering.
3918     * @since 3.4
3919     */
3920    public static boolean isSorted(final char[] array) {
3921        if (getLength(array) < 2) {
3922            return true;
3923        }
3924        char previous = array[0];
3925        final int n = array.length;
3926        for (int i = 1; i < n; i++) {
3927            final char current = array[i];
3928            if (CharUtils.compare(previous, current) > 0) {
3929                return false;
3930            }
3931            previous = current;
3932        }
3933        return true;
3934    }
3935
3936    /**
3937     * Tests whether the provided array is sorted according to natural ordering.
3938     *
3939     * @param array the array to check.
3940     * @return whether the array is sorted according to natural ordering.
3941     * @since 3.4
3942     */
3943    public static boolean isSorted(final double[] array) {
3944        if (getLength(array) < 2) {
3945            return true;
3946        }
3947        double previous = array[0];
3948        final int n = array.length;
3949        for (int i = 1; i < n; i++) {
3950            final double current = array[i];
3951            if (Double.compare(previous, current) > 0) {
3952                return false;
3953            }
3954            previous = current;
3955        }
3956        return true;
3957    }
3958
3959    /**
3960     * Tests whether the provided array is sorted according to natural ordering.
3961     *
3962     * @param array the array to check.
3963     * @return whether the array is sorted according to natural ordering.
3964     * @since 3.4
3965     */
3966    public static boolean isSorted(final float[] array) {
3967        if (getLength(array) < 2) {
3968            return true;
3969        }
3970        float previous = array[0];
3971        final int n = array.length;
3972        for (int i = 1; i < n; i++) {
3973            final float current = array[i];
3974            if (Float.compare(previous, current) > 0) {
3975                return false;
3976            }
3977            previous = current;
3978        }
3979        return true;
3980    }
3981
3982    /**
3983     * Tests whether the provided array is sorted according to natural ordering.
3984     *
3985     * @param array the array to check.
3986     * @return whether the array is sorted according to natural ordering.
3987     * @since 3.4
3988     */
3989    public static boolean isSorted(final int[] array) {
3990        if (getLength(array) < 2) {
3991            return true;
3992        }
3993        int previous = array[0];
3994        final int n = array.length;
3995        for (int i = 1; i < n; i++) {
3996            final int current = array[i];
3997            if (Integer.compare(previous, current) > 0) {
3998                return false;
3999            }
4000            previous = current;
4001        }
4002        return true;
4003    }
4004
4005    /**
4006     * Tests whether the provided array is sorted according to natural ordering.
4007     *
4008     * @param array the array to check.
4009     * @return whether the array is sorted according to natural ordering.
4010     * @since 3.4
4011     */
4012    public static boolean isSorted(final long[] array) {
4013        if (getLength(array) < 2) {
4014            return true;
4015        }
4016        long previous = array[0];
4017        final int n = array.length;
4018        for (int i = 1; i < n; i++) {
4019            final long current = array[i];
4020            if (Long.compare(previous, current) > 0) {
4021                return false;
4022            }
4023            previous = current;
4024        }
4025        return true;
4026    }
4027
4028    /**
4029     * Tests whether the provided array is sorted according to natural ordering.
4030     *
4031     * @param array the array to check.
4032     * @return whether the array is sorted according to natural ordering.
4033     * @since 3.4
4034     */
4035    public static boolean isSorted(final short[] array) {
4036        if (getLength(array) < 2) {
4037            return true;
4038        }
4039        short previous = array[0];
4040        final int n = array.length;
4041        for (int i = 1; i < n; i++) {
4042            final short current = array[i];
4043            if (Short.compare(previous, current) > 0) {
4044                return false;
4045            }
4046            previous = current;
4047        }
4048        return true;
4049    }
4050
4051    /**
4052     * Tests whether the provided array is sorted according to the class's
4053     * {@code compareTo} method.
4054     *
4055     * @param array the array to check.
4056     * @param <T> the datatype of the array to check, it must implement {@link Comparable}.
4057     * @return whether the array is sorted.
4058     * @since 3.4
4059     */
4060    public static <T extends Comparable<? super T>> boolean isSorted(final T[] array) {
4061        return isSorted(array, Comparable::compareTo);
4062    }
4063
4064    /**
4065     * Tests whether the provided array is sorted according to the provided {@link Comparator}.
4066     *
4067     * @param array the array to check.
4068     * @param comparator the {@link Comparator} to compare over.
4069     * @param <T> the datatype of the array.
4070     * @return whether the array is sorted.
4071     * @throws NullPointerException if {@code comparator} is {@code null}.
4072     * @since 3.4
4073     */
4074    public static <T> boolean isSorted(final T[] array, final Comparator<T> comparator) {
4075        Objects.requireNonNull(comparator, "comparator");
4076        if (getLength(array) < 2) {
4077            return true;
4078        }
4079        T previous = array[0];
4080        final int n = array.length;
4081        for (int i = 1; i < n; i++) {
4082            final T current = array[i];
4083            if (comparator.compare(previous, current) > 0) {
4084                return false;
4085            }
4086            previous = current;
4087        }
4088        return true;
4089    }
4090
4091    /**
4092     * Finds the last index of the given value within the array.
4093     * <p>
4094     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) if {@code null} array input.
4095     * </p>
4096     *
4097     * @param array       the array to traverse backwards looking for the object, may be {@code null}.
4098     * @param valueToFind the object to find.
4099     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4100     */
4101    public static int lastIndexOf(final boolean[] array, final boolean valueToFind) {
4102        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4103    }
4104
4105    /**
4106     * Finds the last index of the given value in the array starting at the given index.
4107     * <p>
4108     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4109     * </p>
4110     * <p>
4111     * 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.
4112     * </p>
4113     *
4114     * @param array       the array to traverse for looking for the object, may be {@code null}.
4115     * @param valueToFind the value to find.
4116     * @param startIndex  the start index to traverse backwards from.
4117     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4118     */
4119    public static int lastIndexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
4120        if (isEmpty(array) || startIndex < 0) {
4121            return INDEX_NOT_FOUND;
4122        }
4123        if (startIndex >= array.length) {
4124            startIndex = array.length - 1;
4125        }
4126        for (int i = startIndex; i >= 0; i--) {
4127            if (valueToFind == array[i]) {
4128                return i;
4129            }
4130        }
4131        return INDEX_NOT_FOUND;
4132    }
4133
4134    /**
4135     * Finds the last index of the given value within the array.
4136     * <p>
4137     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4138     * </p>
4139     *
4140     * @param array       the array to traverse backwards looking for the object, may be {@code null}.
4141     * @param valueToFind the object to find.
4142     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4143     */
4144    public static int lastIndexOf(final byte[] array, final byte valueToFind) {
4145        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4146    }
4147
4148    /**
4149     * Finds the last index of the given value in the array starting at the given index.
4150     * <p>
4151     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4152     * </p>
4153     * <p>
4154     * 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.
4155     * </p>
4156     *
4157     * @param array       the array to traverse for looking for the object, may be {@code null}.
4158     * @param valueToFind the value to find.
4159     * @param startIndex  the start index to traverse backwards from.
4160     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4161     */
4162    public static int lastIndexOf(final byte[] array, final byte valueToFind, int startIndex) {
4163        if (array == null || startIndex < 0) {
4164            return INDEX_NOT_FOUND;
4165        }
4166        if (startIndex >= array.length) {
4167            startIndex = array.length - 1;
4168        }
4169        for (int i = startIndex; i >= 0; i--) {
4170            if (valueToFind == array[i]) {
4171                return i;
4172            }
4173        }
4174        return INDEX_NOT_FOUND;
4175    }
4176
4177    /**
4178     * Finds the last index of the given value within the array.
4179     * <p>
4180     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4181     * </p>
4182     *
4183     * @param array       the array to traverse backwards looking for the object, may be {@code null}.
4184     * @param valueToFind the object to find.
4185     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4186     * @since 2.1
4187     */
4188    public static int lastIndexOf(final char[] array, final char valueToFind) {
4189        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4190    }
4191
4192    /**
4193     * Finds the last index of the given value in the array starting at the given index.
4194     * <p>
4195     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4196     * </p>
4197     * <p>
4198     * 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.
4199     * </p>
4200     *
4201     * @param array       the array to traverse for looking for the object, may be {@code null}.
4202     * @param valueToFind the value to find.
4203     * @param startIndex  the start index to traverse backwards from.
4204     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4205     * @since 2.1
4206     */
4207    public static int lastIndexOf(final char[] array, final char valueToFind, int startIndex) {
4208        if (array == null || startIndex < 0) {
4209            return INDEX_NOT_FOUND;
4210        }
4211        if (startIndex >= array.length) {
4212            startIndex = array.length - 1;
4213        }
4214        for (int i = startIndex; i >= 0; i--) {
4215            if (valueToFind == array[i]) {
4216                return i;
4217            }
4218        }
4219        return INDEX_NOT_FOUND;
4220    }
4221
4222    /**
4223     * Finds the last index of the given value within the array.
4224     * <p>
4225     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4226     * </p>
4227     *
4228     * @param array       the array to traverse backwards looking for the object, may be {@code null}.
4229     * @param valueToFind the object to find.
4230     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4231     */
4232    public static int lastIndexOf(final double[] array, final double valueToFind) {
4233        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4234    }
4235
4236    /**
4237     * 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
4238     * the region defined by valueToFind - tolerance and valueToFind + tolerance.
4239     * <p>
4240     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4241     * </p>
4242     *
4243     * @param array       the array to search for the object, may be {@code null}.
4244     * @param valueToFind the value to find.
4245     * @param tolerance   tolerance of the search.
4246     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4247     */
4248    public static int lastIndexOf(final double[] array, final double valueToFind, final double tolerance) {
4249        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance);
4250    }
4251
4252    /**
4253     * Finds the last index of the given value in the array starting at the given index.
4254     * <p>
4255     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4256     * </p>
4257     * <p>
4258     * 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.
4259     * </p>
4260     *
4261     * @param array       the array to traverse for looking for the object, may be {@code null}.
4262     * @param valueToFind the value to find.
4263     * @param startIndex  the start index to traverse backwards from.
4264     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4265     */
4266    public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex) {
4267        if (isEmpty(array) || startIndex < 0) {
4268            return INDEX_NOT_FOUND;
4269        }
4270        if (startIndex >= array.length) {
4271            startIndex = array.length - 1;
4272        }
4273        for (int i = startIndex; i >= 0; i--) {
4274            if (valueToFind == array[i]) {
4275                return i;
4276            }
4277        }
4278        return INDEX_NOT_FOUND;
4279    }
4280
4281    /**
4282     * 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
4283     * the region defined by valueToFind - tolerance and valueToFind + tolerance.
4284     * <p>
4285     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4286     * </p>
4287     * <p>
4288     * 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.
4289     * </p>
4290     *
4291     * @param array       the array to traverse for looking for the object, may be {@code null}.
4292     * @param valueToFind the value to find.
4293     * @param startIndex  the start index to traverse backwards from.
4294     * @param tolerance   search for value within plus/minus this amount.
4295     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4296     */
4297    public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
4298        if (isEmpty(array) || startIndex < 0) {
4299            return INDEX_NOT_FOUND;
4300        }
4301        if (startIndex >= array.length) {
4302            startIndex = array.length - 1;
4303        }
4304        final double min = valueToFind - tolerance;
4305        final double max = valueToFind + tolerance;
4306        for (int i = startIndex; i >= 0; i--) {
4307            if (array[i] >= min && array[i] <= max) {
4308                return i;
4309            }
4310        }
4311        return INDEX_NOT_FOUND;
4312    }
4313
4314    /**
4315     * Finds the last index of the given value within the array.
4316     * <p>
4317     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4318     * </p>
4319     *
4320     * @param array       the array to traverse backwards looking for the object, may be {@code null}.
4321     * @param valueToFind the object to find.
4322     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4323     */
4324    public static int lastIndexOf(final float[] array, final float valueToFind) {
4325        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4326    }
4327
4328    /**
4329     * Finds the last index of the given value in the array starting at the given index.
4330     * <p>
4331     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4332     * </p>
4333     * <p>
4334     * 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.
4335     * </p>
4336     *
4337     * @param array       the array to traverse for looking for the object, may be {@code null}.
4338     * @param valueToFind the value to find.
4339     * @param startIndex  the start index to traverse backwards from.
4340     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4341     */
4342    public static int lastIndexOf(final float[] array, final float valueToFind, int startIndex) {
4343        if (isEmpty(array) || startIndex < 0) {
4344            return INDEX_NOT_FOUND;
4345        }
4346        if (startIndex >= array.length) {
4347            startIndex = array.length - 1;
4348        }
4349        for (int i = startIndex; i >= 0; i--) {
4350            if (valueToFind == array[i]) {
4351                return i;
4352            }
4353        }
4354        return INDEX_NOT_FOUND;
4355    }
4356
4357    /**
4358     * Finds the last index of the given value within the array.
4359     * <p>
4360     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4361     * </p>
4362     *
4363     * @param array       the array to traverse backwards looking for the object, may be {@code null}.
4364     * @param valueToFind the object to find.
4365     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4366     */
4367    public static int lastIndexOf(final int[] array, final int valueToFind) {
4368        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4369    }
4370
4371    /**
4372     * Finds the last index of the given value in the array starting at the given index.
4373     * <p>
4374     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4375     * </p>
4376     * <p>
4377     * 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.
4378     * </p>
4379     *
4380     * @param array       the array to traverse for looking for the object, may be {@code null}.
4381     * @param valueToFind the value to find.
4382     * @param startIndex  the start index to traverse backwards from.
4383     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4384     */
4385    public static int lastIndexOf(final int[] array, final int valueToFind, int startIndex) {
4386        if (array == null || startIndex < 0) {
4387            return INDEX_NOT_FOUND;
4388        }
4389        if (startIndex >= array.length) {
4390            startIndex = array.length - 1;
4391        }
4392        for (int i = startIndex; i >= 0; i--) {
4393            if (valueToFind == array[i]) {
4394                return i;
4395            }
4396        }
4397        return INDEX_NOT_FOUND;
4398    }
4399
4400    /**
4401     * Finds the last index of the given value within the array.
4402     * <p>
4403     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4404     * </p>
4405     *
4406     * @param array       the array to traverse backwards looking for the object, may be {@code null}.
4407     * @param valueToFind the object to find.
4408     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4409     */
4410    public static int lastIndexOf(final long[] array, final long valueToFind) {
4411        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4412    }
4413
4414    /**
4415     * Finds the last index of the given value in the array starting at the given index.
4416     * <p>
4417     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4418     * </p>
4419     * <p>
4420     * 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.
4421     * </p>
4422     *
4423     * @param array       the array to traverse for looking for the object, may be {@code null}.
4424     * @param valueToFind the value to find.
4425     * @param startIndex  the start index to traverse backwards from.
4426     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4427     */
4428    public static int lastIndexOf(final long[] array, final long valueToFind, int startIndex) {
4429        if (array == null || startIndex < 0) {
4430            return INDEX_NOT_FOUND;
4431        }
4432        if (startIndex >= array.length) {
4433            startIndex = array.length - 1;
4434        }
4435        for (int i = startIndex; i >= 0; i--) {
4436            if (valueToFind == array[i]) {
4437                return i;
4438            }
4439        }
4440        return INDEX_NOT_FOUND;
4441    }
4442
4443    /**
4444     * Finds the last index of the given object within the array.
4445     * <p>
4446     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4447     * </p>
4448     *
4449     * @param array        the array to traverse backwards looking for the object, may be {@code null}.
4450     * @param objectToFind the object to find, may be {@code null}.
4451     * @return the last index of the object within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4452     */
4453    public static int lastIndexOf(final Object[] array, final Object objectToFind) {
4454        return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
4455    }
4456
4457    /**
4458     * Finds the last index of the given object in the array starting at the given index.
4459     * <p>
4460     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4461     * </p>
4462     * <p>
4463     * 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.
4464     * </p>
4465     *
4466     * @param array        the array to traverse for looking for the object, may be {@code null}.
4467     * @param objectToFind the object to find, may be {@code null}.
4468     * @param startIndex   the start index to traverse backwards from.
4469     * @return the last index of the object within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4470     */
4471    public static int lastIndexOf(final Object[] array, final Object objectToFind, int startIndex) {
4472        if (array == null || startIndex < 0) {
4473            return INDEX_NOT_FOUND;
4474        }
4475        if (startIndex >= array.length) {
4476            startIndex = array.length - 1;
4477        }
4478        if (objectToFind == null) {
4479            for (int i = startIndex; i >= 0; i--) {
4480                if (array[i] == null) {
4481                    return i;
4482                }
4483            }
4484        } else if (array.getClass().getComponentType().isInstance(objectToFind)) {
4485            for (int i = startIndex; i >= 0; i--) {
4486                if (objectToFind.equals(array[i])) {
4487                    return i;
4488                }
4489            }
4490        }
4491        return INDEX_NOT_FOUND;
4492    }
4493
4494    /**
4495     * Finds the last index of the given value within the array.
4496     * <p>
4497     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4498     * </p>
4499     *
4500     * @param array       the array to traverse backwards looking for the object, may be {@code null}.
4501     * @param valueToFind the object to find.
4502     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4503     */
4504    public static int lastIndexOf(final short[] array, final short valueToFind) {
4505        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4506    }
4507
4508    /**
4509     * Finds the last index of the given value in the array starting at the given index.
4510     * <p>
4511     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4512     * </p>
4513     * <p>
4514     * 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.
4515     * </p>
4516     *
4517     * @param array       the array to traverse for looking for the object, may be {@code null}.
4518     * @param valueToFind the value to find.
4519     * @param startIndex  the start index to traverse backwards from.
4520     * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4521     */
4522    public static int lastIndexOf(final short[] array, final short valueToFind, int startIndex) {
4523        if (array == null || startIndex < 0) {
4524            return INDEX_NOT_FOUND;
4525        }
4526        if (startIndex >= array.length) {
4527            startIndex = array.length - 1;
4528        }
4529        for (int i = startIndex; i >= 0; i--) {
4530            if (valueToFind == array[i]) {
4531                return i;
4532            }
4533        }
4534        return INDEX_NOT_FOUND;
4535    }
4536
4537    /**
4538     * Maps elements from an array into elements of a new array of a given type, while mapping old elements to new elements.
4539     *
4540     * @param <T>           The input array type.
4541     * @param <R>           The output array type.
4542     * @param <E>           The type of exceptions thrown when the mapper function fails.
4543     * @param array         The input array.
4544     * @param componentType the component type of the result array.
4545     * @param mapper        a non-interfering, stateless function to apply to each element.
4546     * @return a new array.
4547     * @throws E Thrown when the mapper function fails.
4548     */
4549    private static <T, R, E extends Throwable> R[] map(final T[] array, final Class<R> componentType, final FailableFunction<? super T, ? extends R, E> mapper)
4550            throws E {
4551        return ArrayFill.fill(newInstance(componentType, array.length), i -> mapper.apply(array[i]));
4552    }
4553
4554    private static int max0(final int other) {
4555        return Math.max(0, other);
4556    }
4557
4558    /**
4559     * Delegates to {@link Array#newInstance(Class,int)} using generics.
4560     *
4561     * @param <T> The array type.
4562     * @param componentType The array class.
4563     * @param length the array length
4564     * @return The new array.
4565     * @throws NullPointerException if the specified {@code componentType} parameter is null.
4566     * @since 3.13.0
4567     */
4568    @SuppressWarnings("unchecked") // OK, because array and values are of type T
4569    public static <T> T[] newInstance(final Class<T> componentType, final int length) {
4570        return (T[]) Array.newInstance(componentType, length);
4571    }
4572
4573    /**
4574     * Defensive programming technique to change a {@code null}
4575     * reference to an empty one.
4576     * <p>
4577     * This method returns a default array for a {@code null} input array.
4578     * </p>
4579     * <p>
4580     * As a memory optimizing technique an empty array passed in will be overridden with
4581     * the empty {@code public static} references in this class.
4582     * </p>
4583     *
4584     * @param <T> The array type.
4585     * @param array  the array to check for {@code null} or empty
4586     * @param defaultArray A default array, usually empty.
4587     * @return the same array, or defaultArray if {@code null} or empty input.
4588     * @since 3.15.0
4589     */
4590    public static <T> T[] nullTo(final T[] array, final T[] defaultArray) {
4591        return isEmpty(array) ? defaultArray : array;
4592    }
4593
4594    /**
4595     * Defensive programming technique to change a {@code null}
4596     * reference to an empty one.
4597     * <p>
4598     * This method returns an empty array for a {@code null} input array.
4599     * </p>
4600     * <p>
4601     * As a memory optimizing technique an empty array passed in will be overridden with
4602     * the empty {@code public static} references in this class.
4603     * </p>
4604     *
4605     * @param array  the array to check for {@code null} or empty.
4606     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4607     * @since 2.5
4608     */
4609    public static boolean[] nullToEmpty(final boolean[] array) {
4610        return isEmpty(array) ? EMPTY_BOOLEAN_ARRAY : array;
4611    }
4612
4613    /**
4614     * Defensive programming technique to change a {@code null}
4615     * reference to an empty one.
4616     * <p>
4617     * This method returns an empty array for a {@code null} input array.
4618     * </p>
4619     * <p>
4620     * As a memory optimizing technique an empty array passed in will be overridden with
4621     * the empty {@code public static} references in this class.
4622     * </p>
4623     *
4624     * @param array  the array to check for {@code null} or empty.
4625     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4626     * @since 2.5
4627     */
4628    public static Boolean[] nullToEmpty(final Boolean[] array) {
4629        return nullTo(array, EMPTY_BOOLEAN_OBJECT_ARRAY);
4630    }
4631
4632    /**
4633     * Defensive programming technique to change a {@code null}
4634     * reference to an empty one.
4635     * <p>
4636     * This method returns an empty array for a {@code null} input array.
4637     * </p>
4638     * <p>
4639     * As a memory optimizing technique an empty array passed in will be overridden with
4640     * the empty {@code public static} references in this class.
4641     * </p>
4642     *
4643     * @param array  the array to check for {@code null} or empty.
4644     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4645     * @since 2.5
4646     */
4647    public static byte[] nullToEmpty(final byte[] array) {
4648        return isEmpty(array) ? EMPTY_BYTE_ARRAY : array;
4649    }
4650
4651    /**
4652     * Defensive programming technique to change a {@code null}
4653     * reference to an empty one.
4654     * <p>
4655     * This method returns an empty array for a {@code null} input array.
4656     * </p>
4657     * <p>
4658     * As a memory optimizing technique an empty array passed in will be overridden with
4659     * the empty {@code public static} references in this class.
4660     * </p>
4661     *
4662     * @param array  the array to check for {@code null} or empty.
4663     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4664     * @since 2.5
4665     */
4666    public static Byte[] nullToEmpty(final Byte[] array) {
4667        return nullTo(array, EMPTY_BYTE_OBJECT_ARRAY);
4668    }
4669
4670    /**
4671     * Defensive programming technique to change a {@code null}
4672     * reference to an empty one.
4673     * <p>
4674     * This method returns an empty 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 array  the array to check for {@code null} or empty.
4682     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4683     * @since 2.5
4684     */
4685    public static char[] nullToEmpty(final char[] array) {
4686        return isEmpty(array) ? EMPTY_CHAR_ARRAY : array;
4687    }
4688
4689    /**
4690     * Defensive programming technique to change a {@code null}
4691     * reference to an empty one.
4692     * <p>
4693     * This method returns an empty array for a {@code null} input array.
4694     * </p>
4695     * <p>
4696     * As a memory optimizing technique an empty array passed in will be overridden with
4697     * the empty {@code public static} references in this class.
4698     * </p>
4699     *
4700     * @param array  the array to check for {@code null} or empty.
4701     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4702     * @since 2.5
4703     */
4704    public static Character[] nullToEmpty(final Character[] array) {
4705        return nullTo(array, EMPTY_CHARACTER_OBJECT_ARRAY);
4706    }
4707
4708    /**
4709     * Defensive programming technique to change a {@code null}
4710     * reference to an empty one.
4711     * <p>
4712     * This method returns an empty array for a {@code null} input array.
4713     * </p>
4714     * <p>
4715     * As a memory optimizing technique an empty array passed in will be overridden with
4716     * the empty {@code public static} references in this class.
4717     * </p>
4718     *
4719     * @param array  the array to check for {@code null} or empty.
4720     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4721     * @since 3.2
4722     */
4723    public static Class<?>[] nullToEmpty(final Class<?>[] array) {
4724        return nullTo(array, EMPTY_CLASS_ARRAY);
4725    }
4726
4727    /**
4728     * Defensive programming technique to change a {@code null}
4729     * reference to an empty one.
4730     * <p>
4731     * This method returns an empty array for a {@code null} input array.
4732     * </p>
4733     * <p>
4734     * As a memory optimizing technique an empty array passed in will be overridden with
4735     * the empty {@code public static} references in this class.
4736     * </p>
4737     *
4738     * @param array  the array to check for {@code null} or empty.
4739     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4740     * @since 2.5
4741     */
4742    public static double[] nullToEmpty(final double[] array) {
4743        return isEmpty(array) ? EMPTY_DOUBLE_ARRAY : array;
4744    }
4745
4746    /**
4747     * Defensive programming technique to change a {@code null}
4748     * reference to an empty one.
4749     * <p>
4750     * This method returns an empty array for a {@code null} input array.
4751     * </p>
4752     * <p>
4753     * As a memory optimizing technique an empty array passed in will be overridden with
4754     * the empty {@code public static} references in this class.
4755     * </p>
4756     *
4757     * @param array  the array to check for {@code null} or empty.
4758     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4759     * @since 2.5
4760     */
4761    public static Double[] nullToEmpty(final Double[] array) {
4762        return nullTo(array, EMPTY_DOUBLE_OBJECT_ARRAY);
4763    }
4764
4765    /**
4766     * Defensive programming technique to change a {@code null}
4767     * reference to an empty one.
4768     * <p>
4769     * This method returns an empty array for a {@code null} input array.
4770     * </p>
4771     * <p>
4772     * As a memory optimizing technique an empty array passed in will be overridden with
4773     * the empty {@code public static} references in this class.
4774     * </p>
4775     *
4776     * @param array  the array to check for {@code null} or empty.
4777     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4778     * @since 2.5
4779     */
4780    public static float[] nullToEmpty(final float[] array) {
4781        return isEmpty(array) ? EMPTY_FLOAT_ARRAY : array;
4782    }
4783
4784    /**
4785     * Defensive programming technique to change a {@code null}
4786     * reference to an empty one.
4787     * <p>
4788     * This method returns an empty array for a {@code null} input array.
4789     * </p>
4790     * <p>
4791     * As a memory optimizing technique an empty array passed in will be overridden with
4792     * the empty {@code public static} references in this class.
4793     * </p>
4794     *
4795     * @param array  the array to check for {@code null} or empty.
4796     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4797     * @since 2.5
4798     */
4799    public static Float[] nullToEmpty(final Float[] array) {
4800        return nullTo(array, EMPTY_FLOAT_OBJECT_ARRAY);
4801    }
4802
4803    /**
4804     * Defensive programming technique to change a {@code null}
4805     * reference to an empty one.
4806     * <p>
4807     * This method returns an empty array for a {@code null} input array.
4808     * </p>
4809     * <p>
4810     * As a memory optimizing technique an empty array passed in will be overridden with
4811     * the empty {@code public static} references in this class.
4812     * </p>
4813     *
4814     * @param array  the array to check for {@code null} or empty.
4815     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4816     * @since 2.5
4817     */
4818    public static int[] nullToEmpty(final int[] array) {
4819        return isEmpty(array) ? EMPTY_INT_ARRAY : array;
4820    }
4821
4822    /**
4823     * Defensive programming technique to change a {@code null}
4824     * reference to an empty one.
4825     * <p>
4826     * This method returns an empty array for a {@code null} input array.
4827     * </p>
4828     * <p>
4829     * As a memory optimizing technique an empty array passed in will be overridden with
4830     * the empty {@code public static} references in this class.
4831     * </p>
4832     *
4833     * @param array  the array to check for {@code null} or empty.
4834     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4835     * @since 2.5
4836     */
4837    public static Integer[] nullToEmpty(final Integer[] array) {
4838        return nullTo(array, EMPTY_INTEGER_OBJECT_ARRAY);
4839    }
4840
4841    /**
4842     * Defensive programming technique to change a {@code null}
4843     * reference to an empty one.
4844     * <p>
4845     * This method returns an empty array for a {@code null} input array.
4846     * </p>
4847     * <p>
4848     * As a memory optimizing technique an empty array passed in will be overridden with
4849     * the empty {@code public static} references in this class.
4850     * </p>
4851     *
4852     * @param array  the array to check for {@code null} or empty.
4853     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4854     * @since 2.5
4855     */
4856    public static long[] nullToEmpty(final long[] array) {
4857        return isEmpty(array) ? EMPTY_LONG_ARRAY : array;
4858    }
4859
4860    /**
4861     * Defensive programming technique to change a {@code null}
4862     * reference to an empty one.
4863     * <p>
4864     * This method returns an empty array for a {@code null} input array.
4865     * </p>
4866     * <p>
4867     * As a memory optimizing technique an empty array passed in will be overridden with
4868     * the empty {@code public static} references in this class.
4869     * </p>
4870     *
4871     * @param array  the array to check for {@code null} or empty.
4872     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4873     * @since 2.5
4874     */
4875    public static Long[] nullToEmpty(final Long[] array) {
4876        return nullTo(array, EMPTY_LONG_OBJECT_ARRAY);
4877    }
4878
4879    /**
4880     * Defensive programming technique to change a {@code null}
4881     * reference to an empty one.
4882     * <p>
4883     * This method returns an empty array for a {@code null} input array.
4884     * </p>
4885     * <p>
4886     * As a memory optimizing technique an empty array passed in will be overridden with
4887     * the empty {@code public static} references in this class.
4888     * </p>
4889     *
4890     * @param array  the array to check for {@code null} or empty.
4891     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4892     * @since 2.5
4893     */
4894    public static Object[] nullToEmpty(final Object[] array) {
4895        return nullTo(array, EMPTY_OBJECT_ARRAY);
4896    }
4897
4898    /**
4899     * Defensive programming technique to change a {@code null}
4900     * reference to an empty one.
4901     * <p>
4902     * This method returns an empty array for a {@code null} input array.
4903     * </p>
4904     * <p>
4905     * As a memory optimizing technique an empty array passed in will be overridden with
4906     * the empty {@code public static} references in this class.
4907     * </p>
4908     *
4909     * @param array  the array to check for {@code null} or empty.
4910     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4911     * @since 2.5
4912     */
4913    public static short[] nullToEmpty(final short[] array) {
4914        return isEmpty(array) ? EMPTY_SHORT_ARRAY : array;
4915    }
4916
4917    /**
4918     * Defensive programming technique to change a {@code null}
4919     * reference to an empty one.
4920     * <p>
4921     * This method returns an empty array for a {@code null} input array.
4922     * </p>
4923     * <p>
4924     * As a memory optimizing technique an empty array passed in will be overridden with
4925     * the empty {@code public static} references in this class.
4926     * </p>
4927     *
4928     * @param array  the array to check for {@code null} or empty.
4929     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4930     * @since 2.5
4931     */
4932    public static Short[] nullToEmpty(final Short[] array) {
4933        return nullTo(array, EMPTY_SHORT_OBJECT_ARRAY);
4934    }
4935
4936    /**
4937     * Defensive programming technique to change a {@code null}
4938     * reference to an empty one.
4939     * <p>
4940     * This method returns an empty array for a {@code null} input array.
4941     * </p>
4942     * <p>
4943     * As a memory optimizing technique an empty array passed in will be overridden with
4944     * the empty {@code public static} references in this class.
4945     * </p>
4946     *
4947     * @param array  the array to check for {@code null} or empty.
4948     * @return the same array, {@code public static} empty array if {@code null} or empty input.
4949     * @since 2.5
4950     */
4951    public static String[] nullToEmpty(final String[] array) {
4952        return nullTo(array, EMPTY_STRING_ARRAY);
4953    }
4954
4955    /**
4956     * Defensive programming technique to change a {@code null}
4957     * reference to an empty one.
4958     * <p>
4959     * This method returns an empty array for a {@code null} input array.
4960     * </p>
4961     *
4962     * @param array  the array to check for {@code null} or empty.
4963     * @param type   the class representation of the desired array.
4964     * @param <T>  the class type.
4965     * @return the same array, {@code public static} empty array if {@code null}.
4966     * @throws IllegalArgumentException if the type argument is null.
4967     * @since 3.5
4968     */
4969    public static <T> T[] nullToEmpty(final T[] array, final Class<T[]> type) {
4970        if (type == null) {
4971            throw new IllegalArgumentException("The type must not be null");
4972        }
4973        if (array == null) {
4974            return type.cast(Array.newInstance(type.getComponentType(), 0));
4975        }
4976        return array;
4977    }
4978
4979    /**
4980     * Gets the {@link ThreadLocalRandom} for {@code shuffle} methods that don't take a {@link Random} argument.
4981     *
4982     * @return the current ThreadLocalRandom.
4983     */
4984    private static ThreadLocalRandom random() {
4985        return ThreadLocalRandom.current();
4986    }
4987
4988    /**
4989     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
4990     * indices).
4991     * <p>
4992     * 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
4993     * returned array is always the same as that of the input array.
4994     * </p>
4995     * <p>
4996     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
4997     * </p>
4998     *
4999     * <pre>
5000     * ArrayUtils.remove([true], 0)              = []
5001     * ArrayUtils.remove([true, false], 0)       = [false]
5002     * ArrayUtils.remove([true, false], 1)       = [true]
5003     * ArrayUtils.remove([true, true, false], 1) = [true, false]
5004     * </pre>
5005     *
5006     * @param array the array to remove the element from, may not be {@code null}.
5007     * @param index the position of the element to be removed.
5008     * @return A new array containing the existing elements except the element at the specified position.
5009     * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5010     * @since 2.1
5011     */
5012    public static boolean[] remove(final boolean[] array, final int index) {
5013        return (boolean[]) remove((Object) array, index);
5014    }
5015
5016    /**
5017     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5018     * indices).
5019     * <p>
5020     * 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
5021     * returned array is always the same as that of the input array.
5022     * </p>
5023     * <p>
5024     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5025     * </p>
5026     *
5027     * <pre>
5028     * ArrayUtils.remove([1], 0)          = []
5029     * ArrayUtils.remove([1, 0], 0)       = [0]
5030     * ArrayUtils.remove([1, 0], 1)       = [1]
5031     * ArrayUtils.remove([1, 0, 1], 1)    = [1, 1]
5032     * </pre>
5033     *
5034     * @param array the array to remove the element from, may not be {@code null}.
5035     * @param index the position of the element to be removed.
5036     * @return A new array containing the existing elements except the element at the specified position.
5037     * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5038     * @since 2.1
5039     */
5040    public static byte[] remove(final byte[] array, final int index) {
5041        return (byte[]) remove((Object) array, index);
5042    }
5043
5044    /**
5045     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5046     * indices).
5047     * <p>
5048     * 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
5049     * returned array is always the same as that of the input array.
5050     * </p>
5051     * <p>
5052     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5053     * </p>
5054     *
5055     * <pre>
5056     * ArrayUtils.remove(['a'], 0)           = []
5057     * ArrayUtils.remove(['a', 'b'], 0)      = ['b']
5058     * ArrayUtils.remove(['a', 'b'], 1)      = ['a']
5059     * ArrayUtils.remove(['a', 'b', 'c'], 1) = ['a', 'c']
5060     * </pre>
5061     *
5062     * @param array the array to remove the element from, may not be {@code null}.
5063     * @param index the position of the element to be removed.
5064     * @return A new array containing the existing elements except the element at the specified position.
5065     * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5066     * @since 2.1
5067     */
5068    public static char[] remove(final char[] array, final int index) {
5069        return (char[]) remove((Object) array, index);
5070    }
5071
5072    /**
5073     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5074     * indices).
5075     * <p>
5076     * 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
5077     * returned array is always the same as that of the input array.
5078     * </p>
5079     * <p>
5080     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5081     * </p>
5082     *
5083     * <pre>
5084     * ArrayUtils.remove([1.1], 0)           = []
5085     * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
5086     * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
5087     * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
5088     * </pre>
5089     *
5090     * @param array the array to remove the element from, may not be {@code null}.
5091     * @param index the position of the element to be removed.
5092     * @return A new array containing the existing elements except the element at the specified position.
5093     * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5094     * @since 2.1
5095     */
5096    public static double[] remove(final double[] array, final int index) {
5097        return (double[]) remove((Object) array, index);
5098    }
5099
5100    /**
5101     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5102     * indices).
5103     * <p>
5104     * 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
5105     * returned array is always the same as that of the input array.
5106     * </p>
5107     * <p>
5108     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5109     * </p>
5110     *
5111     * <pre>
5112     * ArrayUtils.remove([1.1], 0)           = []
5113     * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
5114     * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
5115     * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
5116     * </pre>
5117     *
5118     * @param array the array to remove the element from, may not be {@code null}.
5119     * @param index the position of the element to be removed.
5120     * @return A new array containing the existing elements except the element at the specified position.
5121     * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5122     * @since 2.1
5123     */
5124    public static float[] remove(final float[] array, final int index) {
5125        return (float[]) remove((Object) array, index);
5126    }
5127
5128    /**
5129     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5130     * indices).
5131     * <p>
5132     * 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
5133     * returned array is always the same as that of the input array.
5134     * </p>
5135     * <p>
5136     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5137     * </p>
5138     *
5139     * <pre>
5140     * ArrayUtils.remove([1], 0)         = []
5141     * ArrayUtils.remove([2, 6], 0)      = [6]
5142     * ArrayUtils.remove([2, 6], 1)      = [2]
5143     * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
5144     * </pre>
5145     *
5146     * @param array the array to remove the element from, may not be {@code null}.
5147     * @param index the position of the element to be removed.
5148     * @return A new array containing the existing elements except the element at the specified position.
5149     * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5150     * @since 2.1
5151     */
5152    public static int[] remove(final int[] array, final int index) {
5153        return (int[]) remove((Object) array, index);
5154    }
5155
5156    /**
5157     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5158     * indices).
5159     * <p>
5160     * 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
5161     * returned array is always the same as that of the input array.
5162     * </p>
5163     * <p>
5164     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5165     * </p>
5166     *
5167     * <pre>
5168     * ArrayUtils.remove([1], 0)         = []
5169     * ArrayUtils.remove([2, 6], 0)      = [6]
5170     * ArrayUtils.remove([2, 6], 1)      = [2]
5171     * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
5172     * </pre>
5173     *
5174     * @param array the array to remove the element from, may not be {@code null}.
5175     * @param index the position of the element to be removed.
5176     * @return A new array containing the existing elements except the element at the specified position.
5177     * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5178     * @since 2.1
5179     */
5180    public static long[] remove(final long[] array, final int index) {
5181        return (long[]) remove((Object) array, index);
5182    }
5183
5184    /**
5185     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5186     * indices).
5187     * <p>
5188     * 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
5189     * returned array is always the same as that of the input array.
5190     * </p>
5191     * <p>
5192     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5193     * </p>
5194     *
5195     * @param array the array to remove the element from, may not be {@code null}.
5196     * @param index the position of the element to be removed.
5197     * @return A new array containing the existing elements except the element at the specified position.
5198     * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5199     * @since 2.1
5200     */
5201    private static Object remove(final Object array, final int index) {
5202        final int length = getLength(array);
5203        if (index < 0 || index >= length) {
5204            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
5205        }
5206        final Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
5207        System.arraycopy(array, 0, result, 0, index);
5208        if (index < length - 1) {
5209            System.arraycopy(array, index + 1, result, index, length - index - 1);
5210        }
5211        return result;
5212    }
5213
5214    /**
5215     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5216     * indices).
5217     * <p>
5218     * 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
5219     * returned array is always the same as that of the input array.
5220     * </p>
5221     * <p>
5222     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5223     * </p>
5224     *
5225     * <pre>
5226     * ArrayUtils.remove([1], 0)         = []
5227     * ArrayUtils.remove([2, 6], 0)      = [6]
5228     * ArrayUtils.remove([2, 6], 1)      = [2]
5229     * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
5230     * </pre>
5231     *
5232     * @param array the array to remove the element from, may not be {@code null}.
5233     * @param index the position of the element to be removed.
5234     * @return A new array containing the existing elements except the element at the specified position.
5235     * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5236     * @since 2.1
5237     */
5238    public static short[] remove(final short[] array, final int index) {
5239        return (short[]) remove((Object) array, index);
5240    }
5241
5242    /**
5243     * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5244     * indices).
5245     * <p>
5246     * 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
5247     * returned array is always the same as that of the input array.
5248     * </p>
5249     * <p>
5250     * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5251     * </p>
5252     *
5253     * <pre>
5254     * ArrayUtils.remove(["a"], 0)           = []
5255     * ArrayUtils.remove(["a", "b"], 0)      = ["b"]
5256     * ArrayUtils.remove(["a", "b"], 1)      = ["a"]
5257     * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"]
5258     * </pre>
5259     *
5260     * @param <T>   the component type of the array.
5261     * @param array the array to remove the element from, may not be {@code null}.
5262     * @param index the position of the element to be removed.
5263     * @return A new array containing the existing elements except the element at the specified position.
5264     * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5265     * @since 2.1
5266     */
5267    @SuppressWarnings("unchecked") // remove() always creates an array of the same type as its input
5268    public static <T> T[] remove(final T[] array, final int index) {
5269        return (T[]) remove((Object) array, index);
5270    }
5271
5272    /**
5273     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5274     * <p>
5275     * 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
5276     * array is always the same as that of the input array.
5277     * </p>
5278     * <p>
5279     * If the input array is {@code null}, then return {@code null}.
5280     * </p>
5281     *
5282     * <pre>
5283     * ArrayUtils.removeAll([true, false, true], 0, 2) = [false]
5284     * ArrayUtils.removeAll([true, false, true], 1, 2) = [true]
5285     * </pre>
5286     *
5287     * @param array   the array to remove the element from, may not be {@code null}.
5288     * @param indices the positions of the elements to be removed.
5289     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5290     * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5291     * @since 3.0.1
5292     */
5293    public static boolean[] removeAll(final boolean[] array, final int... indices) {
5294        return (boolean[]) removeAll((Object) array, indices);
5295    }
5296
5297    /**
5298     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5299     * <p>
5300     * 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
5301     * array is always the same as that of the input array.
5302     * </p>
5303     * <p>
5304     * If the input array is {@code null}, then return {@code null}.
5305     * </p>
5306     *
5307     * <pre>
5308     * ArrayUtils.removeAll([1], 0)             = []
5309     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5310     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5311     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5312     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5313     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5314     * </pre>
5315     *
5316     * @param array   the array to remove the element from, may not be {@code null}.
5317     * @param indices the positions of the elements to be removed.
5318     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5319     * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5320     * @since 3.0.1
5321     */
5322    public static byte[] removeAll(final byte[] array, final int... indices) {
5323        return (byte[]) removeAll((Object) array, indices);
5324    }
5325
5326    /**
5327     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5328     * <p>
5329     * 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
5330     * array is always the same as that of the input array.
5331     * </p>
5332     * <p>
5333     * If the input array is {@code null}, then return {@code null}.
5334     * </p>
5335     *
5336     * <pre>
5337     * ArrayUtils.removeAll([1], 0)             = []
5338     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5339     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5340     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5341     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5342     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5343     * </pre>
5344     *
5345     * @param array   the array to remove the element from, may not be {@code null}.
5346     * @param indices the positions of the elements to be removed.
5347     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5348     * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5349     * @since 3.0.1
5350     */
5351    public static char[] removeAll(final char[] array, final int... indices) {
5352        return (char[]) removeAll((Object) array, indices);
5353    }
5354
5355    /**
5356     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5357     * <p>
5358     * 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
5359     * array is always the same as that of the input array.
5360     * </p>
5361     * <p>
5362     * If the input array is {@code null}, then return {@code null}.
5363     * </p>
5364     *
5365     * <pre>
5366     * ArrayUtils.removeAll([1], 0)             = []
5367     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5368     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5369     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5370     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5371     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5372     * </pre>
5373     *
5374     * @param array   the array to remove the element from, may not be {@code null}.
5375     * @param indices the positions of the elements to be removed.
5376     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5377     * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5378     * @since 3.0.1
5379     */
5380    public static double[] removeAll(final double[] array, final int... indices) {
5381        return (double[]) removeAll((Object) array, indices);
5382    }
5383
5384    /**
5385     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5386     * <p>
5387     * 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
5388     * array is always the same as that of the input array.
5389     * </p>
5390     * <p>
5391     * If the input array is {@code null}, then return {@code null}.
5392     * </p>
5393     *
5394     * <pre>
5395     * ArrayUtils.removeAll([1], 0)             = []
5396     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5397     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5398     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5399     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5400     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5401     * </pre>
5402     *
5403     * @param array   the array to remove the element from, may not be {@code null}.
5404     * @param indices the positions of the elements to be removed.
5405     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5406     * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5407     * @since 3.0.1
5408     */
5409    public static float[] removeAll(final float[] array, final int... indices) {
5410        return (float[]) removeAll((Object) array, indices);
5411    }
5412
5413    /**
5414     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5415     * <p>
5416     * 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
5417     * array is always the same as that of the input array.
5418     * </p>
5419     * <p>
5420     * If the input array is {@code null}, then return {@code null}.
5421     * </p>
5422     *
5423     * <pre>
5424     * ArrayUtils.removeAll([1], 0)             = []
5425     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5426     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5427     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5428     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5429     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5430     * </pre>
5431     *
5432     * @param array   the array to remove the element from, may not be {@code null}.
5433     * @param indices the positions of the elements to be removed.
5434     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5435     * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5436     * @since 3.0.1
5437     */
5438    public static int[] removeAll(final int[] array, final int... indices) {
5439        return (int[]) removeAll((Object) array, indices);
5440    }
5441
5442    /**
5443     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5444     * <p>
5445     * 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
5446     * array is always the same as that of the input array.
5447     * </p>
5448     * <p>
5449     * If the input array is {@code null}, then return {@code null}.
5450     * </p>
5451     *
5452     * <pre>
5453     * ArrayUtils.removeAll([1], 0)             = []
5454     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5455     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5456     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5457     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5458     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5459     * </pre>
5460     *
5461     * @param array   the array to remove the element from, may not be {@code null}.
5462     * @param indices the positions of the elements to be removed.
5463     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5464     * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5465     * @since 3.0.1
5466     */
5467    public static long[] removeAll(final long[] array, final int... indices) {
5468        return (long[]) removeAll((Object) array, indices);
5469    }
5470
5471    /**
5472     * Removes multiple array elements specified by index.
5473     *
5474     * @param array   source
5475     * @param indices to remove
5476     * @return new array of same type minus elements specified by unique values of {@code indices}
5477     */
5478    // package protected for access by unit tests
5479    static Object removeAll(final Object array, final int... indices) {
5480        if (array == null) {
5481            return null;
5482        }
5483        final int length = getLength(array);
5484        int diff = 0; // number of distinct indexes, i.e. number of entries that will be removed
5485        final int[] clonedIndices = ArraySorter.sort(clone(indices));
5486        // identify length of result array
5487        if (isNotEmpty(clonedIndices)) {
5488            int i = clonedIndices.length;
5489            int prevIndex = length;
5490            while (--i >= 0) {
5491                final int index = clonedIndices[i];
5492                if (index < 0 || index >= length) {
5493                    throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
5494                }
5495                if (index >= prevIndex) {
5496                    continue;
5497                }
5498                diff++;
5499                prevIndex = index;
5500            }
5501        }
5502        // create result array
5503        final Object result = Array.newInstance(array.getClass().getComponentType(), length - diff);
5504        if (diff < length && clonedIndices != null) {
5505            int end = length; // index just after last copy
5506            int dest = length - diff; // number of entries so far not copied
5507            for (int i = clonedIndices.length - 1; i >= 0; i--) {
5508                final int index = clonedIndices[i];
5509                if (end - index > 1) { // same as (cp > 0)
5510                    final int cp = end - index - 1;
5511                    dest -= cp;
5512                    System.arraycopy(array, index + 1, result, dest, cp);
5513                    // After this copy, we still have room for dest items.
5514                }
5515                end = index;
5516            }
5517            if (end > 0) {
5518                System.arraycopy(array, 0, result, 0, end);
5519            }
5520        }
5521        return result;
5522    }
5523
5524    /**
5525     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5526     * <p>
5527     * 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
5528     * array is always the same as that of the input array.
5529     * </p>
5530     * <p>
5531     * If the input array is {@code null}, then return {@code null}.
5532     * </p>
5533     *
5534     * <pre>
5535     * ArrayUtils.removeAll([1], 0)             = []
5536     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5537     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5538     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5539     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5540     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5541     * </pre>
5542     *
5543     * @param array   the array to remove the element from, may not be {@code null}.
5544     * @param indices the positions of the elements to be removed.
5545     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5546     * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5547     * @since 3.0.1
5548     */
5549    public static short[] removeAll(final short[] array, final int... indices) {
5550        return (short[]) removeAll((Object) array, indices);
5551    }
5552
5553    /**
5554     * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5555     * <p>
5556     * 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
5557     * array is always the same as that of the input array.
5558     * </p>
5559     * <p>
5560     * If the input array is {@code null}, then return {@code null}.
5561     * </p>
5562     *
5563     * <pre>
5564     * ArrayUtils.removeAll(["a", "b", "c"], 0, 2) = ["b"]
5565     * ArrayUtils.removeAll(["a", "b", "c"], 1, 2) = ["a"]
5566     * </pre>
5567     *
5568     * @param <T>     the component type of the array.
5569     * @param array   the array to remove the element from, may not be {@code null}.
5570     * @param indices the positions of the elements to be removed.
5571     * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5572     * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5573     * @since 3.0.1
5574     */
5575    @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
5576    public static <T> T[] removeAll(final T[] array, final int... indices) {
5577        return (T[]) removeAll((Object) array, indices);
5578    }
5579
5580    /**
5581     * Removes the occurrences of the specified element from the specified boolean array.
5582     * <p>
5583     * All subsequent elements are shifted to the left (subtracts one from their indices).
5584     * If the array doesn't contain such an element, no elements are removed from the array.
5585     * {@code null} will be returned if the input array is {@code null}.
5586     * </p>
5587     *
5588     * @param array the input array, will not be modified, and may be {@code null}.
5589     * @param element the element to remove.
5590     * @return A new array containing the existing elements except the occurrences of the specified element.
5591     * @since 3.5
5592     * @deprecated Use {@link #removeAllOccurrences(boolean[], boolean)}.
5593     */
5594    @Deprecated
5595    public static boolean[] removeAllOccurences(final boolean[] array, final boolean element) {
5596        return (boolean[]) removeAt(array, indexesOf(array, element));
5597    }
5598
5599    /**
5600     * Removes the occurrences of the specified element from the specified byte array.
5601     * <p>
5602     * All subsequent elements are shifted to the left (subtracts one from their indices).
5603     * If the array doesn't contain such an element, no elements are removed from the array.
5604     * {@code null} will be returned if the input array is {@code null}.
5605     * </p>
5606     *
5607     * @param array the input array, will not be modified, and may be {@code null}.
5608     * @param element the element to remove.
5609     * @return A new array containing the existing elements except the occurrences of the specified element.
5610     * @since 3.5
5611     * @deprecated Use {@link #removeAllOccurrences(byte[], byte)}.
5612     */
5613    @Deprecated
5614    public static byte[] removeAllOccurences(final byte[] array, final byte element) {
5615        return (byte[]) removeAt(array, indexesOf(array, element));
5616    }
5617
5618    /**
5619     * Removes the occurrences of the specified element from the specified char array.
5620     * <p>
5621     * All subsequent elements are shifted to the left (subtracts one from their indices).
5622     * If the array doesn't contain such an element, no elements are removed from the array.
5623     * {@code null} will be returned if the input array is {@code null}.
5624     * </p>
5625     *
5626     * @param array the input array, will not be modified, and may be {@code null}.
5627     * @param element the element to remove.
5628     * @return A new array containing the existing elements except the occurrences of the specified element.
5629     * @since 3.5
5630     * @deprecated Use {@link #removeAllOccurrences(char[], char)}.
5631     */
5632    @Deprecated
5633    public static char[] removeAllOccurences(final char[] array, final char element) {
5634        return (char[]) removeAt(array, indexesOf(array, element));
5635    }
5636
5637    /**
5638     * Removes the occurrences of the specified element from the specified double array.
5639     * <p>
5640     * All subsequent elements are shifted to the left (subtracts one from their indices).
5641     * If the array doesn't contain such an element, no elements are removed from the array.
5642     * {@code null} will be returned if the input array is {@code null}.
5643     * </p>
5644     *
5645     * @param array the input array, will not be modified, and may be {@code null}.
5646     * @param element the element to remove.
5647     * @return A new array containing the existing elements except the occurrences of the specified element.
5648     * @since 3.5
5649     * @deprecated Use {@link #removeAllOccurrences(double[], double)}.
5650     */
5651    @Deprecated
5652    public static double[] removeAllOccurences(final double[] array, final double element) {
5653        return (double[]) removeAt(array, indexesOf(array, element));
5654    }
5655
5656    /**
5657     * Removes the occurrences of the specified element from the specified float array.
5658     * <p>
5659     * All subsequent elements are shifted to the left (subtracts one from their indices).
5660     * If the array doesn't contain such an element, no elements are removed from the array.
5661     * {@code null} will be returned if the input array is {@code null}.
5662     * </p>
5663     *
5664     * @param array the input array, will not be modified, and may be {@code null}.
5665     * @param element the element to remove.
5666     * @return A new array containing the existing elements except the occurrences of the specified element.
5667     * @since 3.5
5668     * @deprecated Use {@link #removeAllOccurrences(float[], float)}.
5669     */
5670    @Deprecated
5671    public static float[] removeAllOccurences(final float[] array, final float element) {
5672        return (float[]) removeAt(array, indexesOf(array, element));
5673    }
5674
5675    /**
5676     * Removes the occurrences of the specified element from the specified int array.
5677     * <p>
5678     * All subsequent elements are shifted to the left (subtracts one from their indices).
5679     * If the array doesn't contain such an element, no elements are removed from the array.
5680     * {@code null} will be returned if the input array is {@code null}.
5681     * </p>
5682     *
5683     * @param array the input array, will not be modified, and may be {@code null}.
5684     * @param element the element to remove.
5685     * @return A new array containing the existing elements except the occurrences of the specified element.
5686     * @since 3.5
5687     * @deprecated Use {@link #removeAllOccurrences(int[], int)}.
5688     */
5689    @Deprecated
5690    public static int[] removeAllOccurences(final int[] array, final int element) {
5691        return (int[]) removeAt(array, indexesOf(array, element));
5692    }
5693
5694    /**
5695     * Removes the occurrences of the specified element from the specified long array.
5696     * <p>
5697     * All subsequent elements are shifted to the left (subtracts one from their indices).
5698     * If the array doesn't contain such an element, no elements are removed from the array.
5699     * {@code null} will be returned if the input array is {@code null}.
5700     * </p>
5701     *
5702     * @param array the input array, will not be modified, and may be {@code null}.
5703     * @param element the element to remove.
5704     * @return A new array containing the existing elements except the occurrences of the specified element.
5705     * @since 3.5
5706     * @deprecated Use {@link #removeAllOccurrences(long[], long)}.
5707     */
5708    @Deprecated
5709    public static long[] removeAllOccurences(final long[] array, final long element) {
5710        return (long[]) removeAt(array, indexesOf(array, element));
5711    }
5712
5713    /**
5714     * Removes the occurrences of the specified element from the specified short array.
5715     * <p>
5716     * All subsequent elements are shifted to the left (subtracts one from their indices).
5717     * If the array doesn't contain such an element, no elements are removed from the array.
5718     * {@code null} will be returned if the input array is {@code null}.
5719     * </p>
5720     *
5721     * @param array the input array, will not be modified, and may be {@code null}.
5722     * @param element the element to remove.
5723     * @return A new array containing the existing elements except the occurrences of the specified element.
5724     * @since 3.5
5725     * @deprecated Use {@link #removeAllOccurrences(short[], short)}.
5726     */
5727    @Deprecated
5728    public static short[] removeAllOccurences(final short[] array, final short element) {
5729        return (short[]) removeAt(array, indexesOf(array, element));
5730    }
5731
5732    /**
5733     * Removes the occurrences of the specified element from the specified array.
5734     * <p>
5735     * All subsequent elements are shifted to the left (subtracts one from their indices).
5736     * If the array doesn't contain such an element, no elements are removed from the array.
5737     * {@code null} will be returned if the input array is {@code null}.
5738     * </p>
5739     *
5740     * @param <T> the type of object in the array, may be {@code null}.
5741     * @param array the input array, will not be modified, and may be {@code null}.
5742     * @param element the element to remove, may be {@code null}.
5743     * @return A new array containing the existing elements except the occurrences of the specified element.
5744     * @since 3.5
5745     * @deprecated Use {@link #removeAllOccurrences(Object[], Object)}.
5746     */
5747    @Deprecated
5748    public static <T> T[] removeAllOccurences(final T[] array, final T element) {
5749        return (T[]) removeAt(array, indexesOf(array, element));
5750    }
5751
5752    /**
5753     * Removes the occurrences of the specified element from the specified boolean array.
5754     * <p>
5755     * All subsequent elements are shifted to the left (subtracts one from their indices).
5756     * If the array doesn't contain such an element, no elements are removed from the array.
5757     * {@code null} will be returned if the input array is {@code null}.
5758     * </p>
5759     *
5760     * @param array the input array, will not be modified, and may be {@code null}.
5761     * @param element the element to remove.
5762     * @return A new array containing the existing elements except the occurrences of the specified element.
5763     * @since 3.10
5764     */
5765    public static boolean[] removeAllOccurrences(final boolean[] array, final boolean element) {
5766        return (boolean[]) removeAt(array, indexesOf(array, element));
5767    }
5768
5769    /**
5770     * Removes the occurrences of the specified element from the specified byte array.
5771     * <p>
5772     * All subsequent elements are shifted to the left (subtracts one from their indices).
5773     * If the array doesn't contain such an element, no elements are removed from the array.
5774     * {@code null} will be returned if the input array is {@code null}.
5775     * </p>
5776     *
5777     * @param array the input array, will not be modified, and may be {@code null}.
5778     * @param element the element to remove.
5779     * @return A new array containing the existing elements except the occurrences of the specified element.
5780     * @since 3.10
5781     */
5782    public static byte[] removeAllOccurrences(final byte[] array, final byte element) {
5783        return (byte[]) removeAt(array, indexesOf(array, element));
5784    }
5785
5786    /**
5787     * Removes the occurrences of the specified element from the specified char array.
5788     * <p>
5789     * All subsequent elements are shifted to the left (subtracts one from their indices).
5790     * If the array doesn't contain such an element, no elements are removed from the array.
5791     * {@code null} will be returned if the input array is {@code null}.
5792     * </p>
5793     *
5794     * @param array the input array, will not be modified, and may be {@code null}.
5795     * @param element the element to remove.
5796     * @return A new array containing the existing elements except the occurrences of the specified element.
5797     * @since 3.10
5798     */
5799    public static char[] removeAllOccurrences(final char[] array, final char element) {
5800        return (char[]) removeAt(array, indexesOf(array, element));
5801    }
5802
5803    /**
5804     * Removes the occurrences of the specified element from the specified double array.
5805     * <p>
5806     * All subsequent elements are shifted to the left (subtracts one from their indices).
5807     * If the array doesn't contain such an element, no elements are removed from the array.
5808     * {@code null} will be returned if the input array is {@code null}.
5809     * </p>
5810     *
5811     * @param array the input array, will not be modified, and may be {@code null}.
5812     * @param element the element to remove.
5813     * @return A new array containing the existing elements except the occurrences of the specified element.
5814     * @since 3.10
5815     */
5816    public static double[] removeAllOccurrences(final double[] array, final double element) {
5817        return (double[]) removeAt(array, indexesOf(array, element));
5818    }
5819
5820    /**
5821     * Removes the occurrences of the specified element from the specified float array.
5822     * <p>
5823     * All subsequent elements are shifted to the left (subtracts one from their indices).
5824     * If the array doesn't contain such an element, no elements are removed from the array.
5825     * {@code null} will be returned if the input array is {@code null}.
5826     * </p>
5827     *
5828     * @param array the input array, will not be modified, and may be {@code null}.
5829     * @param element the element to remove.
5830     * @return A new array containing the existing elements except the occurrences of the specified element.
5831     * @since 3.10
5832     */
5833    public static float[] removeAllOccurrences(final float[] array, final float element) {
5834        return (float[]) removeAt(array, indexesOf(array, element));
5835    }
5836
5837    /**
5838     * Removes the occurrences of the specified element from the specified int array.
5839     * <p>
5840     * All subsequent elements are shifted to the left (subtracts one from their indices).
5841     * If the array doesn't contain such an element, no elements are removed from the array.
5842     * {@code null} will be returned if the input array is {@code null}.
5843     * </p>
5844     *
5845     * @param array the input array, will not be modified, and may be {@code null}.
5846     * @param element the element to remove.
5847     * @return A new array containing the existing elements except the occurrences of the specified element.
5848     * @since 3.10
5849     */
5850    public static int[] removeAllOccurrences(final int[] array, final int element) {
5851        return (int[]) removeAt(array, indexesOf(array, element));
5852    }
5853
5854    /**
5855     * Removes the occurrences of the specified element from the specified long array.
5856     * <p>
5857     * All subsequent elements are shifted to the left (subtracts one from their indices).
5858     * If the array doesn't contain such an element, no elements are removed from the array.
5859     * {@code null} will be returned if the input array is {@code null}.
5860     * </p>
5861     *
5862     * @param array the input array, will not be modified, and may be {@code null}.
5863     * @param element the element to remove.
5864     * @return A new array containing the existing elements except the occurrences of the specified element.
5865     * @since 3.10
5866     */
5867    public static long[] removeAllOccurrences(final long[] array, final long element) {
5868        return (long[]) removeAt(array, indexesOf(array, element));
5869    }
5870
5871    /**
5872     * Removes the occurrences of the specified element from the specified short array.
5873     * <p>
5874     * All subsequent elements are shifted to the left (subtracts one from their indices).
5875     * If the array doesn't contain such an element, no elements are removed from the array.
5876     * {@code null} will be returned if the input array is {@code null}.
5877     * </p>
5878     *
5879     * @param array the input array, will not be modified, and may be {@code null}.
5880     * @param element the element to remove.
5881     * @return A new array containing the existing elements except the occurrences of the specified element.
5882     * @since 3.10
5883     */
5884    public static short[] removeAllOccurrences(final short[] array, final short element) {
5885        return (short[]) removeAt(array, indexesOf(array, element));
5886    }
5887
5888    /**
5889     * Removes the occurrences of the specified element from the specified array.
5890     * <p>
5891     * All subsequent elements are shifted to the left (subtracts one from their indices).
5892     * If the array doesn't contain such an element, no elements are removed from the array.
5893     * {@code null} will be returned if the input array is {@code null}.
5894     * </p>
5895     *
5896     * @param <T> the type of object in the array, may be {@code null}.
5897     * @param array the input array, will not be modified, and may be {@code null}.
5898     * @param element the element to remove, may be {@code null}.
5899     * @return A new array containing the existing elements except the occurrences of the specified element.
5900     * @since 3.10
5901     */
5902    public static <T> T[] removeAllOccurrences(final T[] array, final T element) {
5903        return (T[]) removeAt(array, indexesOf(array, element));
5904    }
5905
5906    /**
5907     * Removes multiple array elements specified by indices.
5908     *
5909     * @param array the input array, will not be modified, and may be {@code null}.
5910     * @param indices to remove.
5911     * @return new array of same type minus elements specified by the set bits in {@code indices}.
5912     */
5913    // package protected for access by unit tests
5914    static Object removeAt(final Object array, final BitSet indices) {
5915        if (array == null) {
5916            return null;
5917        }
5918        final int srcLength = getLength(array);
5919        // No need to check maxIndex here, because method only currently called from removeElements()
5920        // which guarantee to generate only valid bit entries.
5921//        final int maxIndex = indices.length();
5922//        if (maxIndex > srcLength) {
5923//            throw new IndexOutOfBoundsException("Index: " + (maxIndex-1) + ", Length: " + srcLength);
5924//        }
5925        final int removals = indices.cardinality(); // true bits are items to remove
5926        final Object result = Array.newInstance(array.getClass().getComponentType(), srcLength - removals);
5927        int srcIndex = 0;
5928        int destIndex = 0;
5929        int count;
5930        int set;
5931        while ((set = indices.nextSetBit(srcIndex)) != -1) {
5932            count = set - srcIndex;
5933            if (count > 0) {
5934                System.arraycopy(array, srcIndex, result, destIndex, count);
5935                destIndex += count;
5936            }
5937            srcIndex = indices.nextClearBit(set);
5938        }
5939        count = srcLength - srcIndex;
5940        if (count > 0) {
5941            System.arraycopy(array, srcIndex, result, destIndex, count);
5942        }
5943        return result;
5944    }
5945
5946    /**
5947     * Removes the first occurrence of the specified element from the
5948     * specified array. All subsequent elements are shifted to the left
5949     * (subtracts one from their indices). If the array doesn't contain
5950     * such an element, no elements are removed from the array.
5951     * <p>
5952     * This method returns a new array with the same elements of the input
5953     * array except the first occurrence of the specified element. The component
5954     * type of the returned array is always the same as that of the input
5955     * array.
5956     * </p>
5957     * <pre>
5958     * ArrayUtils.removeElement(null, true)                = null
5959     * ArrayUtils.removeElement([], true)                  = []
5960     * ArrayUtils.removeElement([true], false)             = [true]
5961     * ArrayUtils.removeElement([true, false], false)      = [true]
5962     * ArrayUtils.removeElement([true, false, true], true) = [false, true]
5963     * </pre>
5964     *
5965     * @param array the input array, may be {@code null}.
5966     * @param element  the element to be removed.
5967     * @return A new array containing the existing elements except the first
5968     *         occurrence of the specified element.
5969     * @since 2.1
5970     */
5971    public static boolean[] removeElement(final boolean[] array, final boolean element) {
5972        final int index = indexOf(array, element);
5973        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
5974    }
5975
5976    /**
5977     * Removes the first occurrence of the specified element from the
5978     * specified array. All subsequent elements are shifted to the left
5979     * (subtracts one from their indices). If the array doesn't contain
5980     * such an element, no elements are removed from the array.
5981     * <p>
5982     * This method returns a new array with the same elements of the input
5983     * array except the first occurrence of the specified element. The component
5984     * type of the returned array is always the same as that of the input
5985     * array.
5986     * </p>
5987     * <pre>
5988     * ArrayUtils.removeElement(null, 1)        = null
5989     * ArrayUtils.removeElement([], 1)          = []
5990     * ArrayUtils.removeElement([1], 0)         = [1]
5991     * ArrayUtils.removeElement([1, 0], 0)      = [1]
5992     * ArrayUtils.removeElement([1, 0, 1], 1)   = [0, 1]
5993     * </pre>
5994     *
5995     * @param array the input array, may be {@code null}.
5996     * @param element  the element to be removed.
5997     * @return A new array containing the existing elements except the first
5998     *         occurrence of the specified element.
5999     * @since 2.1
6000     */
6001    public static byte[] removeElement(final byte[] array, final byte element) {
6002        final int index = indexOf(array, element);
6003        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6004    }
6005
6006    /**
6007     * Removes the first occurrence of the specified element from the
6008     * specified array. All subsequent elements are shifted to the left
6009     * (subtracts one from their indices). If the array doesn't contain
6010     * such an element, no elements are removed from the array.
6011     * <p>
6012     * This method returns a new array with the same elements of the input
6013     * array except the first occurrence of the specified element. The component
6014     * type of the returned array is always the same as that of the input
6015     * array.
6016     * </p>
6017     * <pre>
6018     * ArrayUtils.removeElement(null, 'a')            = null
6019     * ArrayUtils.removeElement([], 'a')              = []
6020     * ArrayUtils.removeElement(['a'], 'b')           = ['a']
6021     * ArrayUtils.removeElement(['a', 'b'], 'a')      = ['b']
6022     * ArrayUtils.removeElement(['a', 'b', 'a'], 'a') = ['b', 'a']
6023     * </pre>
6024     *
6025     * @param array the input array, may be {@code null}.
6026     * @param element  the element to be removed.
6027     * @return A new array containing the existing elements except the first
6028     *         occurrence of the specified element.
6029     * @since 2.1
6030     */
6031    public static char[] removeElement(final char[] array, final char element) {
6032        final int index = indexOf(array, element);
6033        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6034    }
6035
6036    /**
6037     * Removes the first occurrence of the specified element from the
6038     * specified array. All subsequent elements are shifted to the left
6039     * (subtracts one from their indices). If the array doesn't contain
6040     * such an element, no elements are removed from the array.
6041     * <p>
6042     * This method returns a new array with the same elements of the input
6043     * array except the first occurrence of the specified element. The component
6044     * type of the returned array is always the same as that of the input
6045     * array.
6046     * </p>
6047     * <pre>
6048     * ArrayUtils.removeElement(null, 1.1)            = null
6049     * ArrayUtils.removeElement([], 1.1)              = []
6050     * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
6051     * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
6052     * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
6053     * </pre>
6054     *
6055     * @param array the input array, may be {@code null}.
6056     * @param element  the element to be removed.
6057     * @return A new array containing the existing elements except the first
6058     *         occurrence of the specified element.
6059     * @since 2.1
6060     */
6061    public static double[] removeElement(final double[] array, final double element) {
6062        final int index = indexOf(array, element);
6063        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6064    }
6065
6066    /**
6067     * Removes the first occurrence of the specified element from the
6068     * specified array. All subsequent elements are shifted to the left
6069     * (subtracts one from their indices). If the array doesn't contain
6070     * such an element, no elements are removed from the array.
6071     * <p>
6072     * This method returns a new array with the same elements of the input
6073     * array except the first occurrence of the specified element. The component
6074     * type of the returned array is always the same as that of the input
6075     * array.
6076     * </p>
6077     * <pre>
6078     * ArrayUtils.removeElement(null, 1.1)            = null
6079     * ArrayUtils.removeElement([], 1.1)              = []
6080     * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
6081     * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
6082     * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
6083     * </pre>
6084     *
6085     * @param array the input array, may be {@code null}.
6086     * @param element  the element to be removed.
6087     * @return A new array containing the existing elements except the first
6088     *         occurrence of the specified element.
6089     * @since 2.1
6090     */
6091    public static float[] removeElement(final float[] array, final float element) {
6092        final int index = indexOf(array, element);
6093        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6094    }
6095
6096    /**
6097     * Removes the first occurrence of the specified element from the
6098     * specified array. All subsequent elements are shifted to the left
6099     * (subtracts one from their indices). If the array doesn't contain
6100     * such an element, no elements are removed from the array.
6101     * <p>
6102     * This method returns a new array with the same elements of the input
6103     * array except the first occurrence of the specified element. The component
6104     * type of the returned array is always the same as that of the input
6105     * array.
6106     * </p>
6107     * <pre>
6108     * ArrayUtils.removeElement(null, 1)      = null
6109     * ArrayUtils.removeElement([], 1)        = []
6110     * ArrayUtils.removeElement([1], 2)       = [1]
6111     * ArrayUtils.removeElement([1, 3], 1)    = [3]
6112     * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
6113     * </pre>
6114     *
6115     * @param array the input array, may be {@code null}.
6116     * @param element  the element to be removed.
6117     * @return A new array containing the existing elements except the first
6118     *         occurrence of the specified element.
6119     * @since 2.1
6120     */
6121    public static int[] removeElement(final int[] array, final int element) {
6122        final int index = indexOf(array, element);
6123        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6124    }
6125
6126    /**
6127     * Removes the first occurrence of the specified element from the
6128     * specified array. All subsequent elements are shifted to the left
6129     * (subtracts one from their indices). If the array doesn't contain
6130     * such an element, no elements are removed from the array.
6131     * <p>
6132     * This method returns a new array with the same elements of the input
6133     * array except the first occurrence of the specified element. The component
6134     * type of the returned array is always the same as that of the input
6135     * array.
6136     * </p>
6137     * <pre>
6138     * ArrayUtils.removeElement(null, 1)      = null
6139     * ArrayUtils.removeElement([], 1)        = []
6140     * ArrayUtils.removeElement([1], 2)       = [1]
6141     * ArrayUtils.removeElement([1, 3], 1)    = [3]
6142     * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
6143     * </pre>
6144     *
6145     * @param array the input array, may be {@code null}.
6146     * @param element  the element to be removed.
6147     * @return A new array containing the existing elements except the first
6148     *         occurrence of the specified element.
6149     * @since 2.1
6150     */
6151    public static long[] removeElement(final long[] array, final long element) {
6152        final int index = indexOf(array, element);
6153        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6154    }
6155
6156    /**
6157     * Removes the first occurrence of the specified element from the
6158     * specified array. All subsequent elements are shifted to the left
6159     * (subtracts one from their indices). If the array doesn't contain
6160     * such an element, no elements are removed from the array.
6161     * <p>
6162     * This method returns a new array with the same elements of the input
6163     * array except the first occurrence of the specified element. The component
6164     * type of the returned array is always the same as that of the input
6165     * array.
6166     * </p>
6167     * <pre>
6168     * ArrayUtils.removeElement(null, 1)      = null
6169     * ArrayUtils.removeElement([], 1)        = []
6170     * ArrayUtils.removeElement([1], 2)       = [1]
6171     * ArrayUtils.removeElement([1, 3], 1)    = [3]
6172     * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
6173     * </pre>
6174     *
6175     * @param array the input array, may be {@code null}.
6176     * @param element  the element to be removed.
6177     * @return A new array containing the existing elements except the first
6178     *         occurrence of the specified element.
6179     * @since 2.1
6180     */
6181    public static short[] removeElement(final short[] array, final short element) {
6182        final int index = indexOf(array, element);
6183        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6184    }
6185
6186    /**
6187     * Removes the first occurrence of the specified element from the
6188     * specified array. All subsequent elements are shifted to the left
6189     * (subtracts one from their indices). If the array doesn't contain
6190     * such an element, no elements are removed from the array.
6191     * <p>
6192     * This method returns a new array with the same elements of the input
6193     * array except the first occurrence of the specified element. The component
6194     * type of the returned array is always the same as that of the input
6195     * array.
6196     * </p>
6197     * <pre>
6198     * ArrayUtils.removeElement(null, "a")            = null
6199     * ArrayUtils.removeElement([], "a")              = []
6200     * ArrayUtils.removeElement(["a"], "b")           = ["a"]
6201     * ArrayUtils.removeElement(["a", "b"], "a")      = ["b"]
6202     * ArrayUtils.removeElement(["a", "b", "a"], "a") = ["b", "a"]
6203     * </pre>
6204     *
6205     * @param <T> the component type of the array
6206     * @param array the input array, may be {@code null}.
6207     * @param element  the element to be removed, may be {@code null}.
6208     * @return A new array containing the existing elements except the first
6209     *         occurrence of the specified element.
6210     * @since 2.1
6211     */
6212    public static <T> T[] removeElement(final T[] array, final Object element) {
6213        final int index = indexOf(array, element);
6214        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6215    }
6216
6217    /**
6218     * Removes occurrences of specified elements, in specified quantities,
6219     * from the specified array. All subsequent elements are shifted left.
6220     * For any element-to-be-removed specified in greater quantities than
6221     * contained in the original array, no change occurs beyond the
6222     * removal of the existing matching items.
6223     * <p>
6224     * This method returns a new array with the same elements of the input
6225     * array except for the earliest-encountered occurrences of the specified
6226     * elements. The component type of the returned array is always the same
6227     * as that of the input array.
6228     * </p>
6229     * <pre>
6230     * ArrayUtils.removeElements(null, true, false)               = null
6231     * ArrayUtils.removeElements([], true, false)                 = []
6232     * ArrayUtils.removeElements([true], false, false)            = [true]
6233     * ArrayUtils.removeElements([true, false], true, true)       = [false]
6234     * ArrayUtils.removeElements([true, false, true], true)       = [false, true]
6235     * ArrayUtils.removeElements([true, false, true], true, true) = [false]
6236     * </pre>
6237     *
6238     * @param array the input array, will not be modified, and may be {@code null}.
6239     * @param values  the values to be removed.
6240     * @return A new array containing the existing elements except the
6241     *         earliest-encountered occurrences of the specified elements.
6242     * @since 3.0.1
6243     */
6244    public static boolean[] removeElements(final boolean[] array, final boolean... values) {
6245        if (isEmpty(array) || isEmpty(values)) {
6246            return clone(array);
6247        }
6248        final HashMap<Boolean, MutableInt> occurrences = new HashMap<>(2); // only two possible values here
6249        for (final boolean v : values) {
6250            increment(occurrences, Boolean.valueOf(v));
6251        }
6252        final BitSet toRemove = new BitSet();
6253        for (int i = 0; i < array.length; i++) {
6254            final boolean key = array[i];
6255            final MutableInt count = occurrences.get(key);
6256            if (count != null) {
6257                if (count.decrementAndGet() == 0) {
6258                    occurrences.remove(key);
6259                }
6260                toRemove.set(i);
6261            }
6262        }
6263        return (boolean[]) removeAt(array, toRemove);
6264    }
6265
6266    /**
6267     * Removes occurrences of specified elements, in specified quantities,
6268     * from the specified array. All subsequent elements are shifted left.
6269     * For any element-to-be-removed specified in greater quantities than
6270     * contained in the original array, no change occurs beyond the
6271     * removal of the existing matching items.
6272     * <p>
6273     * This method returns a new array with the same elements of the input
6274     * array except for the earliest-encountered occurrences of the specified
6275     * elements. The component type of the returned array is always the same
6276     * as that of the input array.
6277     * </p>
6278     * <pre>
6279     * ArrayUtils.removeElements(null, 1, 2)      = null
6280     * ArrayUtils.removeElements([], 1, 2)        = []
6281     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6282     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6283     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6284     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6285     * </pre>
6286     *
6287     * @param array the input array, will not be modified, and may be {@code null}.
6288     * @param values  the values to be removed.
6289     * @return A new array containing the existing elements except the
6290     *         earliest-encountered occurrences of the specified elements.
6291     * @since 3.0.1
6292     */
6293    public static byte[] removeElements(final byte[] array, final byte... values) {
6294        if (isEmpty(array) || isEmpty(values)) {
6295            return clone(array);
6296        }
6297        final HashMap<Byte, MutableInt> occurrences = new HashMap<>(values.length);
6298        for (final byte v : values) {
6299            increment(occurrences, Byte.valueOf(v));
6300        }
6301        final BitSet toRemove = new BitSet();
6302        for (int i = 0; i < array.length; i++) {
6303            final byte key = array[i];
6304            final MutableInt count = occurrences.get(key);
6305            if (count != null) {
6306                if (count.decrementAndGet() == 0) {
6307                    occurrences.remove(key);
6308                }
6309                toRemove.set(i);
6310            }
6311        }
6312        return (byte[]) removeAt(array, toRemove);
6313    }
6314
6315    /**
6316     * Removes occurrences of specified elements, in specified quantities,
6317     * from the specified array. All subsequent elements are shifted left.
6318     * For any element-to-be-removed specified in greater quantities than
6319     * contained in the original array, no change occurs beyond the
6320     * removal of the existing matching items.
6321     * <p>
6322     * This method returns a new array with the same elements of the input
6323     * array except for the earliest-encountered occurrences of the specified
6324     * elements. The component type of the returned array is always the same
6325     * as that of the input array.
6326     * </p>
6327     * <pre>
6328     * ArrayUtils.removeElements(null, 1, 2)      = null
6329     * ArrayUtils.removeElements([], 1, 2)        = []
6330     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6331     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6332     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6333     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6334     * </pre>
6335     *
6336     * @param array the input array, will not be modified, and may be {@code null}.
6337     * @param values  the values to be removed.
6338     * @return A new array containing the existing elements except the
6339     *         earliest-encountered occurrences of the specified elements.
6340     * @since 3.0.1
6341     */
6342    public static char[] removeElements(final char[] array, final char... values) {
6343        if (isEmpty(array) || isEmpty(values)) {
6344            return clone(array);
6345        }
6346        final HashMap<Character, MutableInt> occurrences = new HashMap<>(values.length);
6347        for (final char v : values) {
6348            increment(occurrences, Character.valueOf(v));
6349        }
6350        final BitSet toRemove = new BitSet();
6351        for (int i = 0; i < array.length; i++) {
6352            final char key = array[i];
6353            final MutableInt count = occurrences.get(key);
6354            if (count != null) {
6355                if (count.decrementAndGet() == 0) {
6356                    occurrences.remove(key);
6357                }
6358                toRemove.set(i);
6359            }
6360        }
6361        return (char[]) removeAt(array, toRemove);
6362    }
6363
6364    /**
6365     * Removes occurrences of specified elements, in specified quantities,
6366     * from the specified array. All subsequent elements are shifted left.
6367     * For any element-to-be-removed specified in greater quantities than
6368     * contained in the original array, no change occurs beyond the
6369     * removal of the existing matching items.
6370     * <p>
6371     * This method returns a new array with the same elements of the input
6372     * array except for the earliest-encountered occurrences of the specified
6373     * elements. The component type of the returned array is always the same
6374     * as that of the input array.
6375     * </p>
6376     * <pre>
6377     * ArrayUtils.removeElements(null, 1, 2)      = null
6378     * ArrayUtils.removeElements([], 1, 2)        = []
6379     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6380     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6381     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6382     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6383     * </pre>
6384     *
6385     * @param array the input array, will not be modified, and may be {@code null}.
6386     * @param values  the values to be removed.
6387     * @return A new array containing the existing elements except the
6388     *         earliest-encountered occurrences of the specified elements.
6389     * @since 3.0.1
6390     */
6391    public static double[] removeElements(final double[] array, final double... values) {
6392        if (isEmpty(array) || isEmpty(values)) {
6393            return clone(array);
6394        }
6395        final HashMap<Double, MutableInt> occurrences = new HashMap<>(values.length);
6396        for (final double v : values) {
6397            increment(occurrences, Double.valueOf(v));
6398        }
6399        final BitSet toRemove = new BitSet();
6400        for (int i = 0; i < array.length; i++) {
6401            final double key = array[i];
6402            final MutableInt count = occurrences.get(key);
6403            if (count != null) {
6404                if (count.decrementAndGet() == 0) {
6405                    occurrences.remove(key);
6406                }
6407                toRemove.set(i);
6408            }
6409        }
6410        return (double[]) removeAt(array, toRemove);
6411    }
6412
6413    /**
6414     * Removes occurrences of specified elements, in specified quantities,
6415     * from the specified array. All subsequent elements are shifted left.
6416     * For any element-to-be-removed specified in greater quantities than
6417     * contained in the original array, no change occurs beyond the
6418     * removal of the existing matching items.
6419     * <p>
6420     * This method returns a new array with the same elements of the input
6421     * array except for the earliest-encountered occurrences of the specified
6422     * elements. The component type of the returned array is always the same
6423     * as that of the input array.
6424     * </p>
6425     * <pre>
6426     * ArrayUtils.removeElements(null, 1, 2)      = null
6427     * ArrayUtils.removeElements([], 1, 2)        = []
6428     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6429     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6430     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6431     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6432     * </pre>
6433     *
6434     * @param array the input array, will not be modified, and may be {@code null}.
6435     * @param values  the values to be removed.
6436     * @return A new array containing the existing elements except the
6437     *         earliest-encountered occurrences of the specified elements.
6438     * @since 3.0.1
6439     */
6440    public static float[] removeElements(final float[] array, final float... values) {
6441        if (isEmpty(array) || isEmpty(values)) {
6442            return clone(array);
6443        }
6444        final HashMap<Float, MutableInt> occurrences = new HashMap<>(values.length);
6445        for (final float v : values) {
6446            increment(occurrences, Float.valueOf(v));
6447        }
6448        final BitSet toRemove = new BitSet();
6449        for (int i = 0; i < array.length; i++) {
6450            final float key = array[i];
6451            final MutableInt count = occurrences.get(key);
6452            if (count != null) {
6453                if (count.decrementAndGet() == 0) {
6454                    occurrences.remove(key);
6455                }
6456                toRemove.set(i);
6457            }
6458        }
6459        return (float[]) removeAt(array, toRemove);
6460    }
6461
6462    /**
6463     * Removes occurrences of specified elements, in specified quantities,
6464     * from the specified array. All subsequent elements are shifted left.
6465     * For any element-to-be-removed specified in greater quantities than
6466     * contained in the original array, no change occurs beyond the
6467     * removal of the existing matching items.
6468     * <p>
6469     * This method returns a new array with the same elements of the input
6470     * array except for the earliest-encountered occurrences of the specified
6471     * elements. The component type of the returned array is always the same
6472     * as that of the input array.
6473     * </p>
6474     * <pre>
6475     * ArrayUtils.removeElements(null, 1, 2)      = null
6476     * ArrayUtils.removeElements([], 1, 2)        = []
6477     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6478     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6479     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6480     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6481     * </pre>
6482     *
6483     * @param array the input array, will not be modified, and may be {@code null}.
6484     * @param values  the values to be removed.
6485     * @return A new array containing the existing elements except the
6486     *         earliest-encountered occurrences of the specified elements.
6487     * @since 3.0.1
6488     */
6489    public static int[] removeElements(final int[] array, final int... values) {
6490        if (isEmpty(array) || isEmpty(values)) {
6491            return clone(array);
6492        }
6493        final HashMap<Integer, MutableInt> occurrences = new HashMap<>(values.length);
6494        for (final int v : values) {
6495            increment(occurrences, Integer.valueOf(v));
6496        }
6497        final BitSet toRemove = new BitSet();
6498        for (int i = 0; i < array.length; i++) {
6499            final int key = array[i];
6500            final MutableInt count = occurrences.get(key);
6501            if (count != null) {
6502                if (count.decrementAndGet() == 0) {
6503                    occurrences.remove(key);
6504                }
6505                toRemove.set(i);
6506            }
6507        }
6508        return (int[]) removeAt(array, toRemove);
6509    }
6510
6511    /**
6512     * Removes occurrences of specified elements, in specified quantities,
6513     * from the specified array. All subsequent elements are shifted left.
6514     * For any element-to-be-removed specified in greater quantities than
6515     * contained in the original array, no change occurs beyond the
6516     * removal of the existing matching items.
6517     * <p>
6518     * This method returns a new array with the same elements of the input
6519     * array except for the earliest-encountered occurrences of the specified
6520     * elements. The component type of the returned array is always the same
6521     * as that of the input array.
6522     * </p>
6523     * <pre>
6524     * ArrayUtils.removeElements(null, 1, 2)      = null
6525     * ArrayUtils.removeElements([], 1, 2)        = []
6526     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6527     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6528     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6529     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6530     * </pre>
6531     *
6532     * @param array the input array, will not be modified, and may be {@code null}.
6533     * @param values  the values to be removed.
6534     * @return A new array containing the existing elements except the
6535     *         earliest-encountered occurrences of the specified elements.
6536     * @since 3.0.1
6537     */
6538    public static long[] removeElements(final long[] array, final long... values) {
6539        if (isEmpty(array) || isEmpty(values)) {
6540            return clone(array);
6541        }
6542        final HashMap<Long, MutableInt> occurrences = new HashMap<>(values.length);
6543        for (final long v : values) {
6544            increment(occurrences, Long.valueOf(v));
6545        }
6546        final BitSet toRemove = new BitSet();
6547        for (int i = 0; i < array.length; i++) {
6548            final long key = array[i];
6549            final MutableInt count = occurrences.get(key);
6550            if (count != null) {
6551                if (count.decrementAndGet() == 0) {
6552                    occurrences.remove(key);
6553                }
6554                toRemove.set(i);
6555            }
6556        }
6557        return (long[]) removeAt(array, toRemove);
6558    }
6559
6560    /**
6561     * Removes occurrences of specified elements, in specified quantities,
6562     * from the specified array. All subsequent elements are shifted left.
6563     * For any element-to-be-removed specified in greater quantities than
6564     * contained in the original array, no change occurs beyond the
6565     * removal of the existing matching items.
6566     * <p>
6567     * This method returns a new array with the same elements of the input
6568     * array except for the earliest-encountered occurrences of the specified
6569     * elements. The component type of the returned array is always the same
6570     * as that of the input array.
6571     * </p>
6572     * <pre>
6573     * ArrayUtils.removeElements(null, 1, 2)      = null
6574     * ArrayUtils.removeElements([], 1, 2)        = []
6575     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6576     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6577     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6578     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6579     * </pre>
6580     *
6581     * @param array the input array, will not be modified, and may be {@code null}.
6582     * @param values  the values to be removed.
6583     * @return A new array containing the existing elements except the
6584     *         earliest-encountered occurrences of the specified elements.
6585     * @since 3.0.1
6586     */
6587    public static short[] removeElements(final short[] array, final short... values) {
6588        if (isEmpty(array) || isEmpty(values)) {
6589            return clone(array);
6590        }
6591        final HashMap<Short, MutableInt> occurrences = new HashMap<>(values.length);
6592        for (final short v : values) {
6593            increment(occurrences, Short.valueOf(v));
6594        }
6595        final BitSet toRemove = new BitSet();
6596        for (int i = 0; i < array.length; i++) {
6597            final short key = array[i];
6598            final MutableInt count = occurrences.get(key);
6599            if (count != null) {
6600                if (count.decrementAndGet() == 0) {
6601                    occurrences.remove(key);
6602                }
6603                toRemove.set(i);
6604            }
6605        }
6606        return (short[]) removeAt(array, toRemove);
6607    }
6608
6609    /**
6610     * Removes occurrences of specified elements, in specified quantities,
6611     * from the specified array. All subsequent elements are shifted left.
6612     * For any element-to-be-removed specified in greater quantities than
6613     * contained in the original array, no change occurs beyond the
6614     * removal of the existing matching items.
6615     * <p>
6616     * This method returns a new array with the same elements of the input
6617     * array except for the earliest-encountered occurrences of the specified
6618     * elements. The component type of the returned array is always the same
6619     * as that of the input array.
6620     * </p>
6621     * <pre>
6622     * ArrayUtils.removeElements(null, "a", "b")            = null
6623     * ArrayUtils.removeElements([], "a", "b")              = []
6624     * ArrayUtils.removeElements(["a"], "b", "c")           = ["a"]
6625     * ArrayUtils.removeElements(["a", "b"], "a", "c")      = ["b"]
6626     * ArrayUtils.removeElements(["a", "b", "a"], "a")      = ["b", "a"]
6627     * ArrayUtils.removeElements(["a", "b", "a"], "a", "a") = ["b"]
6628     * </pre>
6629     *
6630     * @param <T> the component type of the array
6631     * @param array the input array, will not be modified, and may be {@code null}.
6632     * @param values  the values to be removed.
6633     * @return A new array containing the existing elements except the
6634     *         earliest-encountered occurrences of the specified elements.
6635     * @since 3.0.1
6636     */
6637    @SafeVarargs
6638    public static <T> T[] removeElements(final T[] array, final T... values) {
6639        if (isEmpty(array) || isEmpty(values)) {
6640            return clone(array);
6641        }
6642        final HashMap<T, MutableInt> occurrences = new HashMap<>(values.length);
6643        for (final T v : values) {
6644            increment(occurrences, v);
6645        }
6646        final BitSet toRemove = new BitSet();
6647        for (int i = 0; i < array.length; i++) {
6648            final T key = array[i];
6649            final MutableInt count = occurrences.get(key);
6650            if (count != null) {
6651                if (count.decrementAndGet() == 0) {
6652                    occurrences.remove(key);
6653                }
6654                toRemove.set(i);
6655            }
6656        }
6657        @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
6658        final T[] result = (T[]) removeAt(array, toRemove);
6659        return result;
6660    }
6661
6662    /**
6663     * Reverses the order of the given array.
6664     * <p>
6665     * This method does nothing for a {@code null} input array.
6666     * </p>
6667     *
6668     * @param array  the array to reverse, may be {@code null}.
6669     */
6670    public static void reverse(final boolean[] array) {
6671        if (array != null) {
6672            reverse(array, 0, array.length);
6673        }
6674    }
6675
6676    /**
6677     * Reverses the order of the given array in the given range.
6678     * <p>
6679     * This method does nothing for a {@code null} input array.
6680     * </p>
6681     *
6682     * @param array
6683     *            the array to reverse, may be {@code null}.
6684     * @param startIndexInclusive
6685     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6686     *            change.
6687     * @param endIndexExclusive
6688     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6689     *            change. Overvalue (&gt;array.length) is demoted to array length.
6690     * @since 3.2
6691     */
6692    public static void reverse(final boolean[] array, final int startIndexInclusive, final int endIndexExclusive) {
6693        if (array == null) {
6694            return;
6695        }
6696        int i = Math.max(startIndexInclusive, 0);
6697        int j = Math.min(array.length, endIndexExclusive) - 1;
6698        boolean tmp;
6699        while (j > i) {
6700            tmp = array[j];
6701            array[j] = array[i];
6702            array[i] = tmp;
6703            j--;
6704            i++;
6705        }
6706    }
6707
6708    /**
6709     * Reverses the order of the given array.
6710     * <p>
6711     * This method does nothing for a {@code null} input array.
6712     * </p>
6713     *
6714     * @param array  the array to reverse, may be {@code null}.
6715     */
6716    public static void reverse(final byte[] array) {
6717        if (array != null) {
6718            reverse(array, 0, array.length);
6719        }
6720    }
6721
6722    /**
6723     * Reverses the order of the given array in the given range.
6724     * <p>
6725     * This method does nothing for a {@code null} input array.
6726     * </p>
6727     *
6728     * @param array               the array to reverse, may be {@code null}.
6729     * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no change.
6730     * @param endIndexExclusive   elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no change. Overvalue
6731     *                            (&gt;array.length) is demoted to array length.
6732     * @since 3.2
6733     */
6734    public static void reverse(final byte[] array, final int startIndexInclusive, final int endIndexExclusive) {
6735        if (array == null) {
6736            return;
6737        }
6738        int i = Math.max(startIndexInclusive, 0);
6739        int j = Math.min(array.length, endIndexExclusive) - 1;
6740        byte tmp;
6741        while (j > i) {
6742            tmp = array[j];
6743            array[j] = array[i];
6744            array[i] = tmp;
6745            j--;
6746            i++;
6747        }
6748    }
6749
6750    /**
6751     * Reverses the order of the given array.
6752     * <p>
6753     * This method does nothing for a {@code null} input array.
6754     * </p>
6755     *
6756     * @param array  the array to reverse, may be {@code null}.
6757     */
6758    public static void reverse(final char[] array) {
6759        if (array != null) {
6760            reverse(array, 0, array.length);
6761        }
6762    }
6763
6764    /**
6765     * Reverses the order of the given array in the given range.
6766     * <p>
6767     * This method does nothing for a {@code null} input array.
6768     * </p>
6769     *
6770     * @param array               the array to reverse, may be {@code null}.
6771     * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no change.
6772     * @param endIndexExclusive   elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no change. Overvalue
6773     *                            (&gt;array.length) is demoted to array length.
6774     * @since 3.2
6775     */
6776    public static void reverse(final char[] array, final int startIndexInclusive, final int endIndexExclusive) {
6777        if (array == null) {
6778            return;
6779        }
6780        int i = Math.max(startIndexInclusive, 0);
6781        int j = Math.min(array.length, endIndexExclusive) - 1;
6782        char tmp;
6783        while (j > i) {
6784            tmp = array[j];
6785            array[j] = array[i];
6786            array[i] = tmp;
6787            j--;
6788            i++;
6789        }
6790    }
6791
6792    /**
6793     * Reverses the order of the given array.
6794     * <p>
6795     * This method does nothing for a {@code null} input array.
6796     * </p>
6797     *
6798     * @param array  the array to reverse, may be {@code null}
6799     */
6800    public static void reverse(final double[] array) {
6801        if (array != null) {
6802            reverse(array, 0, array.length);
6803        }
6804    }
6805
6806    /**
6807     * Reverses the order of the given array in the given range.
6808     * <p>
6809     * This method does nothing for a {@code null} input array.
6810     * </p>
6811     *
6812     * @param array               the array to reverse, may be {@code null}.
6813     * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no change.
6814     * @param endIndexExclusive   elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no change. Overvalue
6815     *                            (&gt;array.length) is demoted to array length.
6816     * @since 3.2
6817     */
6818    public static void reverse(final double[] array, final int startIndexInclusive, final int endIndexExclusive) {
6819        if (array == null) {
6820            return;
6821        }
6822        int i = Math.max(startIndexInclusive, 0);
6823        int j = Math.min(array.length, endIndexExclusive) - 1;
6824        double tmp;
6825        while (j > i) {
6826            tmp = array[j];
6827            array[j] = array[i];
6828            array[i] = tmp;
6829            j--;
6830            i++;
6831        }
6832    }
6833
6834    /**
6835     * Reverses the order of the given array.
6836     * <p>
6837     * This method does nothing for a {@code null} input array.
6838     * </p>
6839     *
6840     * @param array  the array to reverse, may be {@code null}.
6841     */
6842    public static void reverse(final float[] array) {
6843        if (array != null) {
6844            reverse(array, 0, array.length);
6845        }
6846    }
6847
6848    /**
6849     * Reverses the order of the given array in the given range.
6850     * <p>
6851     * This method does nothing for a {@code null} input array.
6852     * </p>
6853     *
6854     * @param array               the array to reverse, may be {@code null}.
6855     * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no change.
6856     * @param endIndexExclusive   elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no change. Overvalue
6857     *                            (&gt;array.length) is demoted to array length.
6858     * @since 3.2
6859     */
6860    public static void reverse(final float[] array, final int startIndexInclusive, final int endIndexExclusive) {
6861        if (array == null) {
6862            return;
6863        }
6864        int i = Math.max(startIndexInclusive, 0);
6865        int j = Math.min(array.length, endIndexExclusive) - 1;
6866        float tmp;
6867        while (j > i) {
6868            tmp = array[j];
6869            array[j] = array[i];
6870            array[i] = tmp;
6871            j--;
6872            i++;
6873        }
6874    }
6875
6876    /**
6877     * Reverses the order of the given array.
6878     * <p>
6879     * This method does nothing for a {@code null} input array.
6880     * </p>
6881     *
6882     * @param array  the array to reverse, may be {@code null}.
6883     */
6884    public static void reverse(final int[] array) {
6885        if (array != null) {
6886            reverse(array, 0, array.length);
6887        }
6888    }
6889
6890    /**
6891     * Reverses the order of the given array in the given range.
6892     * <p>
6893     * This method does nothing for a {@code null} input array.
6894     * </p>
6895     *
6896     * @param array
6897     *            the array to reverse, may be {@code null}.
6898     * @param startIndexInclusive
6899     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6900     *            change.
6901     * @param endIndexExclusive
6902     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6903     *            change. Overvalue (&gt;array.length) is demoted to array length.
6904     * @since 3.2
6905     */
6906    public static void reverse(final int[] array, final int startIndexInclusive, final int endIndexExclusive) {
6907        if (array == null) {
6908            return;
6909        }
6910        int i = Math.max(startIndexInclusive, 0);
6911        int j = Math.min(array.length, endIndexExclusive) - 1;
6912        int tmp;
6913        while (j > i) {
6914            tmp = array[j];
6915            array[j] = array[i];
6916            array[i] = tmp;
6917            j--;
6918            i++;
6919        }
6920    }
6921
6922    /**
6923     * Reverses the order of the given array.
6924     * <p>
6925     * This method does nothing for a {@code null} input array.
6926     * </p>
6927     *
6928     * @param array  the array to reverse, may be {@code null}.
6929     */
6930    public static void reverse(final long[] array) {
6931        if (array != null) {
6932            reverse(array, 0, array.length);
6933        }
6934    }
6935
6936    /**
6937     * Reverses the order of the given array in the given range.
6938     * <p>
6939     * This method does nothing for a {@code null} input array.
6940     * </p>
6941     *
6942     * @param array
6943     *            the array to reverse, may be {@code null}.
6944     * @param startIndexInclusive
6945     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6946     *            change.
6947     * @param endIndexExclusive
6948     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6949     *            change. Overvalue (&gt;array.length) is demoted to array length.
6950     * @since 3.2
6951     */
6952    public static void reverse(final long[] array, final int startIndexInclusive, final int endIndexExclusive) {
6953        if (array == null) {
6954            return;
6955        }
6956        int i = Math.max(startIndexInclusive, 0);
6957        int j = Math.min(array.length, endIndexExclusive) - 1;
6958        long tmp;
6959        while (j > i) {
6960            tmp = array[j];
6961            array[j] = array[i];
6962            array[i] = tmp;
6963            j--;
6964            i++;
6965        }
6966    }
6967
6968    /**
6969     * Reverses the order of the given array.
6970     * <p>
6971     * There is no special handling for multi-dimensional arrays.
6972     * </p>
6973     * <p>
6974     * This method does nothing for a {@code null} input array.
6975     * </p>
6976     *
6977     * @param array  the array to reverse, may be {@code null}.
6978     */
6979    public static void reverse(final Object[] array) {
6980        if (array != null) {
6981            reverse(array, 0, array.length);
6982        }
6983    }
6984
6985    /**
6986     * Reverses the order of the given array in the given range.
6987     * <p>
6988     * This method does nothing for a {@code null} input array.
6989     * </p>
6990     *
6991     * @param array
6992     *            the array to reverse, may be {@code null}.
6993     * @param startIndexInclusive
6994     *            the starting index. Under value (&lt;0) is promoted to 0, over value (&gt;array.length) results in no
6995     *            change.
6996     * @param endIndexExclusive
6997     *            elements up to endIndex-1 are reversed in the array. Under value (&lt; start index) results in no
6998     *            change. Over value (&gt;array.length) is demoted to array length.
6999     * @since 3.2
7000     */
7001    public static void reverse(final Object[] array, final int startIndexInclusive, final int endIndexExclusive) {
7002        if (array == null) {
7003            return;
7004        }
7005        int i = Math.max(startIndexInclusive, 0);
7006        int j = Math.min(array.length, endIndexExclusive) - 1;
7007        Object tmp;
7008        while (j > i) {
7009            tmp = array[j];
7010            array[j] = array[i];
7011            array[i] = tmp;
7012            j--;
7013            i++;
7014        }
7015    }
7016
7017    /**
7018     * Reverses the order of the given array.
7019     * <p>
7020     * This method does nothing for a {@code null} input array.
7021     * </p>
7022     *
7023     * @param array  the array to reverse, may be {@code null}.
7024     */
7025    public static void reverse(final short[] array) {
7026        if (array != null) {
7027            reverse(array, 0, array.length);
7028        }
7029    }
7030
7031    /**
7032     * Reverses the order of the given array in the given range.
7033     * <p>
7034     * This method does nothing for a {@code null} input array.
7035     * </p>
7036     *
7037     * @param array
7038     *            the array to reverse, may be {@code null}.
7039     * @param startIndexInclusive
7040     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7041     *            change.
7042     * @param endIndexExclusive
7043     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
7044     *            change. Overvalue (&gt;array.length) is demoted to array length.
7045     * @since 3.2
7046     */
7047    public static void reverse(final short[] array, final int startIndexInclusive, final int endIndexExclusive) {
7048        if (array == null) {
7049            return;
7050        }
7051        int i = Math.max(startIndexInclusive, 0);
7052        int j = Math.min(array.length, endIndexExclusive) - 1;
7053        short tmp;
7054        while (j > i) {
7055            tmp = array[j];
7056            array[j] = array[i];
7057            array[i] = tmp;
7058            j--;
7059            i++;
7060        }
7061    }
7062
7063    /**
7064     * Sets all elements of the specified array, using the provided generator supplier to compute each element.
7065     * <p>
7066     * If the generator supplier throws an exception, it is relayed to the caller and the array is left in an indeterminate
7067     * state.
7068     * </p>
7069     *
7070     * @param <T> type of elements of the array, may be {@code null}.
7071     * @param array array to be initialized, may be {@code null}.
7072     * @param generator a function accepting an index and producing the desired value for that position.
7073     * @return the input array
7074     * @since 3.13.0
7075     */
7076    public static <T> T[] setAll(final T[] array, final IntFunction<? extends T> generator) {
7077        if (array != null && generator != null) {
7078            Arrays.setAll(array, generator);
7079        }
7080        return array;
7081    }
7082
7083    /**
7084     * Sets all elements of the specified array, using the provided generator supplier to compute each element.
7085     * <p>
7086     * If the generator supplier throws an exception, it is relayed to the caller and the array is left in an indeterminate
7087     * state.
7088     * </p>
7089     *
7090     * @param <T> type of elements of the array, may be {@code null}.
7091     * @param array array to be initialized, may be {@code null}.
7092     * @param generator a function accepting an index and producing the desired value for that position.
7093     * @return the input array
7094     * @since 3.13.0
7095     */
7096    public static <T> T[] setAll(final T[] array, final Supplier<? extends T> generator) {
7097        if (array != null && generator != null) {
7098            for (int i = 0; i < array.length; i++) {
7099                array[i] = generator.get();
7100            }
7101        }
7102        return array;
7103    }
7104
7105    /**
7106     * Shifts the order of the given boolean array.
7107     *
7108     * <p>There is no special handling for multi-dimensional arrays. This method
7109     * does nothing for {@code null} or empty input arrays.</p>
7110     *
7111     * @param array  the array to shift, may be {@code null}.
7112     * @param offset
7113     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7114     *          rotate, than the effective offset is modulo the number of elements to rotate.
7115     * @since 3.5
7116     */
7117    public static void shift(final boolean[] array, final int offset) {
7118        if (array != null) {
7119            shift(array, 0, array.length, offset);
7120        }
7121    }
7122
7123    /**
7124     * Shifts the order of a series of elements in the given boolean array.
7125     *
7126     * <p>There is no special handling for multi-dimensional arrays. This method
7127     * does nothing for {@code null} or empty input arrays.</p>
7128     *
7129     * @param array
7130     *            the array to shift, may be {@code null}.
7131     * @param startIndexInclusive
7132     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7133     *            change.
7134     * @param endIndexExclusive
7135     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7136     *            change. Overvalue (&gt;array.length) is demoted to array length.
7137     * @param offset
7138     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7139     *          rotate, than the effective offset is modulo the number of elements to rotate.
7140     * @since 3.5
7141     */
7142    public static void shift(final boolean[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7143        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7144            return;
7145        }
7146        startIndexInclusive = max0(startIndexInclusive);
7147        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7148        int n = endIndexExclusive - startIndexInclusive;
7149        if (n <= 1) {
7150            return;
7151        }
7152        offset %= n;
7153        if (offset < 0) {
7154            offset += n;
7155        }
7156        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7157        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7158        while (n > 1 && offset > 0) {
7159            final int nOffset = n - offset;
7160            if (offset > nOffset) {
7161                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7162                n = offset;
7163                offset -= nOffset;
7164            } else if (offset < nOffset) {
7165                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7166                startIndexInclusive += offset;
7167                n = nOffset;
7168            } else {
7169                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7170                break;
7171            }
7172        }
7173    }
7174
7175    /**
7176     * Shifts the order of the given byte array.
7177     *
7178     * <p>There is no special handling for multi-dimensional arrays. This method
7179     * does nothing for {@code null} or empty input arrays.</p>
7180     *
7181     * @param array  the array to shift, may be {@code null}.
7182     * @param offset
7183     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7184     *          rotate, than the effective offset is modulo the number of elements to rotate.
7185     * @since 3.5
7186     */
7187    public static void shift(final byte[] array, final int offset) {
7188        if (array != null) {
7189            shift(array, 0, array.length, offset);
7190        }
7191    }
7192
7193    /**
7194     * Shifts the order of a series of elements in the given byte array.
7195     *
7196     * <p>There is no special handling for multi-dimensional arrays. This method
7197     * does nothing for {@code null} or empty input arrays.</p>
7198     *
7199     * @param array
7200     *            the array to shift, may be {@code null}.
7201     * @param startIndexInclusive
7202     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7203     *            change.
7204     * @param endIndexExclusive
7205     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7206     *            change. Overvalue (&gt;array.length) is demoted to array length.
7207     * @param offset
7208     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7209     *          rotate, than the effective offset is modulo the number of elements to rotate.
7210     * @since 3.5
7211     */
7212    public static void shift(final byte[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7213        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7214            return;
7215        }
7216        startIndexInclusive = max0(startIndexInclusive);
7217        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7218        int n = endIndexExclusive - startIndexInclusive;
7219        if (n <= 1) {
7220            return;
7221        }
7222        offset %= n;
7223        if (offset < 0) {
7224            offset += n;
7225        }
7226        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7227        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7228        while (n > 1 && offset > 0) {
7229            final int nOffset = n - offset;
7230            if (offset > nOffset) {
7231                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7232                n = offset;
7233                offset -= nOffset;
7234            } else if (offset < nOffset) {
7235                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7236                startIndexInclusive += offset;
7237                n = nOffset;
7238            } else {
7239                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7240                break;
7241            }
7242        }
7243    }
7244
7245    /**
7246     * Shifts the order of the given char array.
7247     *
7248     * <p>There is no special handling for multi-dimensional arrays. This method
7249     * does nothing for {@code null} or empty input arrays.</p>
7250     *
7251     * @param array  the array to shift, may be {@code null}.
7252     * @param offset
7253     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7254     *          rotate, than the effective offset is modulo the number of elements to rotate.
7255     * @since 3.5
7256     */
7257    public static void shift(final char[] array, final int offset) {
7258        if (array != null) {
7259            shift(array, 0, array.length, offset);
7260        }
7261    }
7262
7263    /**
7264     * Shifts the order of a series of elements in the given char array.
7265     *
7266     * <p>There is no special handling for multi-dimensional arrays. This method
7267     * does nothing for {@code null} or empty input arrays.</p>
7268     *
7269     * @param array
7270     *            the array to shift, may be {@code null}.
7271     * @param startIndexInclusive
7272     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7273     *            change.
7274     * @param endIndexExclusive
7275     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7276     *            change. Overvalue (&gt;array.length) is demoted to array length.
7277     * @param offset
7278     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7279     *          rotate, than the effective offset is modulo the number of elements to rotate.
7280     * @since 3.5
7281     */
7282    public static void shift(final char[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7283        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7284            return;
7285        }
7286        startIndexInclusive = max0(startIndexInclusive);
7287        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7288        int n = endIndexExclusive - startIndexInclusive;
7289        if (n <= 1) {
7290            return;
7291        }
7292        offset %= n;
7293        if (offset < 0) {
7294            offset += n;
7295        }
7296        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7297        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7298        while (n > 1 && offset > 0) {
7299            final int nOffset = n - offset;
7300            if (offset > nOffset) {
7301                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7302                n = offset;
7303                offset -= nOffset;
7304            } else if (offset < nOffset) {
7305                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7306                startIndexInclusive += offset;
7307                n = nOffset;
7308            } else {
7309                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7310                break;
7311            }
7312        }
7313    }
7314
7315    /**
7316     * Shifts the order of the given double array.
7317     *
7318     * <p>There is no special handling for multi-dimensional arrays. This method
7319     * does nothing for {@code null} or empty input arrays.</p>
7320     *
7321     * @param array  the array to shift, may be {@code null}.
7322     * @param offset
7323     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7324     *          rotate, than the effective offset is modulo the number of elements to rotate.
7325     * @since 3.5
7326     */
7327    public static void shift(final double[] array, final int offset) {
7328        if (array != null) {
7329            shift(array, 0, array.length, offset);
7330        }
7331    }
7332
7333    /**
7334     * Shifts the order of a series of elements in the given double array.
7335     *
7336     * <p>There is no special handling for multi-dimensional arrays. This method
7337     * does nothing for {@code null} or empty input arrays.</p>
7338     *
7339     * @param array
7340     *            the array to shift, may be {@code null}.
7341     * @param startIndexInclusive
7342     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7343     *            change.
7344     * @param endIndexExclusive
7345     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7346     *            change. Overvalue (&gt;array.length) is demoted to array length.
7347     * @param offset
7348     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7349     *          rotate, than the effective offset is modulo the number of elements to rotate.
7350     * @since 3.5
7351     */
7352    public static void shift(final double[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7353        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7354            return;
7355        }
7356        startIndexInclusive = max0(startIndexInclusive);
7357        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7358        int n = endIndexExclusive - startIndexInclusive;
7359        if (n <= 1) {
7360            return;
7361        }
7362        offset %= n;
7363        if (offset < 0) {
7364            offset += n;
7365        }
7366        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7367        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7368        while (n > 1 && offset > 0) {
7369            final int nOffset = n - offset;
7370            if (offset > nOffset) {
7371                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7372                n = offset;
7373                offset -= nOffset;
7374            } else if (offset < nOffset) {
7375                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7376                startIndexInclusive += offset;
7377                n = nOffset;
7378            } else {
7379                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7380                break;
7381            }
7382        }
7383    }
7384
7385    /**
7386     * Shifts the order of the given float array.
7387     *
7388     * <p>There is no special handling for multi-dimensional arrays. This method
7389     * does nothing for {@code null} or empty input arrays.</p>
7390     *
7391     * @param array  the array to shift, may be {@code null}.
7392     * @param offset
7393     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7394     *          rotate, than the effective offset is modulo the number of elements to rotate.
7395     * @since 3.5
7396     */
7397    public static void shift(final float[] array, final int offset) {
7398        if (array != null) {
7399            shift(array, 0, array.length, offset);
7400        }
7401    }
7402
7403    /**
7404     * Shifts the order of a series of elements in the given float array.
7405     *
7406     * <p>There is no special handling for multi-dimensional arrays. This method
7407     * does nothing for {@code null} or empty input arrays.</p>
7408     *
7409     * @param array
7410     *            the array to shift, may be {@code null}.
7411     * @param startIndexInclusive
7412     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7413     *            change.
7414     * @param endIndexExclusive
7415     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7416     *            change. Overvalue (&gt;array.length) is demoted to array length.
7417     * @param offset
7418     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7419     *          rotate, than the effective offset is modulo the number of elements to rotate.
7420     * @since 3.5
7421     */
7422    public static void shift(final float[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7423        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7424            return;
7425        }
7426        startIndexInclusive = max0(startIndexInclusive);
7427        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7428        int n = endIndexExclusive - startIndexInclusive;
7429        if (n <= 1) {
7430            return;
7431        }
7432        offset %= n;
7433        if (offset < 0) {
7434            offset += n;
7435        }
7436        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7437        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7438        while (n > 1 && offset > 0) {
7439            final int nOffset = n - offset;
7440            if (offset > nOffset) {
7441                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7442                n = offset;
7443                offset -= nOffset;
7444            } else if (offset < nOffset) {
7445                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7446                startIndexInclusive += offset;
7447                n = nOffset;
7448            } else {
7449                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7450                break;
7451            }
7452        }
7453    }
7454
7455    /**
7456     * Shifts the order of the given int array.
7457     *
7458     * <p>There is no special handling for multi-dimensional arrays. This method
7459     * does nothing for {@code null} or empty input arrays.</p>
7460     *
7461     * @param array  the array to shift, may be {@code null}.
7462     * @param offset
7463     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7464     *          rotate, than the effective offset is modulo the number of elements to rotate.
7465     * @since 3.5
7466     */
7467    public static void shift(final int[] array, final int offset) {
7468        if (array != null) {
7469            shift(array, 0, array.length, offset);
7470        }
7471    }
7472
7473    /**
7474     * Shifts the order of a series of elements in the given int array.
7475     *
7476     * <p>There is no special handling for multi-dimensional arrays. This method
7477     * does nothing for {@code null} or empty input arrays.</p>
7478     *
7479     * @param array
7480     *            the array to shift, may be {@code null}.
7481     * @param startIndexInclusive
7482     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7483     *            change.
7484     * @param endIndexExclusive
7485     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7486     *            change. Overvalue (&gt;array.length) is demoted to array length.
7487     * @param offset
7488     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7489     *          rotate, than the effective offset is modulo the number of elements to rotate.
7490     * @since 3.5
7491     */
7492    public static void shift(final int[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7493        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7494            return;
7495        }
7496        startIndexInclusive = max0(startIndexInclusive);
7497        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7498        int n = endIndexExclusive - startIndexInclusive;
7499        if (n <= 1) {
7500            return;
7501        }
7502        offset %= n;
7503        if (offset < 0) {
7504            offset += n;
7505        }
7506        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7507        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7508        while (n > 1 && offset > 0) {
7509            final int nOffset = n - offset;
7510            if (offset > nOffset) {
7511                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7512                n = offset;
7513                offset -= nOffset;
7514            } else if (offset < nOffset) {
7515                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7516                startIndexInclusive += offset;
7517                n = nOffset;
7518            } else {
7519                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7520                break;
7521            }
7522        }
7523    }
7524
7525    /**
7526     * Shifts the order of the given long array.
7527     *
7528     * <p>There is no special handling for multi-dimensional arrays. This method
7529     * does nothing for {@code null} or empty input arrays.</p>
7530     *
7531     * @param array  the array to shift, may be {@code null}.
7532     * @param offset
7533     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7534     *          rotate, than the effective offset is modulo the number of elements to rotate.
7535     * @since 3.5
7536     */
7537    public static void shift(final long[] array, final int offset) {
7538        if (array != null) {
7539            shift(array, 0, array.length, offset);
7540        }
7541    }
7542
7543    /**
7544     * Shifts the order of a series of elements in the given long array.
7545     *
7546     * <p>There is no special handling for multi-dimensional arrays. This method
7547     * does nothing for {@code null} or empty input arrays.</p>
7548     *
7549     * @param array
7550     *            the array to shift, may be {@code null}.
7551     * @param startIndexInclusive
7552     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7553     *            change.
7554     * @param endIndexExclusive
7555     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7556     *            change. Overvalue (&gt;array.length) is demoted to array length.
7557     * @param offset
7558     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7559     *          rotate, than the effective offset is modulo the number of elements to rotate.
7560     * @since 3.5
7561     */
7562    public static void shift(final long[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7563        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7564            return;
7565        }
7566        startIndexInclusive = max0(startIndexInclusive);
7567        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7568        int n = endIndexExclusive - startIndexInclusive;
7569        if (n <= 1) {
7570            return;
7571        }
7572        offset %= n;
7573        if (offset < 0) {
7574            offset += n;
7575        }
7576        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7577        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7578        while (n > 1 && offset > 0) {
7579            final int nOffset = n - offset;
7580            if (offset > nOffset) {
7581                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7582                n = offset;
7583                offset -= nOffset;
7584            } else if (offset < nOffset) {
7585                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7586                startIndexInclusive += offset;
7587                n = nOffset;
7588            } else {
7589                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7590                break;
7591            }
7592        }
7593    }
7594
7595    /**
7596     * Shifts the order of the given array.
7597     *
7598     * <p>There is no special handling for multi-dimensional arrays. This method
7599     * does nothing for {@code null} or empty input arrays.</p>
7600     *
7601     * @param array  the array to shift, may be {@code null}.
7602     * @param offset
7603     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7604     *          rotate, than the effective offset is modulo the number of elements to rotate.
7605     * @since 3.5
7606     */
7607    public static void shift(final Object[] array, final int offset) {
7608        if (array != null) {
7609            shift(array, 0, array.length, offset);
7610        }
7611    }
7612
7613    /**
7614     * Shifts the order of a series of elements in the given array.
7615     *
7616     * <p>There is no special handling for multi-dimensional arrays. This method
7617     * does nothing for {@code null} or empty input arrays.</p>
7618     *
7619     * @param array
7620     *            the array to shift, may be {@code null}.
7621     * @param startIndexInclusive
7622     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7623     *            change.
7624     * @param endIndexExclusive
7625     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7626     *            change. Overvalue (&gt;array.length) is demoted to array length.
7627     * @param offset
7628     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7629     *          rotate, than the effective offset is modulo the number of elements to rotate.
7630     * @since 3.5
7631     */
7632    public static void shift(final Object[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7633        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7634            return;
7635        }
7636        startIndexInclusive = max0(startIndexInclusive);
7637        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7638        int n = endIndexExclusive - startIndexInclusive;
7639        if (n <= 1) {
7640            return;
7641        }
7642        offset %= n;
7643        if (offset < 0) {
7644            offset += n;
7645        }
7646        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7647        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7648        while (n > 1 && offset > 0) {
7649            final int nOffset = n - offset;
7650            if (offset > nOffset) {
7651                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7652                n = offset;
7653                offset -= nOffset;
7654            } else if (offset < nOffset) {
7655                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7656                startIndexInclusive += offset;
7657                n = nOffset;
7658            } else {
7659                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7660                break;
7661            }
7662        }
7663    }
7664
7665    /**
7666     * Shifts the order of the given short array.
7667     *
7668     * <p>There is no special handling for multi-dimensional arrays. This method
7669     * does nothing for {@code null} or empty input arrays.</p>
7670     *
7671     * @param array  the array to shift, may be {@code null}.
7672     * @param offset
7673     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7674     *          rotate, than the effective offset is modulo the number of elements to rotate.
7675     * @since 3.5
7676     */
7677    public static void shift(final short[] array, final int offset) {
7678        if (array != null) {
7679            shift(array, 0, array.length, offset);
7680        }
7681    }
7682
7683    /**
7684     * Shifts the order of a series of elements in the given short array.
7685     *
7686     * <p>There is no special handling for multi-dimensional arrays. This method
7687     * does nothing for {@code null} or empty input arrays.</p>
7688     *
7689     * @param array
7690     *            the array to shift, may be {@code null}.
7691     * @param startIndexInclusive
7692     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7693     *            change.
7694     * @param endIndexExclusive
7695     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7696     *            change. Overvalue (&gt;array.length) is demoted to array length.
7697     * @param offset
7698     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7699     *          rotate, than the effective offset is modulo the number of elements to rotate.
7700     * @since 3.5
7701     */
7702    public static void shift(final short[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7703        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7704            return;
7705        }
7706        startIndexInclusive = max0(startIndexInclusive);
7707        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7708        int n = endIndexExclusive - startIndexInclusive;
7709        if (n <= 1) {
7710            return;
7711        }
7712        offset %= n;
7713        if (offset < 0) {
7714            offset += n;
7715        }
7716        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7717        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7718        while (n > 1 && offset > 0) {
7719            final int nOffset = n - offset;
7720            if (offset > nOffset) {
7721                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7722                n = offset;
7723                offset -= nOffset;
7724            } else if (offset < nOffset) {
7725                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7726                startIndexInclusive += offset;
7727                n = nOffset;
7728            } else {
7729                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7730                break;
7731            }
7732        }
7733    }
7734
7735    /**
7736     * 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
7737     * algorithm</a>.
7738     * <p>
7739     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7740     * </p>
7741     * <p>
7742     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7743     * with a {@link SecureRandom} argument.
7744     * </p>
7745     *
7746     * @param array the array to shuffle.
7747     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7748     * @since 3.6
7749     */
7750    public static void shuffle(final boolean[] array) {
7751        shuffle(array, random());
7752    }
7753
7754    /**
7755     * 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
7756     * algorithm</a>.
7757     *
7758     * @param array  the array to shuffle, no-op if {@code null}.
7759     * @param random the source of randomness used to permute the elements, no-op if {@code null}.
7760     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7761     * @since 3.6
7762     */
7763    public static void shuffle(final boolean[] array, final Random random) {
7764        if (array != null && random != null) {
7765            for (int i = array.length; i > 1; i--) {
7766                swap(array, i - 1, random.nextInt(i), 1);
7767            }
7768        }
7769    }
7770
7771    /**
7772     * 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
7773     * algorithm</a>.
7774     * <p>
7775     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7776     * </p>
7777     * <p>
7778     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7779     * with a {@link SecureRandom} argument.
7780     * </p>
7781     *
7782     * @param array the array to shuffle.
7783     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7784     * @since 3.6
7785     */
7786    public static void shuffle(final byte[] array) {
7787        shuffle(array, random());
7788    }
7789
7790    /**
7791     * 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
7792     * algorithm</a>.
7793     *
7794     * @param array  the array to shuffle, no-op if {@code null}.
7795     * @param random the source of randomness used to permute the elements, no-op if {@code null}.
7796     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7797     * @since 3.6
7798     */
7799    public static void shuffle(final byte[] array, final Random random) {
7800        if (array != null && random != null) {
7801            for (int i = array.length; i > 1; i--) {
7802                swap(array, i - 1, random.nextInt(i), 1);
7803            }
7804        }
7805    }
7806
7807    /**
7808     * 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
7809     * algorithm</a>.
7810     * <p>
7811     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7812     * </p>
7813     * <p>
7814     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7815     * with a {@link SecureRandom} argument.
7816     * </p>
7817     *
7818     * @param array the array to shuffle.
7819     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7820     * @since 3.6
7821     */
7822    public static void shuffle(final char[] array) {
7823        shuffle(array, random());
7824    }
7825
7826    /**
7827     * 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
7828     * algorithm</a>.
7829     *
7830     * @param array  the array to shuffle, no-op if {@code null}.
7831     * @param random the source of randomness used to permute the elements, no-op if {@code null}.
7832     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7833     * @since 3.6
7834     */
7835    public static void shuffle(final char[] array, final Random random) {
7836        if (array != null && random != null) {
7837            for (int i = array.length; i > 1; i--) {
7838                swap(array, i - 1, random.nextInt(i), 1);
7839            }
7840        }
7841    }
7842
7843    /**
7844     * 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
7845     * algorithm</a>.
7846     * <p>
7847     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7848     * </p>
7849     * <p>
7850     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7851     * with a {@link SecureRandom} argument.
7852     * </p>
7853     *
7854     * @param array the array to shuffle.
7855     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7856     * @since 3.6
7857     */
7858    public static void shuffle(final double[] array) {
7859        shuffle(array, random());
7860    }
7861
7862    /**
7863     * 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
7864     * algorithm</a>.
7865     *
7866     * @param array  the array to shuffle, no-op if {@code null}.
7867     * @param random the source of randomness used to permute the elements, no-op if {@code null}.
7868     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7869     * @since 3.6
7870     */
7871    public static void shuffle(final double[] array, final Random random) {
7872        if (array != null && random != null) {
7873            for (int i = array.length; i > 1; i--) {
7874                swap(array, i - 1, random.nextInt(i), 1);
7875            }
7876        }
7877    }
7878
7879    /**
7880     * 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
7881     * algorithm</a>.
7882     * <p>
7883     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7884     * </p>
7885     * <p>
7886     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7887     * with a {@link SecureRandom} argument.
7888     * </p>
7889     *
7890     * @param array the array to shuffle.
7891     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7892     * @since 3.6
7893     */
7894    public static void shuffle(final float[] array) {
7895        shuffle(array, random());
7896    }
7897
7898    /**
7899     * 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
7900     * algorithm</a>.
7901     *
7902     * @param array  the array to shuffle, no-op if {@code null}.
7903     * @param random the source of randomness used to permute the elements, no-op if {@code null}.
7904     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7905     * @since 3.6
7906     */
7907    public static void shuffle(final float[] array, final Random random) {
7908        if (array != null && random != null) {
7909            for (int i = array.length; i > 1; i--) {
7910                swap(array, i - 1, random.nextInt(i), 1);
7911            }
7912        }
7913    }
7914
7915    /**
7916     * 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
7917     * algorithm</a>.
7918     * <p>
7919     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7920     * </p>
7921     * <p>
7922     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7923     * with a {@link SecureRandom} argument.
7924     * </p>
7925     *
7926     * @param array the array to shuffle.
7927     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7928     * @since 3.6
7929     */
7930    public static void shuffle(final int[] array) {
7931        shuffle(array, random());
7932    }
7933
7934    /**
7935     * 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
7936     * algorithm</a>.
7937     *
7938     * @param array  the array to shuffle, no-op if {@code null}.
7939     * @param random the source of randomness used to permute the elements, no-op if {@code null}.
7940     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7941     * @since 3.6
7942     */
7943    public static void shuffle(final int[] array, final Random random) {
7944        if (array != null && random != null) {
7945            for (int i = array.length; i > 1; i--) {
7946                swap(array, i - 1, random.nextInt(i), 1);
7947            }
7948        }
7949    }
7950
7951    /**
7952     * 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
7953     * algorithm</a>.
7954     * <p>
7955     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7956     * </p>
7957     * <p>
7958     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7959     * with a {@link SecureRandom} argument.
7960     * </p>
7961     *
7962     * @param array the array to shuffle.
7963     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7964     * @since 3.6
7965     */
7966    public static void shuffle(final long[] array) {
7967        shuffle(array, random());
7968    }
7969
7970    /**
7971     * 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
7972     * algorithm</a>.
7973     *
7974     * @param array  the array to shuffle, no-op if {@code null}.
7975     * @param random the source of randomness used to permute the elements, no-op if {@code null}.
7976     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7977     * @since 3.6
7978     */
7979    public static void shuffle(final long[] array, final Random random) {
7980        if (array != null && random != null) {
7981            for (int i = array.length; i > 1; i--) {
7982                swap(array, i - 1, random.nextInt(i), 1);
7983            }
7984        }
7985    }
7986
7987    /**
7988     * 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
7989     * algorithm</a>.
7990     * <p>
7991     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7992     * </p>
7993     * <p>
7994     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7995     * with a {@link SecureRandom} argument.
7996     * </p>
7997     *
7998     * @param array the array to shuffle.
7999     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8000     * @since 3.6
8001     */
8002    public static void shuffle(final Object[] array) {
8003        shuffle(array, random());
8004    }
8005
8006    /**
8007     * 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
8008     * algorithm</a>.
8009     *
8010     * @param array  the array to shuffle, no-op if {@code null}.
8011     * @param random the source of randomness used to permute the elements, no-op if {@code null}.
8012     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8013     * @since 3.6
8014     */
8015    public static void shuffle(final Object[] array, final Random random) {
8016        if (array != null && random != null) {
8017            for (int i = array.length; i > 1; i--) {
8018                swap(array, i - 1, random.nextInt(i), 1);
8019            }
8020        }
8021    }
8022
8023    /**
8024     * 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
8025     * algorithm</a>.
8026     * <p>
8027     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
8028     * </p>
8029     * <p>
8030     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
8031     * with a {@link SecureRandom} argument.
8032     * </p>
8033     *
8034     * @param array the array to shuffle.
8035     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8036     * @since 3.6
8037     */
8038    public static void shuffle(final short[] array) {
8039        shuffle(array, random());
8040    }
8041
8042    /**
8043     * 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
8044     * algorithm</a>.
8045     *
8046     * @param array  the array to shuffle, no-op if {@code null}.
8047     * @param random the source of randomness used to permute the elements, no-op if {@code null}.
8048     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8049     * @since 3.6
8050     */
8051    public static void shuffle(final short[] array, final Random random) {
8052        if (array != null && random != null) {
8053            for (int i = array.length; i > 1; i--) {
8054                swap(array, i - 1, random.nextInt(i), 1);
8055            }
8056        }
8057    }
8058
8059    /**
8060     * Tests whether the given data array starts with an expected array, for example, signature bytes.
8061     * <p>
8062     * If both arrays are null, the method returns true. The method return false when one array is null and the other not.
8063     * </p>
8064     *
8065     * @param data     The data to search, maybe larger than the expected data.
8066     * @param expected The expected data to find.
8067     * @return whether a match was found.
8068     * @since 3.18.0
8069     */
8070    public static boolean startsWith(final byte[] data, final byte[] expected) {
8071        if (data == expected) {
8072            return true;
8073        }
8074        if (data == null || expected == null) {
8075            return false;
8076        }
8077        final int dataLen = data.length;
8078        if (expected.length > dataLen) {
8079            return false;
8080        }
8081        if (expected.length == dataLen) {
8082            // delegate to Arrays.equals() which has optimizations on Java > 8
8083            return Arrays.equals(data, expected);
8084        }
8085        // Once we are on Java 9+ we can delegate to Arrays here as well (or not).
8086        for (int i = 0; i < expected.length; i++) {
8087            if (data[i] != expected[i]) {
8088                return false;
8089            }
8090        }
8091        return true;
8092    }
8093
8094    /**
8095     * Produces a new {@code boolean} array containing the elements between the start and end indices.
8096     * <p>
8097     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8098     * </p>
8099     *
8100     * @param array               the input array.
8101     * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8102     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8103     *                            (&gt;array.length) is demoted to array length.
8104     * @return a new array containing the elements between the start and end indices.
8105     * @since 2.1
8106     * @see Arrays#copyOfRange(boolean[], int, int)
8107     */
8108    public static boolean[] subarray(final boolean[] array, int startIndexInclusive, int endIndexExclusive) {
8109        if (array == null) {
8110            return null;
8111        }
8112        startIndexInclusive = max0(startIndexInclusive);
8113        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8114        final int newSize = endIndexExclusive - startIndexInclusive;
8115        if (newSize <= 0) {
8116            return EMPTY_BOOLEAN_ARRAY;
8117        }
8118        return arraycopy(array, startIndexInclusive, 0, newSize, boolean[]::new);
8119    }
8120
8121    /**
8122     * Produces a new {@code byte} array containing the elements between the start and end indices.
8123     * <p>
8124     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8125     * </p>
8126     *
8127     * @param array               the input array.
8128     * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8129     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8130     *                            (&gt;array.length) is demoted to array length.
8131     * @return a new array containing the elements between the start and end indices.
8132     * @since 2.1
8133     * @see Arrays#copyOfRange(byte[], int, int)
8134     */
8135    public static byte[] subarray(final byte[] array, int startIndexInclusive, int endIndexExclusive) {
8136        if (array == null) {
8137            return null;
8138        }
8139        startIndexInclusive = max0(startIndexInclusive);
8140        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8141        final int newSize = endIndexExclusive - startIndexInclusive;
8142        if (newSize <= 0) {
8143            return EMPTY_BYTE_ARRAY;
8144        }
8145        return arraycopy(array, startIndexInclusive, 0, newSize, byte[]::new);
8146    }
8147
8148    /**
8149     * Produces a new {@code char} array containing the elements between the start and end indices.
8150     * <p>
8151     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8152     * </p>
8153     *
8154     * @param array               the input array.
8155     * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8156     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8157     *                            (&gt;array.length) is demoted to array length.
8158     * @return a new array containing the elements between the start and end indices.
8159     * @since 2.1
8160     * @see Arrays#copyOfRange(char[], int, int)
8161     */
8162    public static char[] subarray(final char[] array, int startIndexInclusive, int endIndexExclusive) {
8163        if (array == null) {
8164            return null;
8165        }
8166        startIndexInclusive = max0(startIndexInclusive);
8167        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8168        final int newSize = endIndexExclusive - startIndexInclusive;
8169        if (newSize <= 0) {
8170            return EMPTY_CHAR_ARRAY;
8171        }
8172        return arraycopy(array, startIndexInclusive, 0, newSize, char[]::new);
8173    }
8174
8175    /**
8176     * Produces a new {@code double} array containing the elements between the start and end indices.
8177     * <p>
8178     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8179     * </p>
8180     *
8181     * @param array               the input array.
8182     * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8183     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8184     *                            (&gt;array.length) is demoted to array length.
8185     * @return a new array containing the elements between the start and end indices.
8186     * @since 2.1
8187     * @see Arrays#copyOfRange(double[], int, int)
8188     */
8189    public static double[] subarray(final double[] array, int startIndexInclusive, int endIndexExclusive) {
8190        if (array == null) {
8191            return null;
8192        }
8193        startIndexInclusive = max0(startIndexInclusive);
8194        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8195        final int newSize = endIndexExclusive - startIndexInclusive;
8196        if (newSize <= 0) {
8197            return EMPTY_DOUBLE_ARRAY;
8198        }
8199        return arraycopy(array, startIndexInclusive, 0, newSize, double[]::new);
8200    }
8201
8202    /**
8203     * Produces a new {@code float} array containing the elements between the start and end indices.
8204     * <p>
8205     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8206     * </p>
8207     *
8208     * @param array               the input array.
8209     * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8210     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8211     *                            (&gt;array.length) is demoted to array length.
8212     * @return a new array containing the elements between the start and end indices.
8213     * @since 2.1
8214     * @see Arrays#copyOfRange(float[], int, int)
8215     */
8216    public static float[] subarray(final float[] array, int startIndexInclusive, int endIndexExclusive) {
8217        if (array == null) {
8218            return null;
8219        }
8220        startIndexInclusive = max0(startIndexInclusive);
8221        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8222        final int newSize = endIndexExclusive - startIndexInclusive;
8223        if (newSize <= 0) {
8224            return EMPTY_FLOAT_ARRAY;
8225        }
8226        return arraycopy(array, startIndexInclusive, 0, newSize, float[]::new);
8227    }
8228
8229    /**
8230     * Produces a new {@code int} array containing the elements between the start and end indices.
8231     * <p>
8232     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8233     * </p>
8234     *
8235     * @param array               the input array.
8236     * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8237     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8238     *                            (&gt;array.length) is demoted to array length.
8239     * @return a new array containing the elements between the start and end indices.
8240     * @since 2.1
8241     * @see Arrays#copyOfRange(int[], int, int)
8242     */
8243    public static int[] subarray(final int[] array, int startIndexInclusive, int endIndexExclusive) {
8244        if (array == null) {
8245            return null;
8246        }
8247        startIndexInclusive = max0(startIndexInclusive);
8248        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8249        final int newSize = endIndexExclusive - startIndexInclusive;
8250        if (newSize <= 0) {
8251            return EMPTY_INT_ARRAY;
8252        }
8253        return arraycopy(array, startIndexInclusive, 0, newSize, int[]::new);
8254    }
8255
8256    /**
8257     * Produces a new {@code long} array containing the elements between the start and end indices.
8258     * <p>
8259     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8260     * </p>
8261     *
8262     * @param array               the input array.
8263     * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8264     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8265     *                            (&gt;array.length) is demoted to array length.
8266     * @return a new array containing the elements between the start and end indices.
8267     * @since 2.1
8268     * @see Arrays#copyOfRange(long[], int, int)
8269     */
8270    public static long[] subarray(final long[] array, int startIndexInclusive, int endIndexExclusive) {
8271        if (array == null) {
8272            return null;
8273        }
8274        startIndexInclusive = max0(startIndexInclusive);
8275        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8276        final int newSize = endIndexExclusive - startIndexInclusive;
8277        if (newSize <= 0) {
8278            return EMPTY_LONG_ARRAY;
8279        }
8280        return arraycopy(array, startIndexInclusive, 0, newSize, long[]::new);
8281    }
8282
8283    /**
8284     * Produces a new {@code short} array containing the elements between the start and end indices.
8285     * <p>
8286     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8287     * </p>
8288     *
8289     * @param array               the input array.
8290     * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8291     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8292     *                            (&gt;array.length) is demoted to array length.
8293     * @return a new array containing the elements between the start and end indices.
8294     * @since 2.1
8295     * @see Arrays#copyOfRange(short[], int, int)
8296     */
8297    public static short[] subarray(final short[] array, int startIndexInclusive, int endIndexExclusive) {
8298        if (array == null) {
8299            return null;
8300        }
8301        startIndexInclusive = max0(startIndexInclusive);
8302        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8303        final int newSize = endIndexExclusive - startIndexInclusive;
8304        if (newSize <= 0) {
8305            return EMPTY_SHORT_ARRAY;
8306        }
8307        return arraycopy(array, startIndexInclusive, 0, newSize, short[]::new);
8308    }
8309
8310    /**
8311     * Produces a new array containing the elements between the start and end indices.
8312     * <p>
8313     * The start index is inclusive, the end index exclusive. Null array input produces null output.
8314     * </p>
8315     * <p>
8316     * 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
8317     * usage is envisaged:
8318     * </p>
8319     *
8320     * <pre>
8321     *
8322     * Date[] someDates = (Date[]) ArrayUtils.subarray(allDates, 2, 5);
8323     * </pre>
8324     *
8325     * @param <T>                 the component type of the array.
8326     * @param array               the input array.
8327     * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8328     * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8329     *                            (&gt;array.length) is demoted to array length.
8330     * @return a new array containing the elements between the start and end indices.
8331     * @since 2.1
8332     * @see Arrays#copyOfRange(Object[], int, int)
8333     */
8334    public static <T> T[] subarray(final T[] array, int startIndexInclusive, int endIndexExclusive) {
8335        if (array == null) {
8336            return null;
8337        }
8338        startIndexInclusive = max0(startIndexInclusive);
8339        endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8340        final int newSize = endIndexExclusive - startIndexInclusive;
8341        final Class<T> type = getComponentType(array);
8342        if (newSize <= 0) {
8343            return newInstance(type, 0);
8344        }
8345        return arraycopy(array, startIndexInclusive, 0, newSize, () -> newInstance(type, newSize));
8346    }
8347
8348    /**
8349     * Swaps two elements in the given boolean array.
8350     *
8351     * <p>There is no special handling for multi-dimensional arrays. This method
8352     * does nothing for a {@code null} or empty input array or for overflow indices.
8353     * Negative indices are promoted to 0(zero).</p>
8354     *
8355     * Examples:
8356     * <ul>
8357     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8358     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8359     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8360     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8361     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8362     * </ul>
8363     *
8364     * @param array  the array to swap, may be {@code null}.
8365     * @param offset1 the index of the first element to swap.
8366     * @param offset2 the index of the second element to swap.
8367     * @since 3.5
8368     */
8369    public static void swap(final boolean[] array, final int offset1, final int offset2) {
8370        swap(array, offset1, offset2, 1);
8371    }
8372
8373    /**
8374     * Swaps a series of elements in the given boolean array.
8375     *
8376     * <p>This method does nothing for a {@code null} or empty input array or
8377     * for overflow indices. Negative indices are promoted to 0(zero). If any
8378     * of the sub-arrays to swap falls outside of the given array, then the
8379     * swap is stopped at the end of the array and as many as possible elements
8380     * are swapped.</p>
8381     *
8382     * Examples:
8383     * <ul>
8384     *     <li>ArrayUtils.swap([true, false, true, false], 0, 2, 1) -&gt; [true, false, true, false]</li>
8385     *     <li>ArrayUtils.swap([true, false, true, false], 0, 0, 1) -&gt; [true, false, true, false]</li>
8386     *     <li>ArrayUtils.swap([true, false, true, false], 0, 2, 2) -&gt; [true, false, true, false]</li>
8387     *     <li>ArrayUtils.swap([true, false, true, false], -3, 2, 2) -&gt; [true, false, true, false]</li>
8388     *     <li>ArrayUtils.swap([true, false, true, false], 0, 3, 3) -&gt; [false, false, true, true]</li>
8389     * </ul>
8390     *
8391     * @param array the array to swap, may be {@code null}.
8392     * @param offset1 the index of the first element in the series to swap.
8393     * @param offset2 the index of the second element in the series to swap.
8394     * @param len the number of elements to swap starting with the given indices.
8395     * @since 3.5
8396     */
8397    public static void swap(final boolean[] array, int offset1, int offset2, int len) {
8398        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8399            return;
8400        }
8401        offset1 = max0(offset1);
8402        offset2 = max0(offset2);
8403        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8404        for (int i = 0; i < len; i++, offset1++, offset2++) {
8405            final boolean aux = array[offset1];
8406            array[offset1] = array[offset2];
8407            array[offset2] = aux;
8408        }
8409    }
8410
8411    /**
8412     * Swaps two elements in the given byte array.
8413     *
8414     * <p>There is no special handling for multi-dimensional arrays. This method
8415     * does nothing for a {@code null} or empty input array or for overflow indices.
8416     * Negative indices are promoted to 0(zero).</p>
8417     *
8418     * Examples:
8419     * <ul>
8420     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8421     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8422     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8423     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8424     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8425     * </ul>
8426     *
8427     * @param array  the array to swap, may be {@code null}.
8428     * @param offset1 the index of the first element to swap.
8429     * @param offset2 the index of the second element to swap.
8430     * @since 3.5
8431     */
8432    public static void swap(final byte[] array, final int offset1, final int offset2) {
8433        swap(array, offset1, offset2, 1);
8434    }
8435
8436    /**
8437     * Swaps a series of elements in the given byte array.
8438     *
8439     * <p>This method does nothing for a {@code null} or empty input array or
8440     * for overflow indices. Negative indices are promoted to 0(zero). If any
8441     * of the sub-arrays to swap falls outside of the given array, then the
8442     * swap is stopped at the end of the array and as many as possible elements
8443     * are swapped.</p>
8444     *
8445     * Examples:
8446     * <ul>
8447     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8448     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8449     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8450     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8451     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8452     * </ul>
8453     *
8454     * @param array the array to swap, may be {@code null}.
8455     * @param offset1 the index of the first element in the series to swap.
8456     * @param offset2 the index of the second element in the series to swap.
8457     * @param len the number of elements to swap starting with the given indices.
8458     * @since 3.5
8459     */
8460    public static void swap(final byte[] array, int offset1, int offset2, int len) {
8461        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8462            return;
8463        }
8464        offset1 = max0(offset1);
8465        offset2 = max0(offset2);
8466        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8467        for (int i = 0; i < len; i++, offset1++, offset2++) {
8468            final byte aux = array[offset1];
8469            array[offset1] = array[offset2];
8470            array[offset2] = aux;
8471        }
8472    }
8473
8474    /**
8475     * Swaps two elements in the given char array.
8476     *
8477     * <p>There is no special handling for multi-dimensional arrays. This method
8478     * does nothing for a {@code null} or empty input array or for overflow indices.
8479     * Negative indices are promoted to 0(zero).</p>
8480     *
8481     * Examples:
8482     * <ul>
8483     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8484     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8485     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8486     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8487     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8488     * </ul>
8489     *
8490     * @param array  the array to swap, may be {@code null}.
8491     * @param offset1 the index of the first element to swap.
8492     * @param offset2 the index of the second element to swap.
8493     * @since 3.5
8494     */
8495    public static void swap(final char[] array, final int offset1, final int offset2) {
8496        swap(array, offset1, offset2, 1);
8497    }
8498
8499    /**
8500     * Swaps a series of elements in the given char array.
8501     *
8502     * <p>This method does nothing for a {@code null} or empty input array or
8503     * for overflow indices. Negative indices are promoted to 0(zero). If any
8504     * of the sub-arrays to swap falls outside of the given array, then the
8505     * swap is stopped at the end of the array and as many as possible elements
8506     * are swapped.</p>
8507     *
8508     * Examples:
8509     * <ul>
8510     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8511     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8512     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8513     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8514     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8515     * </ul>
8516     *
8517     * @param array the array to swap, may be {@code null}.
8518     * @param offset1 the index of the first element in the series to swap.
8519     * @param offset2 the index of the second element in the series to swap.
8520     * @param len the number of elements to swap starting with the given indices.
8521     * @since 3.5
8522     */
8523    public static void swap(final char[] array, int offset1, int offset2, int len) {
8524        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8525            return;
8526        }
8527        offset1 = max0(offset1);
8528        offset2 = max0(offset2);
8529        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8530        for (int i = 0; i < len; i++, offset1++, offset2++) {
8531            final char aux = array[offset1];
8532            array[offset1] = array[offset2];
8533            array[offset2] = aux;
8534        }
8535    }
8536
8537    /**
8538     * Swaps two elements in the given double array.
8539     *
8540     * <p>There is no special handling for multi-dimensional arrays. This method
8541     * does nothing for a {@code null} or empty input array or for overflow indices.
8542     * Negative indices are promoted to 0(zero).</p>
8543     *
8544     * Examples:
8545     * <ul>
8546     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8547     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8548     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8549     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8550     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8551     * </ul>
8552     *
8553     * @param array  the array to swap, may be {@code null}.
8554     * @param offset1 the index of the first element to swap.
8555     * @param offset2 the index of the second element to swap.
8556     * @since 3.5
8557     */
8558    public static void swap(final double[] array, final int offset1, final int offset2) {
8559        swap(array, offset1, offset2, 1);
8560    }
8561
8562    /**
8563     * Swaps a series of elements in the given double array.
8564     *
8565     * <p>This method does nothing for a {@code null} or empty input array or
8566     * for overflow indices. Negative indices are promoted to 0(zero). If any
8567     * of the sub-arrays to swap falls outside of the given array, then the
8568     * swap is stopped at the end of the array and as many as possible elements
8569     * are swapped.</p>
8570     *
8571     * Examples:
8572     * <ul>
8573     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8574     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8575     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8576     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8577     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8578     * </ul>
8579     *
8580     * @param array the array to swap, may be {@code null}.
8581     * @param offset1 the index of the first element in the series to swap.
8582     * @param offset2 the index of the second element in the series to swap.
8583     * @param len the number of elements to swap starting with the given indices.
8584     * @since 3.5
8585     */
8586    public static void swap(final double[] array,  int offset1, int offset2, int len) {
8587        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8588            return;
8589        }
8590        offset1 = max0(offset1);
8591        offset2 = max0(offset2);
8592        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8593        for (int i = 0; i < len; i++, offset1++, offset2++) {
8594            final double aux = array[offset1];
8595            array[offset1] = array[offset2];
8596            array[offset2] = aux;
8597        }
8598    }
8599
8600    /**
8601     * Swaps two elements in the given float array.
8602     *
8603     * <p>There is no special handling for multi-dimensional arrays. This method
8604     * does nothing for a {@code null} or empty input array or for overflow indices.
8605     * Negative indices are promoted to 0(zero).</p>
8606     *
8607     * Examples:
8608     * <ul>
8609     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8610     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8611     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8612     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8613     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8614     * </ul>
8615     *
8616     * @param array  the array to swap, may be {@code null}.
8617     * @param offset1 the index of the first element to swap.
8618     * @param offset2 the index of the second element to swap.
8619     * @since 3.5
8620     */
8621    public static void swap(final float[] array, final int offset1, final int offset2) {
8622        swap(array, offset1, offset2, 1);
8623    }
8624
8625    /**
8626     * Swaps a series of elements in the given float array.
8627     *
8628     * <p>This method does nothing for a {@code null} or empty input array or
8629     * for overflow indices. Negative indices are promoted to 0(zero). If any
8630     * of the sub-arrays to swap falls outside of the given array, then the
8631     * swap is stopped at the end of the array and as many as possible elements
8632     * are swapped.</p>
8633     *
8634     * Examples:
8635     * <ul>
8636     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8637     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8638     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8639     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8640     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8641     * </ul>
8642     *
8643     * @param array the array to swap, may be {@code null}.
8644     * @param offset1 the index of the first element in the series to swap.
8645     * @param offset2 the index of the second element in the series to swap.
8646     * @param len the number of elements to swap starting with the given indices.
8647     * @since 3.5
8648     */
8649    public static void swap(final float[] array, int offset1, int offset2, int len) {
8650        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8651            return;
8652        }
8653        offset1 = max0(offset1);
8654        offset2 = max0(offset2);
8655        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8656        for (int i = 0; i < len; i++, offset1++, offset2++) {
8657            final float aux = array[offset1];
8658            array[offset1] = array[offset2];
8659            array[offset2] = aux;
8660        }
8661
8662    }
8663
8664    /**
8665     * Swaps two elements in the given int array.
8666     *
8667     * <p>There is no special handling for multi-dimensional arrays. This method
8668     * does nothing for a {@code null} or empty input array or for overflow indices.
8669     * Negative indices are promoted to 0(zero).</p>
8670     *
8671     * Examples:
8672     * <ul>
8673     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8674     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8675     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8676     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8677     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8678     * </ul>
8679     *
8680     * @param array  the array to swap, may be {@code null}.
8681     * @param offset1 the index of the first element to swap.
8682     * @param offset2 the index of the second element to swap.
8683     * @since 3.5
8684     */
8685    public static void swap(final int[] array, final int offset1, final int offset2) {
8686        swap(array, offset1, offset2, 1);
8687    }
8688
8689    /**
8690     * Swaps a series of elements in the given int array.
8691     *
8692     * <p>This method does nothing for a {@code null} or empty input array or
8693     * for overflow indices. Negative indices are promoted to 0(zero). If any
8694     * of the sub-arrays to swap falls outside of the given array, then the
8695     * swap is stopped at the end of the array and as many as possible elements
8696     * are swapped.</p>
8697     *
8698     * Examples:
8699     * <ul>
8700     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8701     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8702     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8703     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8704     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8705     * </ul>
8706     *
8707     * @param array the array to swap, may be {@code null}.
8708     * @param offset1 the index of the first element in the series to swap.
8709     * @param offset2 the index of the second element in the series to swap.
8710     * @param len the number of elements to swap starting with the given indices.
8711     * @since 3.5
8712     */
8713    public static void swap(final int[] array,  int offset1, int offset2, int len) {
8714        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8715            return;
8716        }
8717        offset1 = max0(offset1);
8718        offset2 = max0(offset2);
8719        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8720        for (int i = 0; i < len; i++, offset1++, offset2++) {
8721            final int aux = array[offset1];
8722            array[offset1] = array[offset2];
8723            array[offset2] = aux;
8724        }
8725    }
8726
8727    /**
8728     * Swaps two elements in the given long array.
8729     *
8730     * <p>There is no special handling for multi-dimensional arrays. This method
8731     * does nothing for a {@code null} or empty input array or for overflow indices.
8732     * Negative indices are promoted to 0(zero).</p>
8733     *
8734     * Examples:
8735     * <ul>
8736     *     <li>ArrayUtils.swap([true, false, true], 0, 2) -&gt; [true, false, true]</li>
8737     *     <li>ArrayUtils.swap([true, false, true], 0, 0) -&gt; [true, false, true]</li>
8738     *     <li>ArrayUtils.swap([true, false, true], 1, 0) -&gt; [false, true, true]</li>
8739     *     <li>ArrayUtils.swap([true, false, true], 0, 5) -&gt; [true, false, true]</li>
8740     *     <li>ArrayUtils.swap([true, false, true], -1, 1) -&gt; [false, true, true]</li>
8741     * </ul>
8742     *
8743     * @param array  the array to swap, may be {@code null}.
8744     * @param offset1 the index of the first element to swap.
8745     * @param offset2 the index of the second element to swap.
8746     * @since 3.5
8747     */
8748    public static void swap(final long[] array, final int offset1, final int offset2) {
8749        swap(array, offset1, offset2, 1);
8750    }
8751
8752    /**
8753     * Swaps a series of elements in the given long array.
8754     *
8755     * <p>This method does nothing for a {@code null} or empty input array or
8756     * for overflow indices. Negative indices are promoted to 0(zero). If any
8757     * of the sub-arrays to swap falls outside of the given array, then the
8758     * swap is stopped at the end of the array and as many as possible elements
8759     * are swapped.</p>
8760     *
8761     * Examples:
8762     * <ul>
8763     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8764     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8765     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8766     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8767     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8768     * </ul>
8769     *
8770     * @param array the array to swap, may be {@code null}.
8771     * @param offset1 the index of the first element in the series to swap.
8772     * @param offset2 the index of the second element in the series to swap.
8773     * @param len the number of elements to swap starting with the given indices.
8774     * @since 3.5
8775     */
8776    public static void swap(final long[] array,  int offset1, int offset2, int len) {
8777        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8778            return;
8779        }
8780        offset1 = max0(offset1);
8781        offset2 = max0(offset2);
8782        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8783        for (int i = 0; i < len; i++, offset1++, offset2++) {
8784            final long aux = array[offset1];
8785            array[offset1] = array[offset2];
8786            array[offset2] = aux;
8787        }
8788    }
8789
8790    /**
8791     * Swaps two elements in the given array.
8792     *
8793     * <p>There is no special handling for multi-dimensional arrays. This method
8794     * does nothing for a {@code null} or empty input array or for overflow indices.
8795     * Negative indices are promoted to 0(zero).</p>
8796     *
8797     * Examples:
8798     * <ul>
8799     *     <li>ArrayUtils.swap(["1", "2", "3"], 0, 2) -&gt; ["3", "2", "1"]</li>
8800     *     <li>ArrayUtils.swap(["1", "2", "3"], 0, 0) -&gt; ["1", "2", "3"]</li>
8801     *     <li>ArrayUtils.swap(["1", "2", "3"], 1, 0) -&gt; ["2", "1", "3"]</li>
8802     *     <li>ArrayUtils.swap(["1", "2", "3"], 0, 5) -&gt; ["1", "2", "3"]</li>
8803     *     <li>ArrayUtils.swap(["1", "2", "3"], -1, 1) -&gt; ["2", "1", "3"]</li>
8804     * </ul>
8805     *
8806     * @param array the array to swap, may be {@code null}.
8807     * @param offset1 the index of the first element to swap.
8808     * @param offset2 the index of the second element to swap.
8809     * @since 3.5
8810     */
8811    public static void swap(final Object[] array, final int offset1, final int offset2) {
8812        swap(array, offset1, offset2, 1);
8813    }
8814
8815    /**
8816     * Swaps a series of elements in the given array.
8817     *
8818     * <p>This method does nothing for a {@code null} or empty input array or
8819     * for overflow indices. Negative indices are promoted to 0(zero). If any
8820     * of the sub-arrays to swap falls outside of the given array, then the
8821     * swap is stopped at the end of the array and as many as possible elements
8822     * are swapped.</p>
8823     *
8824     * Examples:
8825     * <ul>
8826     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 0, 2, 1) -&gt; ["3", "2", "1", "4"]</li>
8827     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 0, 0, 1) -&gt; ["1", "2", "3", "4"]</li>
8828     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 2, 0, 2) -&gt; ["3", "4", "1", "2"]</li>
8829     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], -3, 2, 2) -&gt; ["3", "4", "1", "2"]</li>
8830     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 0, 3, 3) -&gt; ["4", "2", "3", "1"]</li>
8831     * </ul>
8832     *
8833     * @param array the array to swap, may be {@code null}.
8834     * @param offset1 the index of the first element in the series to swap.
8835     * @param offset2 the index of the second element in the series to swap.
8836     * @param len the number of elements to swap starting with the given indices.
8837     * @since 3.5
8838     */
8839    public static void swap(final Object[] array,  int offset1, int offset2, int len) {
8840        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8841            return;
8842        }
8843        offset1 = max0(offset1);
8844        offset2 = max0(offset2);
8845        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8846        for (int i = 0; i < len; i++, offset1++, offset2++) {
8847            final Object aux = array[offset1];
8848            array[offset1] = array[offset2];
8849            array[offset2] = aux;
8850        }
8851    }
8852
8853    /**
8854     * Swaps two elements in the given short array.
8855     *
8856     * <p>There is no special handling for multi-dimensional arrays. This method
8857     * does nothing for a {@code null} or empty input array or for overflow indices.
8858     * Negative indices are promoted to 0(zero).</p>
8859     *
8860     * Examples:
8861     * <ul>
8862     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8863     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8864     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8865     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8866     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8867     * </ul>
8868     *
8869     * @param array  the array to swap, may be {@code null}.
8870     * @param offset1 the index of the first element to swap.
8871     * @param offset2 the index of the second element to swap.
8872     * @since 3.5
8873     */
8874    public static void swap(final short[] array, final int offset1, final int offset2) {
8875        swap(array, offset1, offset2, 1);
8876    }
8877
8878    /**
8879     * Swaps a series of elements in the given short array.
8880     *
8881     * <p>This method does nothing for a {@code null} or empty input array or
8882     * for overflow indices. Negative indices are promoted to 0(zero). If any
8883     * of the sub-arrays to swap falls outside of the given array, then the
8884     * swap is stopped at the end of the array and as many as possible elements
8885     * are swapped.</p>
8886     *
8887     * Examples:
8888     * <ul>
8889     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8890     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8891     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8892     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8893     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8894     * </ul>
8895     *
8896     * @param array the array to swap, may be {@code null}.
8897     * @param offset1 the index of the first element in the series to swap.
8898     * @param offset2 the index of the second element in the series to swap.
8899     * @param len the number of elements to swap starting with the given indices.
8900     * @since 3.5
8901     */
8902    public static void swap(final short[] array, int offset1, int offset2, int len) {
8903        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8904            return;
8905        }
8906        offset1 = max0(offset1);
8907        offset2 = max0(offset2);
8908        if (offset1 == offset2) {
8909            return;
8910        }
8911        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8912        for (int i = 0; i < len; i++, offset1++, offset2++) {
8913            final short aux = array[offset1];
8914            array[offset1] = array[offset2];
8915            array[offset2] = aux;
8916        }
8917    }
8918
8919    /**
8920     * Create a type-safe generic array.
8921     * <p>
8922     * The Java language does not allow an array to be created from a generic type:
8923     * </p>
8924     * <pre>
8925    public static &lt;T&gt; T[] createAnArray(int size) {
8926        return new T[size]; // compiler error here
8927    }
8928    public static &lt;T&gt; T[] createAnArray(int size) {
8929        return (T[]) new Object[size]; // ClassCastException at runtime
8930    }
8931     * </pre>
8932     * <p>
8933     * Therefore new arrays of generic types can be created with this method.
8934     * For example, an array of Strings can be created:
8935     * </p>
8936     * <pre>{@code
8937     * String[] array = ArrayUtils.toArray("1", "2");
8938     * String[] emptyArray = ArrayUtils.<String>toArray();
8939     * }</pre>
8940     * <p>
8941     * The method is typically used in scenarios, where the caller itself uses generic types
8942     * that have to be combined into an array.
8943     * </p>
8944     * <p>
8945     * Note, this method makes only sense to provide arguments of the same type so that the
8946     * compiler can deduce the type of the array itself. While it is possible to select the
8947     * type explicitly like in
8948     * {@code Number[] array = ArrayUtils.<Number>toArray(Integer.valueOf(42), Double.valueOf(Math.PI))},
8949     * there is no real advantage when compared to
8950     * {@code new Number[] {Integer.valueOf(42), Double.valueOf(Math.PI)}}.
8951     * </p>
8952     *
8953     * @param  <T>   the array's element type.
8954     * @param  items  the varargs array items, null allowed.
8955     * @return the array, not null unless a null array is passed in.
8956     * @since 3.0
8957     */
8958    public static <T> T[] toArray(@SuppressWarnings("unchecked") final T... items) {
8959        return items;
8960    }
8961
8962    /**
8963     * 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
8964     * least two elements, where the first element is used as key and the second as value.
8965     * <p>
8966     * This method can be used to initialize:
8967     * </p>
8968     *
8969     * <pre>
8970     *
8971     * // Create a Map mapping colors.
8972     * Map colorMap = ArrayUtils.toMap(new String[][] { { "RED", "#FF0000" }, { "GREEN", "#00FF00" }, { "BLUE", "#0000FF" } });
8973     * </pre>
8974     * <p>
8975     * This method returns {@code null} for a {@code null} input array.
8976     * </p>
8977     *
8978     * @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}.
8979     * @return a {@link Map} that was created from the array.
8980     * @throws IllegalArgumentException if one element of this Array is itself an Array containing less than two elements.
8981     * @throws IllegalArgumentException if the array contains elements other than {@link java.util.Map.Entry} and an Array.
8982     */
8983    public static Map<Object, Object> toMap(final Object[] array) {
8984        if (array == null) {
8985            return null;
8986        }
8987        final Map<Object, Object> map = new HashMap<>((int) (array.length * 1.5));
8988        for (int i = 0; i < array.length; i++) {
8989            final Object object = array[i];
8990            if (object instanceof Map.Entry<?, ?>) {
8991                final Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
8992                map.put(entry.getKey(), entry.getValue());
8993            } else if (object instanceof Object[]) {
8994                final Object[] entry = (Object[]) object;
8995                if (entry.length < 2) {
8996                    throw new IllegalArgumentException("Array element " + i + ", '"
8997                        + object
8998                        + "', has a length less than 2");
8999                }
9000                map.put(entry[0], entry[1]);
9001            } else {
9002                throw new IllegalArgumentException("Array element " + i + ", '"
9003                        + object
9004                        + "', is neither of type Map.Entry nor an Array");
9005            }
9006        }
9007        return map;
9008    }
9009
9010    /**
9011     * Converts an array of primitive booleans to objects.
9012     *
9013     * <p>This method returns {@code null} for a {@code null} input array.</p>
9014     *
9015     * @param array  a {@code boolean} array.
9016     * @return a {@link Boolean} array, {@code null} if null array input.
9017     */
9018    public static Boolean[] toObject(final boolean[] array) {
9019        if (array == null) {
9020            return null;
9021        }
9022        if (array.length == 0) {
9023            return EMPTY_BOOLEAN_OBJECT_ARRAY;
9024        }
9025        return setAll(new Boolean[array.length], i -> array[i] ? Boolean.TRUE : Boolean.FALSE);
9026    }
9027
9028    /**
9029     * Converts an array of primitive bytes to objects.
9030     *
9031     * <p>This method returns {@code null} for a {@code null} input array.</p>
9032     *
9033     * @param array  a {@code byte} array.
9034     * @return a {@link Byte} array, {@code null} if null array input.
9035     */
9036    public static Byte[] toObject(final byte[] array) {
9037        if (array == null) {
9038            return null;
9039        }
9040        if (array.length == 0) {
9041            return EMPTY_BYTE_OBJECT_ARRAY;
9042        }
9043        return setAll(new Byte[array.length], i -> Byte.valueOf(array[i]));
9044    }
9045
9046    /**
9047     * Converts an array of primitive chars to objects.
9048     *
9049     * <p>This method returns {@code null} for a {@code null} input array.</p>
9050     *
9051     * @param array a {@code char} array.
9052     * @return a {@link Character} array, {@code null} if null array input.
9053     */
9054    public static Character[] toObject(final char[] array) {
9055        if (array == null) {
9056            return null;
9057        }
9058        if (array.length == 0) {
9059            return EMPTY_CHARACTER_OBJECT_ARRAY;
9060        }
9061        return setAll(new Character[array.length], i -> Character.valueOf(array[i]));
9062     }
9063
9064    /**
9065     * Converts an array of primitive doubles to objects.
9066     *
9067     * <p>This method returns {@code null} for a {@code null} input array.</p>
9068     *
9069     * @param array  a {@code double} array.
9070     * @return a {@link Double} array, {@code null} if null array input.
9071     */
9072    public static Double[] toObject(final double[] array) {
9073        if (array == null) {
9074            return null;
9075        }
9076        if (array.length == 0) {
9077            return EMPTY_DOUBLE_OBJECT_ARRAY;
9078        }
9079        return setAll(new Double[array.length], i -> Double.valueOf(array[i]));
9080    }
9081
9082    /**
9083     * Converts an array of primitive floats to objects.
9084     *
9085     * <p>This method returns {@code null} for a {@code null} input array.</p>
9086     *
9087     * @param array  a {@code float} array.
9088     * @return a {@link Float} array, {@code null} if null array input.
9089     */
9090    public static Float[] toObject(final float[] array) {
9091        if (array == null) {
9092            return null;
9093        }
9094        if (array.length == 0) {
9095            return EMPTY_FLOAT_OBJECT_ARRAY;
9096        }
9097        return setAll(new Float[array.length], i -> Float.valueOf(array[i]));
9098    }
9099
9100    /**
9101     * Converts an array of primitive ints to objects.
9102     *
9103     * <p>This method returns {@code null} for a {@code null} input array.</p>
9104     *
9105     * @param array  an {@code int} array.
9106     * @return an {@link Integer} array, {@code null} if null array input.
9107     */
9108    public static Integer[] toObject(final int[] array) {
9109        if (array == null) {
9110            return null;
9111        }
9112        if (array.length == 0) {
9113            return EMPTY_INTEGER_OBJECT_ARRAY;
9114        }
9115        return setAll(new Integer[array.length], i -> Integer.valueOf(array[i]));
9116    }
9117
9118    /**
9119     * Converts an array of primitive longs to objects.
9120     *
9121     * <p>This method returns {@code null} for a {@code null} input array.</p>
9122     *
9123     * @param array  a {@code long} array.
9124     * @return a {@link Long} array, {@code null} if null array input.
9125     */
9126    public static Long[] toObject(final long[] array) {
9127        if (array == null) {
9128            return null;
9129        }
9130        if (array.length == 0) {
9131            return EMPTY_LONG_OBJECT_ARRAY;
9132        }
9133        return setAll(new Long[array.length], i -> Long.valueOf(array[i]));
9134    }
9135
9136    /**
9137     * Converts an array of primitive shorts to objects.
9138     *
9139     * <p>This method returns {@code null} for a {@code null} input array.</p>
9140     *
9141     * @param array  a {@code short} array.
9142     * @return a {@link Short} array, {@code null} if null array input.
9143     */
9144    public static Short[] toObject(final short[] array) {
9145        if (array == null) {
9146            return null;
9147        }
9148        if (array.length == 0) {
9149            return EMPTY_SHORT_OBJECT_ARRAY;
9150        }
9151        return setAll(new Short[array.length], i -> Short.valueOf(array[i]));
9152    }
9153
9154    /**
9155     * Converts an array of object Booleans to primitives.
9156     * <p>
9157     * This method returns {@code null} for a {@code null} input array.
9158     * </p>
9159     * <p>
9160     * Null array elements map to false, like {@code Boolean.parseBoolean(null)} and its callers return false.
9161     * </p>
9162     *
9163     * @param array a {@link Boolean} array, may be {@code null}.
9164     * @return a {@code boolean} array, {@code null} if null array input.
9165     */
9166    public static boolean[] toPrimitive(final Boolean[] array) {
9167        return toPrimitive(array, false);
9168    }
9169
9170    /**
9171     * Converts an array of object Booleans to primitives handling {@code null}.
9172     * <p>
9173     * This method returns {@code null} for a {@code null} input array.
9174     * </p>
9175     *
9176     * @param array  a {@link Boolean} array, may be {@code null}.
9177     * @param valueForNull  the value to insert if {@code null} found.
9178     * @return a {@code boolean} array, {@code null} if null array input.
9179     */
9180    public static boolean[] toPrimitive(final Boolean[] array, final boolean valueForNull) {
9181        if (array == null) {
9182            return null;
9183        }
9184        if (array.length == 0) {
9185            return EMPTY_BOOLEAN_ARRAY;
9186        }
9187        final boolean[] result = new boolean[array.length];
9188        for (int i = 0; i < array.length; i++) {
9189            final Boolean b = array[i];
9190            result[i] = b == null ? valueForNull : b.booleanValue();
9191        }
9192        return result;
9193    }
9194
9195    /**
9196     * Converts an array of object Bytes to primitives.
9197     * <p>
9198     * This method returns {@code null} for a {@code null} input array.
9199     * </p>
9200     *
9201     * @param array  a {@link Byte} array, may be {@code null}.
9202     * @return a {@code byte} array, {@code null} if null array input.
9203     * @throws NullPointerException if an array element is {@code null}.
9204     */
9205    public static byte[] toPrimitive(final Byte[] array) {
9206        if (array == null) {
9207            return null;
9208        }
9209        if (array.length == 0) {
9210            return EMPTY_BYTE_ARRAY;
9211        }
9212        final byte[] result = new byte[array.length];
9213        for (int i = 0; i < array.length; i++) {
9214            result[i] = array[i].byteValue();
9215        }
9216        return result;
9217    }
9218
9219    /**
9220     * Converts an array of object Bytes to primitives handling {@code null}.
9221     * <p>
9222     * This method returns {@code null} for a {@code null} input array.
9223     * </p>
9224     *
9225     * @param array  a {@link Byte} array, may be {@code null}.
9226     * @param valueForNull  the value to insert if {@code null} found.
9227     * @return a {@code byte} array, {@code null} if null array input.
9228     */
9229    public static byte[] toPrimitive(final Byte[] array, final byte valueForNull) {
9230        if (array == null) {
9231            return null;
9232        }
9233        if (array.length == 0) {
9234            return EMPTY_BYTE_ARRAY;
9235        }
9236        final byte[] result = new byte[array.length];
9237        for (int i = 0; i < array.length; i++) {
9238            final Byte b = array[i];
9239            result[i] = b == null ? valueForNull : b.byteValue();
9240        }
9241        return result;
9242    }
9243
9244    /**
9245     * Converts an array of object Characters to primitives.
9246     * <p>
9247     * This method returns {@code null} for a {@code null} input array.
9248     * </p>
9249     *
9250     * @param array  a {@link Character} array, may be {@code null}.
9251     * @return a {@code char} array, {@code null} if null array input.
9252     * @throws NullPointerException if an array element is {@code null}.
9253     */
9254    public static char[] toPrimitive(final Character[] array) {
9255        if (array == null) {
9256            return null;
9257        }
9258        if (array.length == 0) {
9259            return EMPTY_CHAR_ARRAY;
9260        }
9261        final char[] result = new char[array.length];
9262        for (int i = 0; i < array.length; i++) {
9263            result[i] = array[i].charValue();
9264        }
9265        return result;
9266    }
9267
9268    /**
9269     * Converts an array of object Character to primitives handling {@code null}.
9270     * <p>
9271     * This method returns {@code null} for a {@code null} input array.
9272     * </p>
9273     *
9274     * @param array  a {@link Character} array, may be {@code null}.
9275     * @param valueForNull  the value to insert if {@code null} found.
9276     * @return a {@code char} array, {@code null} if null array input.
9277     */
9278    public static char[] toPrimitive(final Character[] array, final char valueForNull) {
9279        if (array == null) {
9280            return null;
9281        }
9282        if (array.length == 0) {
9283            return EMPTY_CHAR_ARRAY;
9284        }
9285        final char[] result = new char[array.length];
9286        for (int i = 0; i < array.length; i++) {
9287            final Character b = array[i];
9288            result[i] = b == null ? valueForNull : b.charValue();
9289        }
9290        return result;
9291    }
9292
9293    /**
9294     * Converts an array of object Doubles to primitives.
9295     * <p>
9296     * This method returns {@code null} for a {@code null} input array.
9297     * </p>
9298     *
9299     * @param array  a {@link Double} array, may be {@code null}.
9300     * @return a {@code double} array, {@code null} if null array input.
9301     * @throws NullPointerException if an array element is {@code null}.
9302     */
9303    public static double[] toPrimitive(final Double[] array) {
9304        if (array == null) {
9305            return null;
9306        }
9307        if (array.length == 0) {
9308            return EMPTY_DOUBLE_ARRAY;
9309        }
9310        final double[] result = new double[array.length];
9311        for (int i = 0; i < array.length; i++) {
9312            result[i] = array[i].doubleValue();
9313        }
9314        return result;
9315    }
9316
9317    /**
9318     * Converts an array of object Doubles to primitives handling {@code null}.
9319     * <p>
9320     * This method returns {@code null} for a {@code null} input array.
9321     * </p>
9322     *
9323     * @param array  a {@link Double} array, may be {@code null}.
9324     * @param valueForNull  the value to insert if {@code null} found.
9325     * @return a {@code double} array, {@code null} if null array input.
9326     */
9327    public static double[] toPrimitive(final Double[] array, final double valueForNull) {
9328        if (array == null) {
9329            return null;
9330        }
9331        if (array.length == 0) {
9332            return EMPTY_DOUBLE_ARRAY;
9333        }
9334        final double[] result = new double[array.length];
9335        for (int i = 0; i < array.length; i++) {
9336            final Double b = array[i];
9337            result[i] = b == null ? valueForNull : b.doubleValue();
9338        }
9339        return result;
9340    }
9341
9342    /**
9343     * Converts an array of object Floats to primitives.
9344     * <p>
9345     * This method returns {@code null} for a {@code null} input array.
9346     * </p>
9347     *
9348     * @param array  a {@link Float} array, may be {@code null}.
9349     * @return a {@code float} array, {@code null} if null array input.
9350     * @throws NullPointerException if an array element is {@code null}.
9351     */
9352    public static float[] toPrimitive(final Float[] array) {
9353        if (array == null) {
9354            return null;
9355        }
9356        if (array.length == 0) {
9357            return EMPTY_FLOAT_ARRAY;
9358        }
9359        final float[] result = new float[array.length];
9360        for (int i = 0; i < array.length; i++) {
9361            result[i] = array[i].floatValue();
9362        }
9363        return result;
9364    }
9365
9366    /**
9367     * Converts an array of object Floats to primitives handling {@code null}.
9368     * <p>
9369     * This method returns {@code null} for a {@code null} input array.
9370     * </p>
9371     *
9372     * @param array  a {@link Float} array, may be {@code null}.
9373     * @param valueForNull  the value to insert if {@code null} found.
9374     * @return a {@code float} array, {@code null} if null array input.
9375     */
9376    public static float[] toPrimitive(final Float[] array, final float valueForNull) {
9377        if (array == null) {
9378            return null;
9379        }
9380        if (array.length == 0) {
9381            return EMPTY_FLOAT_ARRAY;
9382        }
9383        final float[] result = new float[array.length];
9384        for (int i = 0; i < array.length; i++) {
9385            final Float b = array[i];
9386            result[i] = b == null ? valueForNull : b.floatValue();
9387        }
9388        return result;
9389    }
9390
9391    /**
9392     * Converts an array of object Integers to primitives.
9393     * <p>
9394     * This method returns {@code null} for a {@code null} input array.
9395     * </p>
9396     *
9397     * @param array  a {@link Integer} array, may be {@code null}.
9398     * @return an {@code int} array, {@code null} if null array input.
9399     * @throws NullPointerException if an array element is {@code null}.
9400     */
9401    public static int[] toPrimitive(final Integer[] array) {
9402        if (array == null) {
9403            return null;
9404        }
9405        if (array.length == 0) {
9406            return EMPTY_INT_ARRAY;
9407        }
9408        final int[] result = new int[array.length];
9409        for (int i = 0; i < array.length; i++) {
9410            result[i] = array[i].intValue();
9411        }
9412        return result;
9413    }
9414
9415    /**
9416     * Converts an array of object Integer to primitives handling {@code null}.
9417     * <p>
9418     * This method returns {@code null} for a {@code null} input array.
9419     * </p>
9420     *
9421     * @param array  a {@link Integer} array, may be {@code null}.
9422     * @param valueForNull  the value to insert if {@code null} found.
9423     * @return an {@code int} array, {@code null} if null array input.
9424     */
9425    public static int[] toPrimitive(final Integer[] array, final int valueForNull) {
9426        if (array == null) {
9427            return null;
9428        }
9429        if (array.length == 0) {
9430            return EMPTY_INT_ARRAY;
9431        }
9432        final int[] result = new int[array.length];
9433        for (int i = 0; i < array.length; i++) {
9434            final Integer b = array[i];
9435            result[i] = b == null ? valueForNull : b.intValue();
9436        }
9437        return result;
9438    }
9439
9440    /**
9441     * Converts an array of object Longs to primitives.
9442     * <p>
9443     * This method returns {@code null} for a {@code null} input array.
9444     * </p>
9445     *
9446     * @param array  a {@link Long} array, may be {@code null}.
9447     * @return a {@code long} array, {@code null} if null array input.
9448     * @throws NullPointerException if an array element is {@code null}.
9449     */
9450    public static long[] toPrimitive(final Long[] array) {
9451        if (array == null) {
9452            return null;
9453        }
9454        if (array.length == 0) {
9455            return EMPTY_LONG_ARRAY;
9456        }
9457        final long[] result = new long[array.length];
9458        for (int i = 0; i < array.length; i++) {
9459            result[i] = array[i].longValue();
9460        }
9461        return result;
9462    }
9463
9464    /**
9465     * Converts an array of object Long to primitives handling {@code null}.
9466     * <p>
9467     * This method returns {@code null} for a {@code null} input array.
9468     * </p>
9469     *
9470     * @param array  a {@link Long} array, may be {@code null}.
9471     * @param valueForNull  the value to insert if {@code null} found.
9472     * @return a {@code long} array, {@code null} if null array input.
9473     */
9474    public static long[] toPrimitive(final Long[] array, final long valueForNull) {
9475        if (array == null) {
9476            return null;
9477        }
9478        if (array.length == 0) {
9479            return EMPTY_LONG_ARRAY;
9480        }
9481        final long[] result = new long[array.length];
9482        for (int i = 0; i < array.length; i++) {
9483            final Long b = array[i];
9484            result[i] = b == null ? valueForNull : b.longValue();
9485        }
9486        return result;
9487    }
9488
9489    /**
9490     * Create an array of primitive type from an array of wrapper types.
9491     * <p>
9492     * This method returns {@code null} for a {@code null} input array.
9493     * </p>
9494     *
9495     * @param array  an array of wrapper object.
9496     * @return an array of the corresponding primitive type, or the original array.
9497     * @since 3.5
9498     */
9499    public static Object toPrimitive(final Object array) {
9500        if (array == null) {
9501            return null;
9502        }
9503        final Class<?> ct = array.getClass().getComponentType();
9504        final Class<?> pt = ClassUtils.wrapperToPrimitive(ct);
9505        if (Boolean.TYPE.equals(pt)) {
9506            return toPrimitive((Boolean[]) array);
9507        }
9508        if (Character.TYPE.equals(pt)) {
9509            return toPrimitive((Character[]) array);
9510        }
9511        if (Byte.TYPE.equals(pt)) {
9512            return toPrimitive((Byte[]) array);
9513        }
9514        if (Integer.TYPE.equals(pt)) {
9515            return toPrimitive((Integer[]) array);
9516        }
9517        if (Long.TYPE.equals(pt)) {
9518            return toPrimitive((Long[]) array);
9519        }
9520        if (Short.TYPE.equals(pt)) {
9521            return toPrimitive((Short[]) array);
9522        }
9523        if (Double.TYPE.equals(pt)) {
9524            return toPrimitive((Double[]) array);
9525        }
9526        if (Float.TYPE.equals(pt)) {
9527            return toPrimitive((Float[]) array);
9528        }
9529        return array;
9530    }
9531
9532    /**
9533     * Converts an array of object Shorts to primitives.
9534     * <p>
9535     * This method returns {@code null} for a {@code null} input array.
9536     * </p>
9537     *
9538     * @param array  a {@link Short} array, may be {@code null}.
9539     * @return a {@code byte} array, {@code null} if null array input.
9540     * @throws NullPointerException if an array element is {@code null}.
9541     */
9542    public static short[] toPrimitive(final Short[] array) {
9543        if (array == null) {
9544            return null;
9545        }
9546        if (array.length == 0) {
9547            return EMPTY_SHORT_ARRAY;
9548        }
9549        final short[] result = new short[array.length];
9550        for (int i = 0; i < array.length; i++) {
9551            result[i] = array[i].shortValue();
9552        }
9553        return result;
9554    }
9555
9556    /**
9557     * Converts an array of object Short to primitives handling {@code null}.
9558     * <p>
9559     * This method returns {@code null} for a {@code null} input array.
9560     * </p>
9561     *
9562     * @param array  a {@link Short} array, may be {@code null}.
9563     * @param valueForNull  the value to insert if {@code null} found.
9564     * @return a {@code byte} array, {@code null} if null array input.
9565     */
9566    public static short[] toPrimitive(final Short[] array, final short valueForNull) {
9567        if (array == null) {
9568            return null;
9569        }
9570        if (array.length == 0) {
9571            return EMPTY_SHORT_ARRAY;
9572        }
9573        final short[] result = new short[array.length];
9574        for (int i = 0; i < array.length; i++) {
9575            final Short b = array[i];
9576            result[i] = b == null ? valueForNull : b.shortValue();
9577        }
9578        return result;
9579    }
9580
9581    /**
9582     * Outputs an array as a String, treating {@code null} as an empty array.
9583     * <p>
9584     * Multi-dimensional arrays are handled correctly, including
9585     * multi-dimensional primitive arrays.
9586     * </p>
9587     * <p>
9588     * The format is that of Java source code, for example {@code {a,b}}.
9589     * </p>
9590     *
9591     * @param array  the array to get a toString for, may be {@code null}.
9592     * @return a String representation of the array, '{}' if null array input.
9593     */
9594    public static String toString(final Object array) {
9595        return toString(array, "{}");
9596    }
9597
9598    /**
9599     * Outputs an array as a String handling {@code null}s.
9600     * <p>
9601     * Multi-dimensional arrays are handled correctly, including
9602     * multi-dimensional primitive arrays.
9603     * </p>
9604     * <p>
9605     * The format is that of Java source code, for example {@code {a,b}}.
9606     * </p>
9607     *
9608     * @param array  the array to get a toString for, may be {@code null}.
9609     * @param stringIfNull  the String to return if the array is {@code null}.
9610     * @return a String representation of the array.
9611     */
9612    public static String toString(final Object array, final String stringIfNull) {
9613        return array != null ? new ToStringBuilder(array, ToStringStyle.SIMPLE_STYLE).append(array).toString() : stringIfNull;
9614    }
9615
9616    /**
9617     * Returns an array containing the string representation of each element in the argument array.
9618     * <p>
9619     * This method returns {@code null} for a {@code null} input array.
9620     * </p>
9621     *
9622     * @param array the {@code Object[]} to be processed, may be {@code null}.
9623     * @return {@code String[]} of the same size as the source with its element's string representation, {@code null} if null array input.
9624     * @since 3.6
9625     */
9626    public static String[] toStringArray(final Object[] array) {
9627        return toStringArray(array, "null");
9628    }
9629
9630    /**
9631     * Returns an array containing the string representation of each element in the argument array handling {@code null} elements.
9632     * <p>
9633     * This method returns {@code null} for a {@code null} input array.
9634     * </p>
9635     *
9636     * @param array                the Object[] to be processed, may be {@code null}.
9637     * @param valueForNullElements the value to insert if {@code null} is found.
9638     * @return a {@link String} array, {@code null} if null array input.
9639     * @since 3.6
9640     */
9641    public static String[] toStringArray(final Object[] array, final String valueForNullElements) {
9642        if (null == array) {
9643            return null;
9644        }
9645        if (array.length == 0) {
9646            return EMPTY_STRING_ARRAY;
9647        }
9648        return map(array, String.class, e -> Objects.toString(e, valueForNullElements));
9649    }
9650
9651    /**
9652     * ArrayUtils instances should NOT be constructed in standard programming. Instead, the class should be used as {@code ArrayUtils.clone(new int[] {2})}.
9653     * <p>
9654     * This constructor is public to permit tools that require a JavaBean instance to operate.
9655     * </p>
9656     *
9657     * @deprecated TODO Make private in 4.0.
9658     */
9659    @Deprecated
9660    public ArrayUtils() {
9661        // empty
9662    }
9663}