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