001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.lang3;
018
019import java.lang.reflect.Array;
020import java.lang.reflect.Field;
021import java.lang.reflect.Method;
022import java.lang.reflect.Type;
023import java.security.SecureRandom;
024import java.util.Arrays;
025import java.util.BitSet;
026import java.util.Comparator;
027import java.util.Date;
028import java.util.HashMap;
029import java.util.Map;
030import java.util.Objects;
031import java.util.Random;
032import java.util.concurrent.ThreadLocalRandom;
033import java.util.function.Function;
034import java.util.function.IntFunction;
035import java.util.function.Supplier;
036
037import org.apache.commons.lang3.builder.EqualsBuilder;
038import org.apache.commons.lang3.builder.HashCodeBuilder;
039import org.apache.commons.lang3.builder.ToStringBuilder;
040import org.apache.commons.lang3.builder.ToStringStyle;
041import org.apache.commons.lang3.function.FailableFunction;
042import org.apache.commons.lang3.mutable.MutableInt;
043import org.apache.commons.lang3.stream.IntStreams;
044import org.apache.commons.lang3.stream.Streams;
045
046/**
047 * Operations on arrays, primitive arrays (like {@code int[]}) and
048 * primitive wrapper arrays (like {@code Integer[]}).
049 * <p>
050 * This class tries to handle {@code null} input gracefully.
051 * An exception will not be thrown for a {@code null}
052 * array input. However, an Object array that contains a {@code null}
053 * element may throw an exception. Each method documents its behavior.
054 * </p>
055 * <p>
056 * #ThreadSafe#
057 * </p>
058 * @since 2.0
059 */
060public class ArrayUtils {
061
062    /**
063     * An empty immutable {@code boolean} array.
064     */
065    public static final boolean[] EMPTY_BOOLEAN_ARRAY = {};
066
067    /**
068     * An empty immutable {@link Boolean} array.
069     */
070    public static final Boolean[] EMPTY_BOOLEAN_OBJECT_ARRAY = {};
071
072    /**
073     * An empty immutable {@code byte} array.
074     */
075    public static final byte[] EMPTY_BYTE_ARRAY = {};
076
077    /**
078     * An empty immutable {@link Byte} array.
079     */
080    public static final Byte[] EMPTY_BYTE_OBJECT_ARRAY = {};
081
082    /**
083     * An empty immutable {@code char} array.
084     */
085    public static final char[] EMPTY_CHAR_ARRAY = {};
086
087    /**
088     * An empty immutable {@link Character} array.
089     */
090    public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = {};
091
092    /**
093     * An empty immutable {@link Class} array.
094     */
095    public static final Class<?>[] EMPTY_CLASS_ARRAY = {};
096
097    /**
098     * An empty immutable {@code double} array.
099     */
100    public static final double[] EMPTY_DOUBLE_ARRAY = {};
101
102    /**
103     * An empty immutable {@link Double} array.
104     */
105    public static final Double[] EMPTY_DOUBLE_OBJECT_ARRAY = {};
106
107    /**
108     * An empty immutable {@link Field} array.
109     *
110     * @since 3.10
111     */
112    public static final Field[] EMPTY_FIELD_ARRAY = {};
113
114    /**
115     * An empty immutable {@code float} array.
116     */
117    public static final float[] EMPTY_FLOAT_ARRAY = {};
118
119    /**
120     * An empty immutable {@link Float} array.
121     */
122    public static final Float[] EMPTY_FLOAT_OBJECT_ARRAY = {};
123
124    /**
125     * An empty immutable {@code int} array.
126     */
127    public static final int[] EMPTY_INT_ARRAY = {};
128
129    /**
130     * An empty immutable {@link Integer} array.
131     */
132    public static final Integer[] EMPTY_INTEGER_OBJECT_ARRAY = {};
133
134    /**
135     * An empty immutable {@code long} array.
136     */
137    public static final long[] EMPTY_LONG_ARRAY = {};
138
139    /**
140     * An empty immutable {@link Long} array.
141     */
142    public static final Long[] EMPTY_LONG_OBJECT_ARRAY = {};
143
144    /**
145     * An empty immutable {@link Method} array.
146     *
147     * @since 3.10
148     */
149    public static final Method[] EMPTY_METHOD_ARRAY = {};
150
151    /**
152     * An empty immutable {@link Object} array.
153     */
154    public static final Object[] EMPTY_OBJECT_ARRAY = {};
155
156    /**
157     * An empty immutable {@code short} array.
158     */
159    public static final short[] EMPTY_SHORT_ARRAY = {};
160
161    /**
162     * An empty immutable {@link Short} array.
163     */
164    public static final Short[] EMPTY_SHORT_OBJECT_ARRAY = {};
165
166    /**
167     * An empty immutable {@link String} array.
168     */
169    public static final String[] EMPTY_STRING_ARRAY = {};
170
171    /**
172     * An empty immutable {@link Throwable} array.
173     *
174     * @since 3.10
175     */
176    public static final Throwable[] EMPTY_THROWABLE_ARRAY = {};
177
178    /**
179     * An empty immutable {@link Type} array.
180     *
181     * @since 3.10
182     */
183    public static final Type[] EMPTY_TYPE_ARRAY = {};
184
185    /**
186     * The index value when an element is not found in a list or array: {@code -1}.
187     * This value is returned by methods in this class and can also be used in comparisons with values returned by
188     * various method from {@link java.util.List}.
189     */
190    public static final int INDEX_NOT_FOUND = -1;
191
192    /**
193     * The {@code SOFT_MAX_ARRAY_LENGTH} constant from Java's internal ArraySupport class.
194     *
195     * @since 3.19.0
196     */
197    public static int SOFT_MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;
198
199    /**
200     * Copies the given array and adds the given element at the end of the new array.
201     * <p>
202     * The new array contains the same elements of the input
203     * array plus the given element in the last position. The component type of
204     * the new array is the same as that of the input array.
205     * </p>
206     * <p>
207     * If the input array is {@code null}, a new one element array is returned
208     * whose component type is the same as the element.
209     * </p>
210     * <pre>
211     * ArrayUtils.add(null, true)          = [true]
212     * ArrayUtils.add([true], false)       = [true, false]
213     * ArrayUtils.add([true, false], true) = [true, false, true]
214     * </pre>
215     *
216     * @param array  the array to copy and add the element to, may be {@code null}
217     * @param element  the object to add at the last index of the new array
218     * @return A new array containing the existing elements plus the new element
219     * @since 2.1
220     */
221    public static boolean[] add(final boolean[] array, final boolean element) {
222        final boolean[] newArray = (boolean[]) copyArrayGrow1(array, Boolean.TYPE);
223        newArray[newArray.length - 1] = element;
224        return newArray;
225    }
226
227    /**
228     * Inserts the specified element at the specified position in the array.
229     * Shifts the element currently at that position (if any) and any subsequent
230     * elements to the right (adds one to their indices).
231     * <p>
232     * This method returns a new array with the same elements of the input
233     * array plus the given element on the specified position. The component
234     * type of the returned array is always the same as that of the input
235     * array.
236     * </p>
237     * <p>
238     * If the input array is {@code null}, a new one element array is returned
239     * whose component type is the same as the element.
240     * </p>
241     * <pre>
242     * ArrayUtils.add(null, 0, true)          = [true]
243     * ArrayUtils.add([true], 0, false)       = [false, true]
244     * ArrayUtils.add([false], 1, true)       = [false, true]
245     * ArrayUtils.add([true, false], 1, true) = [true, true, false]
246     * </pre>
247     *
248     * @param array  the array to add the element to, may be {@code null}
249     * @param index  the position of the new object
250     * @param element  the object to add
251     * @return A new array containing the existing elements and the new element
252     * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt; array.length).
253     * @deprecated this method has been superseded by {@link #insert(int, boolean[], boolean...)} and
254     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
255     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
256     */
257    @Deprecated
258    public static boolean[] add(final boolean[] array, final int index, final boolean element) {
259        return (boolean[]) add(array, index, Boolean.valueOf(element), Boolean.TYPE);
260    }
261
262    /**
263     * Copies the given array and adds the given element at the end of the new array.
264     * <p>
265     * The new array contains the same elements of the input
266     * array plus the given element in the last position. The component type of
267     * the new array is the same as that of the input array.
268     * </p>
269     * <p>
270     * If the input array is {@code null}, a new one element array is returned
271     * whose component type is the same as the element.
272     * </p>
273     * <pre>
274     * ArrayUtils.add(null, 0)   = [0]
275     * ArrayUtils.add([1], 0)    = [1, 0]
276     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
277     * </pre>
278     *
279     * @param array  the array to copy and add the element to, may be {@code null}
280     * @param element  the object to add at the last index of the new array
281     * @return A new array containing the existing elements plus the new element
282     * @since 2.1
283     */
284    public static byte[] add(final byte[] array, final byte element) {
285        final byte[] newArray = (byte[]) copyArrayGrow1(array, Byte.TYPE);
286        newArray[newArray.length - 1] = element;
287        return newArray;
288    }
289
290    /**
291     * Inserts the specified element at the specified position in the array.
292     * Shifts the element currently at that position (if any) and any subsequent
293     * elements to the right (adds one to their indices).
294     * <p>
295     * This method returns a new array with the same elements of the input
296     * array plus the given element on the specified position. The component
297     * type of the returned array is always the same as that of the input
298     * array.
299     * </p>
300     * <p>
301     * If the input array is {@code null}, a new one element array is returned
302     * whose component type is the same as the element.
303     * </p>
304     * <pre>
305     * ArrayUtils.add([1], 0, 2)         = [2, 1]
306     * ArrayUtils.add([2, 6], 2, 3)      = [2, 6, 3]
307     * ArrayUtils.add([2, 6], 0, 1)      = [1, 2, 6]
308     * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
309     * </pre>
310     *
311     * @param array  the array to add the element to, may be {@code null}
312     * @param index  the position of the new object
313     * @param element  the object to add
314     * @return A new array containing the existing elements and the new element
315     * @throws IndexOutOfBoundsException if the index is out of range
316     * (index &lt; 0 || index &gt; array.length).
317     * @deprecated this method has been superseded by {@link #insert(int, byte[], byte...)} and
318     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
319     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
320     */
321    @Deprecated
322    public static byte[] add(final byte[] array, final int index, final byte element) {
323        return (byte[]) add(array, index, Byte.valueOf(element), Byte.TYPE);
324    }
325
326    /**
327     * Copies the given array and adds the given element at the end of the new array.
328     * <p>
329     * The new array contains the same elements of the input
330     * array plus the given element in the last position. The component type of
331     * the new array is the same as that of the input array.
332     * </p>
333     * <p>
334     * If the input array is {@code null}, a new one element array is returned
335     * whose component type is the same as the element.
336     * </p>
337     * <pre>
338     * ArrayUtils.add(null, '0')       = ['0']
339     * ArrayUtils.add(['1'], '0')      = ['1', '0']
340     * ArrayUtils.add(['1', '0'], '1') = ['1', '0', '1']
341     * </pre>
342     *
343     * @param array  the array to copy and add the element to, may be {@code null}
344     * @param element  the object to add at the last index of the new array
345     * @return A new array containing the existing elements plus the new element
346     * @since 2.1
347     */
348    public static char[] add(final char[] array, final char element) {
349        final char[] newArray = (char[]) copyArrayGrow1(array, Character.TYPE);
350        newArray[newArray.length - 1] = element;
351        return newArray;
352    }
353
354    /**
355     * Inserts the specified element at the specified position in the array.
356     * Shifts the element currently at that position (if any) and any subsequent
357     * elements to the right (adds one to their indices).
358     * <p>
359     * This method returns a new array with the same elements of the input
360     * array plus the given element on the specified position. The component
361     * type of the returned array is always the same as that of the input
362     * array.
363     * </p>
364     * <p>
365     * If the input array is {@code null}, a new one element array is returned
366     * whose component type is the same as the element.
367     * </p>
368     * <pre>
369     * ArrayUtils.add(null, 0, 'a')            = ['a']
370     * ArrayUtils.add(['a'], 0, 'b')           = ['b', 'a']
371     * ArrayUtils.add(['a', 'b'], 0, 'c')      = ['c', 'a', 'b']
372     * ArrayUtils.add(['a', 'b'], 1, 'k')      = ['a', 'k', 'b']
373     * ArrayUtils.add(['a', 'b', 'c'], 1, 't') = ['a', 't', 'b', 'c']
374     * </pre>
375     *
376     * @param array  the array to add the element to, may be {@code null}
377     * @param index  the position of the new object
378     * @param element  the object to add
379     * @return A new array containing the existing elements and the new element
380     * @throws IndexOutOfBoundsException if the index is out of range
381     * (index &lt; 0 || index &gt; array.length).
382     * @deprecated this method has been superseded by {@link #insert(int, char[], char...)} and
383     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
384     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
385     */
386    @Deprecated
387    public static char[] add(final char[] array, final int index, final char element) {
388        return (char[]) add(array, index, Character.valueOf(element), Character.TYPE);
389    }
390
391    /**
392     * Copies the given array and adds the given element at the end of the new array.
393     *
394     * <p>
395     * The new array contains the same elements of the input
396     * array plus the given element in the last position. The component type of
397     * the new array is the same as that of the input array.
398     * </p>
399     * <p>
400     * If the input array is {@code null}, a new one element array is returned
401     * whose component type is the same as the element.
402     * </p>
403     * <pre>
404     * ArrayUtils.add(null, 0)   = [0]
405     * ArrayUtils.add([1], 0)    = [1, 0]
406     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
407     * </pre>
408     *
409     * @param array  the array to copy and add the element to, may be {@code null}
410     * @param element  the object to add at the last index of the new array
411     * @return A new array containing the existing elements plus the new element
412     * @since 2.1
413     */
414    public static double[] add(final double[] array, final double element) {
415        final double[] newArray = (double[]) copyArrayGrow1(array, Double.TYPE);
416        newArray[newArray.length - 1] = element;
417        return newArray;
418    }
419
420    /**
421     * Inserts the specified element at the specified position in the array.
422     * Shifts the element currently at that position (if any) and any subsequent
423     * elements to the right (adds one to their indices).
424     * <p>
425     * This method returns a new array with the same elements of the input
426     * array plus the given element on the specified position. The component
427     * type of the returned array is always the same as that of the input
428     * array.
429     * </p>
430     * <p>
431     * If the input array is {@code null}, a new one element array is returned
432     * whose component type is the same as the element.
433     * </p>
434     * <pre>
435     * ArrayUtils.add([1.1], 0, 2.2)              = [2.2, 1.1]
436     * ArrayUtils.add([2.3, 6.4], 2, 10.5)        = [2.3, 6.4, 10.5]
437     * ArrayUtils.add([2.6, 6.7], 0, -4.8)        = [-4.8, 2.6, 6.7]
438     * ArrayUtils.add([2.9, 6.0, 0.3], 2, 1.0)    = [2.9, 6.0, 1.0, 0.3]
439     * </pre>
440     *
441     * @param array  the array to add the element to, may be {@code null}
442     * @param index  the position of the new object
443     * @param element  the object to add
444     * @return A new array containing the existing elements and the new element
445     * @throws IndexOutOfBoundsException if the index is out of range
446     * (index &lt; 0 || index &gt; array.length).
447     * @deprecated this method has been superseded by {@link #insert(int, double[], double...)} and
448     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
449     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
450     */
451    @Deprecated
452    public static double[] add(final double[] array, final int index, final double element) {
453        return (double[]) add(array, index, Double.valueOf(element), Double.TYPE);
454    }
455
456    /**
457     * Copies the given array and adds the given element at the end of the new array.
458     * <p>
459     * The new array contains the same elements of the input
460     * array plus the given element in the last position. The component type of
461     * the new array is the same as that of the input array.
462     * </p>
463     * <p>
464     * If the input array is {@code null}, a new one element array is returned
465     * whose component type is the same as the element.
466     * </p>
467     * <pre>
468     * ArrayUtils.add(null, 0)   = [0]
469     * ArrayUtils.add([1], 0)    = [1, 0]
470     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
471     * </pre>
472     *
473     * @param array  the array to copy and add the element to, may be {@code null}
474     * @param element  the object to add at the last index of the new array
475     * @return A new array containing the existing elements plus the new element
476     * @since 2.1
477     */
478    public static float[] add(final float[] array, final float element) {
479        final float[] newArray = (float[]) copyArrayGrow1(array, Float.TYPE);
480        newArray[newArray.length - 1] = element;
481        return newArray;
482    }
483
484    /**
485     * Inserts the specified element at the specified position in the array.
486     * Shifts the element currently at that position (if any) and any subsequent
487     * elements to the right (adds one to their indices).
488     * <p>
489     * This method returns a new array with the same elements of the input
490     * array plus the given element on the specified position. The component
491     * type of the returned array is always the same as that of the input
492     * array.
493     * </p>
494     * <p>
495     * If the input array is {@code null}, a new one element array is returned
496     * whose component type is the same as the element.
497     * </p>
498     * <pre>
499     * ArrayUtils.add([1.1f], 0, 2.2f)               = [2.2f, 1.1f]
500     * ArrayUtils.add([2.3f, 6.4f], 2, 10.5f)        = [2.3f, 6.4f, 10.5f]
501     * ArrayUtils.add([2.6f, 6.7f], 0, -4.8f)        = [-4.8f, 2.6f, 6.7f]
502     * ArrayUtils.add([2.9f, 6.0f, 0.3f], 2, 1.0f)   = [2.9f, 6.0f, 1.0f, 0.3f]
503     * </pre>
504     *
505     * @param array  the array to add the element to, may be {@code null}
506     * @param index  the position of the new object
507     * @param element  the object to add
508     * @return A new array containing the existing elements and the new element
509     * @throws IndexOutOfBoundsException if the index is out of range
510     * (index &lt; 0 || index &gt; array.length).
511     * @deprecated this method has been superseded by {@link #insert(int, float[], float...)} and
512     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
513     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
514     */
515    @Deprecated
516    public static float[] add(final float[] array, final int index, final float element) {
517        return (float[]) add(array, index, Float.valueOf(element), Float.TYPE);
518    }
519
520    /**
521     * Copies the given array and adds the given element at the end of the new array.
522     * <p>
523     * The new array contains the same elements of the input
524     * array plus the given element in the last position. The component type of
525     * the new array is the same as that of the input array.
526     * </p>
527     * <p>
528     * If the input array is {@code null}, a new one element array is returned
529     * whose component type is the same as the element.
530     * </p>
531     * <pre>
532     * ArrayUtils.add(null, 0)   = [0]
533     * ArrayUtils.add([1], 0)    = [1, 0]
534     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
535     * </pre>
536     *
537     * @param array  the array to copy and add the element to, may be {@code null}
538     * @param element  the object to add at the last index of the new array
539     * @return A new array containing the existing elements plus the new element
540     * @since 2.1
541     */
542    public static int[] add(final int[] array, final int element) {
543        final int[] newArray = (int[]) copyArrayGrow1(array, Integer.TYPE);
544        newArray[newArray.length - 1] = element;
545        return newArray;
546    }
547
548    /**
549     * Inserts the specified element at the specified position in the array.
550     * Shifts the element currently at that position (if any) and any subsequent
551     * elements to the right (adds one to their indices).
552     * <p>
553     * This method returns a new array with the same elements of the input
554     * array plus the given element on the specified position. The component
555     * type of the returned array is always the same as that of the input
556     * array.
557     * </p>
558     * <p>
559     * If the input array is {@code null}, a new one element array is returned
560     * whose component type is the same as the element.
561     * </p>
562     * <pre>
563     * ArrayUtils.add([1], 0, 2)         = [2, 1]
564     * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
565     * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
566     * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
567     * </pre>
568     *
569     * @param array  the array to add the element to, may be {@code null}
570     * @param index  the position of the new object
571     * @param element  the object to add
572     * @return A new array containing the existing elements and the new element
573     * @throws IndexOutOfBoundsException if the index is out of range
574     * (index &lt; 0 || index &gt; array.length).
575     * @deprecated this method has been superseded by {@link #insert(int, int[], int...)} and
576     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
577     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
578     */
579    @Deprecated
580    public static int[] add(final int[] array, final int index, final int element) {
581        return (int[]) add(array, index, Integer.valueOf(element), Integer.TYPE);
582    }
583
584    /**
585     * Inserts the specified element at the specified position in the array.
586     * Shifts the element currently at that position (if any) and any subsequent
587     * elements to the right (adds one to their indices).
588     * <p>
589     * This method returns a new array with the same elements of the input
590     * array plus the given element on the specified position. The component
591     * type of the returned array is always the same as that of the input
592     * array.
593     * </p>
594     * <p>
595     * If the input array is {@code null}, a new one element array is returned
596     * whose component type is the same as the element.
597     * </p>
598     * <pre>
599     * ArrayUtils.add([1L], 0, 2L)           = [2L, 1L]
600     * ArrayUtils.add([2L, 6L], 2, 10L)      = [2L, 6L, 10L]
601     * ArrayUtils.add([2L, 6L], 0, -4L)      = [-4L, 2L, 6L]
602     * ArrayUtils.add([2L, 6L, 3L], 2, 1L)   = [2L, 6L, 1L, 3L]
603     * </pre>
604     *
605     * @param array  the array to add the element to, may be {@code null}
606     * @param index  the position of the new object
607     * @param element  the object to add
608     * @return A new array containing the existing elements and the new element
609     * @throws IndexOutOfBoundsException if the index is out of range
610     * (index &lt; 0 || index &gt; array.length).
611     * @deprecated this method has been superseded by {@link #insert(int, long[], long...)} and
612     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
613     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
614     */
615    @Deprecated
616    public static long[] add(final long[] array, final int index, final long element) {
617        return (long[]) add(array, index, Long.valueOf(element), Long.TYPE);
618    }
619
620    /**
621     * Copies the given array and adds the given element at the end of the new array.
622     * <p>
623     * The new array contains the same elements of the input
624     * array plus the given element in the last position. The component type of
625     * the new array is the same as that of the input array.
626     * </p>
627     * <p>
628     * If the input array is {@code null}, a new one element array is returned
629     * whose component type is the same as the element.
630     * </p>
631     * <pre>
632     * ArrayUtils.add(null, 0)   = [0]
633     * ArrayUtils.add([1], 0)    = [1, 0]
634     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
635     * </pre>
636     *
637     * @param array  the array to copy and add the element to, may be {@code null}
638     * @param element  the object to add at the last index of the new array
639     * @return A new array containing the existing elements plus the new element
640     * @since 2.1
641     */
642    public static long[] add(final long[] array, final long element) {
643        final long[] newArray = (long[]) copyArrayGrow1(array, Long.TYPE);
644        newArray[newArray.length - 1] = element;
645        return newArray;
646    }
647
648    /**
649     * Underlying implementation of add(array, index, element) methods.
650     * The last parameter is the class, which may not equal element.getClass
651     * for primitives.
652     *
653     * @param array  the array to add the element to, may be {@code null}
654     * @param index  the position of the new object
655     * @param element  the object to add
656     * @param clazz the type of the element being added
657     * @return A new array containing the existing elements and the new element
658     */
659    private static Object add(final Object array, final int index, final Object element, final Class<?> clazz) {
660        if (array == null) {
661            if (index != 0) {
662                throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
663            }
664            final Object joinedArray = Array.newInstance(clazz, 1);
665            Array.set(joinedArray, 0, element);
666            return joinedArray;
667        }
668        final int length = Array.getLength(array);
669        if (index > length || index < 0) {
670            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
671        }
672        final Object result = arraycopy(array, 0, 0, index, () -> Array.newInstance(clazz, length + 1));
673        Array.set(result, index, element);
674        if (index < length) {
675            System.arraycopy(array, index, result, index + 1, length - index);
676        }
677        return result;
678    }
679
680    /**
681     * Inserts the specified element at the specified position in the array.
682     * Shifts the element currently at that position (if any) and any subsequent
683     * elements to the right (adds one to their indices).
684     * <p>
685     * This method returns a new array with the same elements of the input
686     * array plus the given element on the specified position. The component
687     * type of the returned array is always the same as that of the input
688     * array.
689     * </p>
690     * <p>
691     * If the input array is {@code null}, a new one element array is returned
692     * whose component type is the same as the element.
693     * </p>
694     * <pre>
695     * ArrayUtils.add([1], 0, 2)         = [2, 1]
696     * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
697     * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
698     * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
699     * </pre>
700     *
701     * @param array  the array to add the element to, may be {@code null}
702     * @param index  the position of the new object
703     * @param element  the object to add
704     * @return A new array containing the existing elements and the new element
705     * @throws IndexOutOfBoundsException if the index is out of range
706     * (index &lt; 0 || index &gt; array.length).
707     * @deprecated this method has been superseded by {@link #insert(int, short[], short...)} and
708     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
709     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
710     */
711    @Deprecated
712    public static short[] add(final short[] array, final int index, final short element) {
713        return (short[]) add(array, index, Short.valueOf(element), Short.TYPE);
714    }
715
716    /**
717     * Copies the given array and adds the given element at the end of the new array.
718     * <p>
719     * The new array contains the same elements of the input
720     * array plus the given element in the last position. The component type of
721     * the new array is the same as that of the input array.
722     * </p>
723     * <p>
724     * If the input array is {@code null}, a new one element array is returned
725     * whose component type is the same as the element.
726     * </p>
727     * <pre>
728     * ArrayUtils.add(null, 0)   = [0]
729     * ArrayUtils.add([1], 0)    = [1, 0]
730     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
731     * </pre>
732     *
733     * @param array  the array to copy and add the element to, may be {@code null}
734     * @param element  the object to add at the last index of the new array
735     * @return A new array containing the existing elements plus the new element
736     * @since 2.1
737     */
738    public static short[] add(final short[] array, final short element) {
739        final short[] newArray = (short[]) copyArrayGrow1(array, Short.TYPE);
740        newArray[newArray.length - 1] = element;
741        return newArray;
742    }
743
744    /**
745     * Inserts the specified element at the specified position in the array.
746     * Shifts the element currently at that position (if any) and any subsequent
747     * elements to the right (adds one to their indices).
748     * <p>
749     * This method returns a new array with the same elements of the input
750     * array plus the given element on the specified position. The component
751     * type of the returned array is always the same as that of the input
752     * array.
753     * </p>
754     * <p>
755     * If the input array is {@code null}, a new one element array is returned
756     * whose component type is the same as the element.
757     * </p>
758     * <pre>
759     * ArrayUtils.add(null, 0, null)      = IllegalArgumentException
760     * ArrayUtils.add(null, 0, "a")       = ["a"]
761     * ArrayUtils.add(["a"], 1, null)     = ["a", null]
762     * ArrayUtils.add(["a"], 1, "b")      = ["a", "b"]
763     * ArrayUtils.add(["a", "b"], 3, "c") = ["a", "b", "c"]
764     * </pre>
765     *
766     * @param <T> the component type of the array
767     * @param array  the array to add the element to, may be {@code null}
768     * @param index  the position of the new object
769     * @param element  the object to add
770     * @return A new array containing the existing elements and the new element
771     * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt; array.length).
772     * @throws IllegalArgumentException if both array and element are null
773     * @deprecated this method has been superseded by {@link #insert(int, Object[], Object...) insert(int, T[], T...)} and
774     * may be removed in a future release. Please note the handling of {@code null} input arrays differs
775     * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
776     */
777    @Deprecated
778    public static <T> T[] add(final T[] array, final int index, final T element) {
779        final Class<T> clazz;
780        if (array != null) {
781            clazz = getComponentType(array);
782        } else if (element != null) {
783            clazz = ObjectUtils.getClass(element);
784        } else {
785            throw new IllegalArgumentException("Array and element cannot both be null");
786        }
787        return (T[]) add(array, index, element, clazz);
788    }
789
790    /**
791     * Copies the given array and adds the given element at the end of the new array.
792     * <p>
793     * The new array contains the same elements of the input
794     * array plus the given element in the last position. The component type of
795     * the new array is the same as that of the input array.
796     * </p>
797     * <p>
798     * If the input array is {@code null}, a new one element array is returned
799     * whose component type is the same as the element, unless the element itself is null,
800     * in which case the return type is Object[]
801     * </p>
802     * <pre>
803     * ArrayUtils.add(null, null)      = IllegalArgumentException
804     * ArrayUtils.add(null, "a")       = ["a"]
805     * ArrayUtils.add(["a"], null)     = ["a", null]
806     * ArrayUtils.add(["a"], "b")      = ["a", "b"]
807     * ArrayUtils.add(["a", "b"], "c") = ["a", "b", "c"]
808     * </pre>
809     *
810     * @param <T> the component type of the array
811     * @param array  the array to "add" the element to, may be {@code null}
812     * @param element  the object to add, may be {@code null}
813     * @return A new array containing the existing elements plus the new element
814     * The returned array type will be that of the input array (unless null),
815     * in which case it will have the same type as the element.
816     * If both are null, an IllegalArgumentException is thrown
817     * @throws IllegalArgumentException if both arguments are null
818     * @since 2.1
819     */
820    public static <T> T[] add(final T[] array, final T element) {
821        final Class<?> type;
822        if (array != null) {
823            type = array.getClass().getComponentType();
824        } else if (element != null) {
825            type = element.getClass();
826        } else {
827            throw new IllegalArgumentException("Arguments cannot both be null");
828        }
829        @SuppressWarnings("unchecked") // type must be T
830        final
831        T[] newArray = (T[]) copyArrayGrow1(array, type);
832        newArray[newArray.length - 1] = element;
833        return newArray;
834    }
835
836    /**
837     * Adds all the elements of the given arrays into a new array.
838     * <p>
839     * The new array contains all of the element of {@code array1} followed
840     * by all of the elements {@code array2}. When an array is returned, it is always
841     * a new array.
842     * </p>
843     * <pre>
844     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
845     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
846     * ArrayUtils.addAll([], [])         = []
847     * ArrayUtils.addAll(null, null)     = null
848     * </pre>
849     *
850     * @param array1  the first array whose elements are added to the new array.
851     * @param array2  the second array whose elements are added to the new array.
852     * @return The new boolean[] array or {@code null}.
853     * @since 2.1
854     */
855    public static boolean[] addAll(final boolean[] array1, final boolean... array2) {
856        if (array1 == null) {
857            return clone(array2);
858        }
859        if (array2 == null) {
860            return clone(array1);
861        }
862        final boolean[] joinedArray = new boolean[array1.length + array2.length];
863        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
864        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
865        return joinedArray;
866    }
867
868    /**
869     * Adds all the elements of the given arrays into a new array.
870     * <p>
871     * The new array contains all of the element of {@code array1} followed
872     * by all of the elements {@code array2}. When an array is returned, it is always
873     * a new array.
874     * </p>
875     * <pre>
876     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
877     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
878     * ArrayUtils.addAll([], [])         = []
879     * ArrayUtils.addAll(null, null)     = null
880     * </pre>
881     *
882     * @param array1  the first array whose elements are added to the new array.
883     * @param array2  the second array whose elements are added to the new array.
884     * @return The new byte[] array or {@code null}.
885     * @since 2.1
886     */
887    public static byte[] addAll(final byte[] array1, final byte... array2) {
888        if (array1 == null) {
889            return clone(array2);
890        }
891        if (array2 == null) {
892            return clone(array1);
893        }
894        final byte[] joinedArray = new byte[array1.length + array2.length];
895        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
896        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
897        return joinedArray;
898    }
899
900    /**
901     * Adds all the elements of the given arrays into a new array.
902     * <p>
903     * The new array contains all of the element of {@code array1} followed
904     * by all of the elements {@code array2}. When an array is returned, it is always
905     * a new array.
906     * </p>
907     * <pre>
908     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
909     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
910     * ArrayUtils.addAll([], [])         = []
911     * ArrayUtils.addAll(null, null)     = null
912     * </pre>
913     *
914     * @param array1  the first array whose elements are added to the new array.
915     * @param array2  the second array whose elements are added to the new array.
916     * @return The new char[] array or {@code null}.
917     * @since 2.1
918     */
919    public static char[] addAll(final char[] array1, final char... array2) {
920        if (array1 == null) {
921            return clone(array2);
922        }
923        if (array2 == null) {
924            return clone(array1);
925        }
926        final char[] joinedArray = new char[array1.length + array2.length];
927        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
928        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
929        return joinedArray;
930    }
931
932    /**
933     * Adds all the elements of the given arrays into a new array.
934     * <p>
935     * The new array contains all of the element of {@code array1} followed
936     * by all of the elements {@code array2}. When an array is returned, it is always
937     * a new array.
938     * </p>
939     * <pre>
940     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
941     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
942     * ArrayUtils.addAll([], [])         = []
943     * ArrayUtils.addAll(null, null)     = null
944     * </pre>
945     *
946     * @param array1  the first array whose elements are added to the new array.
947     * @param array2  the second array whose elements are added to the new array.
948     * @return The new double[] array or {@code null}.
949     * @since 2.1
950     */
951    public static double[] addAll(final double[] array1, final double... array2) {
952        if (array1 == null) {
953            return clone(array2);
954        }
955        if (array2 == null) {
956            return clone(array1);
957        }
958        final double[] joinedArray = new double[array1.length + array2.length];
959        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
960        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
961        return joinedArray;
962    }
963
964    /**
965     * Adds all the elements of the given arrays into a new array.
966     * <p>
967     * The new array contains all of the element of {@code array1} followed
968     * by all of the elements {@code array2}. When an array is returned, it is always
969     * a new array.
970     * </p>
971     * <pre>
972     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
973     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
974     * ArrayUtils.addAll([], [])         = []
975     * ArrayUtils.addAll(null, null)     = null
976     * </pre>
977     *
978     * @param array1  the first array whose elements are added to the new array.
979     * @param array2  the second array whose elements are added to the new array.
980     * @return The new float[] array or {@code null}.
981     * @since 2.1
982     */
983    public static float[] addAll(final float[] array1, final float... array2) {
984        if (array1 == null) {
985            return clone(array2);
986        }
987        if (array2 == null) {
988            return clone(array1);
989        }
990        final float[] joinedArray = new float[array1.length + array2.length];
991        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
992        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
993        return joinedArray;
994    }
995
996    /**
997     * Adds all the elements of the given arrays into a new array.
998     * <p>
999     * The new array contains all of the element of {@code array1} followed
1000     * by all of the elements {@code array2}. When an array is returned, it is always
1001     * a new array.
1002     * </p>
1003     * <pre>
1004     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1005     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1006     * ArrayUtils.addAll([], [])         = []
1007     * ArrayUtils.addAll(null, null)     = null
1008     * </pre>
1009     *
1010     * @param array1  the first array whose elements are added to the new array.
1011     * @param array2  the second array whose elements are added to the new array.
1012     * @return The new int[] array or {@code null}.
1013     * @since 2.1
1014     */
1015    public static int[] addAll(final int[] array1, final int... array2) {
1016        if (array1 == null) {
1017            return clone(array2);
1018        }
1019        if (array2 == null) {
1020            return clone(array1);
1021        }
1022        final int[] joinedArray = new int[array1.length + array2.length];
1023        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1024        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1025        return joinedArray;
1026    }
1027
1028    /**
1029     * Adds all the elements of the given arrays into a new array.
1030     * <p>
1031     * The new array contains all of the element of {@code array1} followed
1032     * by all of the elements {@code array2}. When an array is returned, it is always
1033     * a new array.
1034     * </p>
1035     * <pre>
1036     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1037     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1038     * ArrayUtils.addAll([], [])         = []
1039     * ArrayUtils.addAll(null, null)     = null
1040     * </pre>
1041     *
1042     * @param array1  the first array whose elements are added to the new array.
1043     * @param array2  the second array whose elements are added to the new array.
1044     * @return The new long[] array or {@code null}.
1045     * @since 2.1
1046     */
1047    public static long[] addAll(final long[] array1, final long... array2) {
1048        if (array1 == null) {
1049            return clone(array2);
1050        }
1051        if (array2 == null) {
1052            return clone(array1);
1053        }
1054        final long[] joinedArray = new long[array1.length + array2.length];
1055        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1056        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1057        return joinedArray;
1058    }
1059
1060    /**
1061     * Adds all the elements of the given arrays into a new array.
1062     * <p>
1063     * The new array contains all of the element of {@code array1} followed
1064     * by all of the elements {@code array2}. When an array is returned, it is always
1065     * a new array.
1066     * </p>
1067     * <pre>
1068     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1069     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1070     * ArrayUtils.addAll([], [])         = []
1071     * ArrayUtils.addAll(null, null)     = null
1072     * </pre>
1073     *
1074     * @param array1  the first array whose elements are added to the new array.
1075     * @param array2  the second array whose elements are added to the new array.
1076     * @return The new short[] array or {@code null}.
1077     * @since 2.1
1078     */
1079    public static short[] addAll(final short[] array1, final short... array2) {
1080        if (array1 == null) {
1081            return clone(array2);
1082        }
1083        if (array2 == null) {
1084            return clone(array1);
1085        }
1086        final short[] joinedArray = new short[array1.length + array2.length];
1087        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1088        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1089        return joinedArray;
1090    }
1091
1092    /**
1093     * Adds all the elements of the given arrays into a new array.
1094     * <p>
1095     * The new array contains all of the element of {@code array1} followed
1096     * by all of the elements {@code array2}. When an array is returned, it is always
1097     * a new array.
1098     * </p>
1099     * <pre>
1100     * ArrayUtils.addAll(null, null)     = null
1101     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1102     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1103     * ArrayUtils.addAll([], [])         = []
1104     * ArrayUtils.addAll(null, null)     = null
1105     * ArrayUtils.addAll([null], [null]) = [null, null]
1106     * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
1107     * </pre>
1108     *
1109     * @param <T> the component type of the array
1110     * @param array1  the first array whose elements are added to the new array, may be {@code null}
1111     * @param array2  the second array whose elements are added to the new array, may be {@code null}
1112     * @return The new array, {@code null} if both arrays are {@code null}.
1113     *      The type of the new array is the type of the first array,
1114     *      unless the first array is null, in which case the type is the same as the second array.
1115     * @throws IllegalArgumentException if the array types are incompatible
1116     * @since 2.1
1117     */
1118    public static <T> T[] addAll(final T[] array1, @SuppressWarnings("unchecked") final T... array2) {
1119        if (array1 == null) {
1120            return clone(array2);
1121        }
1122        if (array2 == null) {
1123            return clone(array1);
1124        }
1125        final Class<T> type1 = getComponentType(array1);
1126        final T[] joinedArray = arraycopy(array1, 0, 0, array1.length, () -> newInstance(type1, array1.length + array2.length));
1127        try {
1128            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1129        } catch (final ArrayStoreException ase) {
1130            // Check if problem was due to incompatible types
1131            /*
1132             * 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
1133             * strict
1134             */
1135            final Class<?> type2 = array2.getClass().getComponentType();
1136            if (!type1.isAssignableFrom(type2)) {
1137                throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of " + type1.getName(), ase);
1138            }
1139            throw ase; // No, so rethrow original
1140        }
1141        return joinedArray;
1142    }
1143
1144    /**
1145     * Copies the given array and adds the given element at the beginning of the new array.
1146     * <p>
1147     * The new array contains the same elements of the input array plus the given element in the first position. The
1148     * component type of the new array is the same as that of the input array.
1149     * </p>
1150     * <p>
1151     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1152     * element.
1153     * </p>
1154     * <pre>
1155     * ArrayUtils.addFirst(null, true)          = [true]
1156     * ArrayUtils.addFirst([true], false)       = [false, true]
1157     * ArrayUtils.addFirst([true, false], true) = [true, true, false]
1158     * </pre>
1159     *
1160     * @param array the array to "add" the element to, may be {@code null}.
1161     * @param element the object to add.
1162     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1163     *         the input array (unless null), in which case it will have the same type as the element.
1164     * @since 3.10
1165     */
1166    public static boolean[] addFirst(final boolean[] array, final boolean element) {
1167        return array == null ? add(array, element) : insert(0, array, element);
1168    }
1169
1170    /**
1171     * Copies the given array and adds the given element at the beginning of the new array.
1172     * <p>
1173     * The new array contains the same elements of the input array plus the given element in the first position. The
1174     * component type of the new array is the same as that of the input array.
1175     * </p>
1176     * <p>
1177     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1178     * element.
1179     * </p>
1180     * <pre>
1181     * ArrayUtils.addFirst(null, 1)   = [1]
1182     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1183     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1184     * </pre>
1185     *
1186     * @param array the array to "add" the element to, may be {@code null}.
1187     * @param element the object to add.
1188     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1189     *         the input array (unless null), in which case it will have the same type as the element.
1190     * @since 3.10
1191     */
1192    public static byte[] addFirst(final byte[] array, final byte element) {
1193        return array == null ? add(array, element) : insert(0, array, element);
1194    }
1195
1196    /**
1197     * Copies the given array and adds the given element at the beginning of the new array.
1198     * <p>
1199     * The new array contains the same elements of the input array plus the given element in the first position. The
1200     * component type of the new array is the same as that of the input array.
1201     * </p>
1202     * <p>
1203     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1204     * element.
1205     * </p>
1206     * <pre>
1207     * ArrayUtils.addFirst(null, '1')       = ['1']
1208     * ArrayUtils.addFirst(['1'], '0')      = ['0', '1']
1209     * ArrayUtils.addFirst(['1', '0'], '1') = ['1', '1', '0']
1210     * </pre>
1211     *
1212     * @param array the array to "add" the element to, may be {@code null}.
1213     * @param element the object to add.
1214     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1215     *         the input array (unless null), in which case it will have the same type as the element.
1216     * @since 3.10
1217     */
1218    public static char[] addFirst(final char[] array, final char element) {
1219        return array == null ? add(array, element) : insert(0, array, element);
1220    }
1221
1222    /**
1223     * Copies the given array and adds the given element at the beginning of the new array.
1224     * <p>
1225     * The new array contains the same elements of the input array plus the given element in the first position. The
1226     * component type of the new array is the same as that of the input array.
1227     * </p>
1228     * <p>
1229     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1230     * element.
1231     * </p>
1232     * <pre>
1233     * ArrayUtils.addFirst(null, 1)   = [1]
1234     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1235     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1236     * </pre>
1237     *
1238     * @param array the array to "add" the element to, may be {@code null}.
1239     * @param element the object to add.
1240     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1241     *         the input array (unless null), in which case it will have the same type as the element.
1242     * @since 3.10
1243     */
1244    public static double[] addFirst(final double[] array, final double element) {
1245        return array == null ? add(array, element) : insert(0, array, element);
1246    }
1247
1248    /**
1249     * Copies the given array and adds the given element at the beginning of the new array.
1250     * <p>
1251     * The new array contains the same elements of the input array plus the given element in the first position. The
1252     * component type of the new array is the same as that of the input array.
1253     * </p>
1254     * <p>
1255     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1256     * element.
1257     * </p>
1258     * <pre>
1259     * ArrayUtils.addFirst(null, 1)   = [1]
1260     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1261     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1262     * </pre>
1263     *
1264     * @param array the array to "add" the element to, may be {@code null}.
1265     * @param element the object to add.
1266     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1267     *         the input array (unless null), in which case it will have the same type as the element.
1268     * @since 3.10
1269     */
1270    public static float[] addFirst(final float[] array, final float element) {
1271        return array == null ? add(array, element) : insert(0, array, element);
1272    }
1273
1274    /**
1275     * Copies the given array and adds the given element at the beginning of the new array.
1276     * <p>
1277     * The new array contains the same elements of the input array plus the given element in the first position. The
1278     * component type of the new array is the same as that of the input array.
1279     * </p>
1280     * <p>
1281     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1282     * element.
1283     * </p>
1284     * <pre>
1285     * ArrayUtils.addFirst(null, 1)   = [1]
1286     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1287     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1288     * </pre>
1289     *
1290     * @param array the array to "add" the element to, may be {@code null}.
1291     * @param element the object to add.
1292     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1293     *         the input array (unless null), in which case it will have the same type as the element.
1294     * @since 3.10
1295     */
1296    public static int[] addFirst(final int[] array, final int element) {
1297        return array == null ? add(array, element) : insert(0, array, element);
1298    }
1299
1300    /**
1301     * Copies the given array and adds the given element at the beginning of the new array.
1302     * <p>
1303     * The new array contains the same elements of the input array plus the given element in the first position. The
1304     * component type of the new array is the same as that of the input array.
1305     * </p>
1306     * <p>
1307     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1308     * element.
1309     * </p>
1310     * <pre>
1311     * ArrayUtils.addFirst(null, 1)   = [1]
1312     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1313     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1314     * </pre>
1315     *
1316     * @param array the array to "add" the element to, may be {@code null}.
1317     * @param element the object to add.
1318     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1319     *         the input array (unless null), in which case it will have the same type as the element.
1320     * @since 3.10
1321     */
1322    public static long[] addFirst(final long[] array, final long element) {
1323        return array == null ? add(array, element) : insert(0, array, element);
1324    }
1325
1326    /**
1327     * Copies the given array and adds the given element at the beginning of the new array.
1328     * <p>
1329     * The new array contains the same elements of the input array plus the given element in the first position. The
1330     * component type of the new array is the same as that of the input array.
1331     * </p>
1332     * <p>
1333     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1334     * element.
1335     * </p>
1336     * <pre>
1337     * ArrayUtils.addFirst(null, 1)   = [1]
1338     * ArrayUtils.addFirst([1], 0)    = [0, 1]
1339     * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1340     * </pre>
1341     *
1342     * @param array the array to "add" the element to, may be {@code null}.
1343     * @param element the object to add.
1344     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1345     *         the input array (unless null), in which case it will have the same type as the element.
1346     * @since 3.10
1347     */
1348    public static short[] addFirst(final short[] array, final short element) {
1349        return array == null ? add(array, element) : insert(0, array, element);
1350    }
1351
1352    /**
1353     * Copies the given array and adds the given element at the beginning of the new array.
1354     * <p>
1355     * The new array contains the same elements of the input array plus the given element in the first position. The
1356     * component type of the new array is the same as that of the input array.
1357     * </p>
1358     * <p>
1359     * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1360     * element, unless the element itself is null, in which case the return type is Object[]
1361     * </p>
1362     * <pre>
1363     * ArrayUtils.addFirst(null, null)      = IllegalArgumentException
1364     * ArrayUtils.addFirst(null, "a")       = ["a"]
1365     * ArrayUtils.addFirst(["a"], null)     = [null, "a"]
1366     * ArrayUtils.addFirst(["a"], "b")      = ["b", "a"]
1367     * ArrayUtils.addFirst(["a", "b"], "c") = ["c", "a", "b"]
1368     * </pre>
1369     *
1370     * @param <T> the component type of the array
1371     * @param array the array to "add" the element to, may be {@code null}
1372     * @param element the object to add, may be {@code null}
1373     * @return A new array containing the existing elements plus the new element The returned array type will be that of
1374     *         the input array (unless null), in which case it will have the same type as the element. If both are null,
1375     *         an IllegalArgumentException is thrown
1376     * @throws IllegalArgumentException if both arguments are null
1377     * @since 3.10
1378     */
1379    public static <T> T[] addFirst(final T[] array, final T element) {
1380        return array == null ? add(array, element) : insert(0, array, element);
1381    }
1382
1383    /**
1384     * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array.
1385     *
1386     * @param <T>       the type.
1387     * @param source    the source array.
1388     * @param sourcePos starting position in the source array.
1389     * @param destPos   starting position in the destination data.
1390     * @param length    the number of array elements to be copied.
1391     * @param allocator allocates the array to populate and return.
1392     * @return dest
1393     * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds.
1394     * @throws ArrayStoreException       if an element in the {@code src} array could not be stored into the {@code dest} array because of a type
1395     *                                   mismatch.
1396     * @throws NullPointerException      if either {@code src} or {@code dest} is {@code null}.
1397     * @since 3.15.0
1398     */
1399    public static <T> T arraycopy(final T source, final int sourcePos, final int destPos, final int length, final Function<Integer, T> allocator) {
1400        return arraycopy(source, sourcePos, allocator.apply(length), destPos, length);
1401    }
1402
1403    /**
1404     * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array.
1405     *
1406     * @param <T>       the type.
1407     * @param source    the source array.
1408     * @param sourcePos starting position in the source array.
1409     * @param destPos   starting position in the destination data.
1410     * @param length    the number of array elements to be copied.
1411     * @param allocator allocates the array to populate and return.
1412     * @return dest
1413     * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds.
1414     * @throws ArrayStoreException       if an element in the {@code src} array could not be stored into the {@code dest} array because of a type
1415     *                                   mismatch.
1416     * @throws NullPointerException      if either {@code src} or {@code dest} is {@code null}.
1417     * @since 3.15.0
1418     */
1419    public static <T> T arraycopy(final T source, final int sourcePos, final int destPos, final int length, final Supplier<T> allocator) {
1420        return arraycopy(source, sourcePos, allocator.get(), destPos, length);
1421    }
1422
1423    /**
1424     * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array.
1425     *
1426     * @param <T>       the type
1427     * @param source    the source array.
1428     * @param sourcePos starting position in the source array.
1429     * @param dest      the destination array.
1430     * @param destPos   starting position in the destination data.
1431     * @param length    the number of array elements to be copied.
1432     * @return dest
1433     * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds.
1434     * @throws ArrayStoreException       if an element in the {@code src} array could not be stored into the {@code dest} array because of a type
1435     *                                   mismatch.
1436     * @throws NullPointerException      if either {@code src} or {@code dest} is {@code null}.
1437     * @since 3.15.0
1438     */
1439    public static <T> T arraycopy(final T source, final int sourcePos, final T dest, final int destPos, final int length) {
1440        System.arraycopy(source, sourcePos, dest, destPos, length);
1441        return dest;
1442    }
1443
1444    /**
1445     * Clones an array or returns {@code null}.
1446     * <p>
1447     * This method returns {@code null} for a {@code null} input array.
1448     * </p>
1449     *
1450     * @param array the array to clone, may be {@code null}
1451     * @return the cloned array, {@code null} if {@code null} input
1452     */
1453    public static boolean[] clone(final boolean[] array) {
1454        return array != null ? array.clone() : null;
1455    }
1456
1457    /**
1458     * Clones an array or returns {@code null}.
1459     * <p>
1460     * This method returns {@code null} for a {@code null} input array.
1461     * </p>
1462     *
1463     * @param array the array to clone, may be {@code null}
1464     * @return the cloned array, {@code null} if {@code null} input
1465     */
1466    public static byte[] clone(final byte[] array) {
1467        return array != null ? array.clone() : null;
1468    }
1469
1470    /**
1471     * Clones an array or returns {@code null}.
1472     * <p>
1473     * This method returns {@code null} for a {@code null} input array.
1474     * </p>
1475     *
1476     * @param array the array to clone, may be {@code null}
1477     * @return the cloned array, {@code null} if {@code null} input
1478     */
1479    public static char[] clone(final char[] array) {
1480        return array != null ? array.clone() : null;
1481    }
1482
1483    /**
1484     * Clones an array or returns {@code null}.
1485     * <p>
1486     * This method returns {@code null} for a {@code null} input array.
1487     * </p>
1488     *
1489     * @param array the array to clone, may be {@code null}
1490     * @return the cloned array, {@code null} if {@code null} input
1491     */
1492    public static double[] clone(final double[] array) {
1493        return array != null ? array.clone() : null;
1494    }
1495
1496    /**
1497     * Clones an array or returns {@code null}.
1498     * <p>
1499     * This method returns {@code null} for a {@code null} input array.
1500     * </p>
1501     *
1502     * @param array the array to clone, may be {@code null}
1503     * @return the cloned array, {@code null} if {@code null} input
1504     */
1505    public static float[] clone(final float[] array) {
1506        return array != null ? array.clone() : null;
1507    }
1508
1509    /**
1510     * Clones an array or returns {@code null}.
1511     * <p>
1512     * This method returns {@code null} for a {@code null} input array.
1513     * </p>
1514     *
1515     * @param array the array to clone, may be {@code null}
1516     * @return the cloned array, {@code null} if {@code null} input
1517     */
1518    public static int[] clone(final int[] array) {
1519        return array != null ? array.clone() : null;
1520    }
1521
1522    /**
1523     * Clones an array or returns {@code null}.
1524     * <p>
1525     * This method returns {@code null} for a {@code null} input array.
1526     * </p>
1527     *
1528     * @param array the array to clone, may be {@code null}
1529     * @return the cloned array, {@code null} if {@code null} input
1530     */
1531    public static long[] clone(final long[] array) {
1532        return array != null ? array.clone() : null;
1533    }
1534
1535    /**
1536     * Clones an array or returns {@code null}.
1537     * <p>
1538     * This method returns {@code null} for a {@code null} input array.
1539     * </p>
1540     *
1541     * @param array the array to clone, may be {@code null}
1542     * @return the cloned array, {@code null} if {@code null} input
1543     */
1544    public static short[] clone(final short[] array) {
1545        return array != null ? array.clone() : null;
1546    }
1547
1548    /**
1549     * Shallow clones an array or returns {@code null}.
1550     * <p>
1551     * The objects in the array are not cloned, thus there is no special handling for multi-dimensional arrays.
1552     * </p>
1553     * <p>
1554     * This method returns {@code null} for a {@code null} input array.
1555     * </p>
1556     *
1557     * @param <T>   the component type of the array
1558     * @param array the array to shallow clone, may be {@code null}
1559     * @return the cloned array, {@code null} if {@code null} input
1560     */
1561    public static <T> T[] clone(final T[] array) {
1562        return array != null ? array.clone() : null;
1563    }
1564
1565    /**
1566     * Checks if the value is in the given array.
1567     * <p>
1568     * The method returns {@code false} if a {@code null} array is passed in.
1569     * </p>
1570     *
1571     * @param array  the array to search
1572     * @param valueToFind  the value to find
1573     * @return {@code true} if the array contains the object
1574     */
1575    public static boolean contains(final boolean[] array, final boolean valueToFind) {
1576        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1577    }
1578
1579    /**
1580     * Checks if the value is in the given array.
1581     * <p>
1582     * The method returns {@code false} if a {@code null} array is passed in.
1583     * </p>
1584     * <p>
1585     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1586     * {@link Arrays#sort(byte[])} and {@link Arrays#binarySearch(byte[], byte)}.
1587     * </p>
1588     *
1589     * @param array  the array to search
1590     * @param valueToFind  the value to find
1591     * @return {@code true} if the array contains the object
1592     */
1593    public static boolean contains(final byte[] array, final byte valueToFind) {
1594        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1595    }
1596
1597    /**
1598     * Checks if the value is in the given array.
1599     * <p>
1600     * The method returns {@code false} if a {@code null} array is passed in.
1601     * </p>
1602     * <p>
1603     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1604     * {@link Arrays#sort(char[])} and {@link Arrays#binarySearch(char[], char)}.
1605     * </p>
1606     *
1607     * @param array  the array to search
1608     * @param valueToFind  the value to find
1609     * @return {@code true} if the array contains the object
1610     * @since 2.1
1611     */
1612    public static boolean contains(final char[] array, final char valueToFind) {
1613        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1614    }
1615
1616    /**
1617     * Checks if the value is in the given array.
1618     * <p>
1619     * The method returns {@code false} if a {@code null} array is passed in.
1620     * </p>
1621     * <p>
1622     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1623     * {@link Arrays#sort(double[])} and {@link Arrays#binarySearch(double[], double)}.
1624     * </p>
1625     *
1626     * @param array  the array to search
1627     * @param valueToFind  the value to find
1628     * @return {@code true} if the array contains the object
1629     */
1630    public static boolean contains(final double[] array, final double valueToFind) {
1631        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1632    }
1633
1634    /**
1635     * Checks if a value falling within the given tolerance is in the
1636     * given array.  If the array contains a value within the inclusive range
1637     * defined by (value - tolerance) to (value + tolerance).
1638     * <p>
1639     * The method returns {@code false} if a {@code null} array
1640     * is passed in.
1641     * </p>
1642     * <p>
1643     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1644     * {@link Arrays#sort(double[])} and {@link Arrays#binarySearch(double[], double)}.
1645     * </p>
1646     *
1647     * @param array  the array to search
1648     * @param valueToFind  the value to find
1649     * @param tolerance  the array contains the tolerance of the search
1650     * @return true if value falling within tolerance is in array
1651     */
1652    public static boolean contains(final double[] array, final double valueToFind, final double tolerance) {
1653        return indexOf(array, valueToFind, 0, tolerance) != INDEX_NOT_FOUND;
1654    }
1655
1656    /**
1657     * Checks if the value is in the given array.
1658     * <p>
1659     * The method returns {@code false} if a {@code null} array is passed in.
1660     * </p>
1661     * <p>
1662     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1663     * {@link Arrays#sort(float[])} and {@link Arrays#binarySearch(float[], float)}.
1664     * </p>
1665     *
1666     * @param array  the array to search
1667     * @param valueToFind  the value to find
1668     * @return {@code true} if the array contains the object
1669     */
1670    public static boolean contains(final float[] array, final float valueToFind) {
1671        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1672    }
1673
1674    /**
1675     * Checks if the value is in the given array.
1676     * <p>
1677     * The method returns {@code false} if a {@code null} array is passed in.
1678     * </p>
1679     * <p>
1680     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1681     * {@link Arrays#sort(int[])} and {@link Arrays#binarySearch(int[], int)}.
1682     * </p>
1683     *
1684     * @param array  the array to search
1685     * @param valueToFind  the value to find
1686     * @return {@code true} if the array contains the object
1687     */
1688    public static boolean contains(final int[] array, final int valueToFind) {
1689        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1690    }
1691
1692    /**
1693     * Checks if the value is in the given array.
1694     * <p>
1695     * The method returns {@code false} if a {@code null} array is passed in.
1696     * </p>
1697     * <p>
1698     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1699     * {@link Arrays#sort(long[])} and {@link Arrays#binarySearch(long[], long)}.
1700     * </p>
1701     *
1702     * @param array  the array to search
1703     * @param valueToFind  the value to find
1704     * @return {@code true} if the array contains the object
1705     */
1706    public static boolean contains(final long[] array, final long valueToFind) {
1707        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1708    }
1709
1710    /**
1711     * Checks if the object is in the given array.
1712     * <p>
1713     * The method returns {@code false} if a {@code null} array is passed in.
1714     * </p>
1715     * <p>
1716     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1717     * {@link Arrays#sort(Object[], Comparator)} and {@link Arrays#binarySearch(Object[], Object)}.
1718     * </p>
1719     *
1720     * @param array  the array to search, may be {@code null}.
1721     * @param objectToFind  the object to find, may be {@code null}.
1722     * @return {@code true} if the array contains the object
1723     */
1724    public static boolean contains(final Object[] array, final Object objectToFind) {
1725        return indexOf(array, objectToFind) != INDEX_NOT_FOUND;
1726    }
1727
1728    /**
1729     * Checks if the value is in the given array.
1730     * <p>
1731     * The method returns {@code false} if a {@code null} array is passed in.
1732     * </p>
1733     * <p>
1734     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1735     * {@link Arrays#sort(short[])} and {@link Arrays#binarySearch(short[], short)}.
1736     * </p>
1737     *
1738     * @param array  the array to search
1739     * @param valueToFind  the value to find
1740     * @return {@code true} if the array contains the object
1741     */
1742    public static boolean contains(final short[] array, final short valueToFind) {
1743        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1744    }
1745
1746    /**
1747     * Checks if any of the ints are in the given array.
1748     * <p>
1749     * The method returns {@code false} if a {@code null} array is passed in.
1750     * </p>
1751     * <p>
1752     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1753     * {@link Arrays#sort(int[])} and {@link Arrays#binarySearch(int[], int)}.
1754     * </p>
1755     *
1756     * @param array         the array to search
1757     * @param objectsToFind any of the ints to find
1758     * @return {@code true} if the array contains any of the ints
1759     * @since 3.18.0
1760     */
1761    public static boolean containsAny(final int[] array, final int... objectsToFind) {
1762        return IntStreams.of(objectsToFind).anyMatch(e -> contains(array, e));
1763    }
1764
1765    /**
1766     * Checks if any of the objects are in the given array.
1767     * <p>
1768     * The method returns {@code false} if a {@code null} array is passed in.
1769     * </p>
1770     * <p>
1771     * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1772     * {@link Arrays#sort(Object[], Comparator)} and {@link Arrays#binarySearch(Object[], Object)}.
1773     * </p>
1774     *
1775     * @param array         the array to search, may be {@code null}.
1776     * @param objectsToFind any of the objects to find, may be {@code null}.
1777     * @return {@code true} if the array contains any of the objects
1778     * @since 3.13.0
1779     */
1780    public static boolean containsAny(final Object[] array, final Object... objectsToFind) {
1781        return Streams.of(objectsToFind).anyMatch(e -> contains(array, e));
1782    }
1783
1784    /**
1785     * Returns a copy of the given array of size 1 greater than the argument.
1786     * The last value of the array is left to the default value.
1787     *
1788     * @param array The array to copy, must not be {@code null}.
1789     * @param newArrayComponentType If {@code array} is {@code null}, create a
1790     * size 1 array of this type.
1791     * @return A new copy of the array of size 1 greater than the input.
1792     */
1793    private static Object copyArrayGrow1(final Object array, final Class<?> newArrayComponentType) {
1794        if (array != null) {
1795            final int arrayLength = Array.getLength(array);
1796            final Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
1797            System.arraycopy(array, 0, newArray, 0, arrayLength);
1798            return newArray;
1799        }
1800        return Array.newInstance(newArrayComponentType, 1);
1801    }
1802
1803    /**
1804     * Gets the nTh element of an array or null if the index is out of bounds or the array is null.
1805     *
1806     * @param <T> The type of array elements.
1807     * @param array The array to index.
1808     * @param index The index
1809     * @return the nTh element of an array or null if the index is out of bounds or the array is null.
1810     * @since 3.11
1811     */
1812    public static <T> T get(final T[] array, final int index) {
1813        return get(array, index, null);
1814    }
1815
1816    /**
1817     * Gets the nTh element of an array or a default value if the index is out of bounds.
1818     *
1819     * @param <T> The type of array elements.
1820     * @param array The array to index.
1821     * @param index The index
1822     * @param defaultValue The return value of the given index is out of bounds.
1823     * @return the nTh element of an array or a default value if the index is out of bounds.
1824     * @since 3.11
1825     */
1826    public static <T> T get(final T[] array, final int index, final T defaultValue) {
1827        return isArrayIndexValid(array, index) ? array[index] : defaultValue;
1828    }
1829
1830    /**
1831     * Gets an array's component type.
1832     *
1833     * @param <T> The array type.
1834     * @param array The array.
1835     * @return The component type.
1836     * @since 3.13.0
1837     */
1838    public static <T> Class<T> getComponentType(final T[] array) {
1839        return ClassUtils.getComponentType(ObjectUtils.getClass(array));
1840    }
1841
1842    /**
1843     * Gets the length of the specified array.
1844     * This method can deal with {@link Object} arrays and with primitive arrays.
1845     * <p>
1846     * If the input array is {@code null}, {@code 0} is returned.
1847     * </p>
1848     * <pre>
1849     * ArrayUtils.getLength(null)            = 0
1850     * ArrayUtils.getLength([])              = 0
1851     * ArrayUtils.getLength([null])          = 1
1852     * ArrayUtils.getLength([true, false])   = 2
1853     * ArrayUtils.getLength([1, 2, 3])       = 3
1854     * ArrayUtils.getLength(["a", "b", "c"]) = 3
1855     * </pre>
1856     *
1857     * @param array  the array to retrieve the length from, may be {@code null}.
1858     * @return The length of the array, or {@code 0} if the array is {@code null}
1859     * @throws IllegalArgumentException if the object argument is not an array.
1860     * @since 2.1
1861     */
1862    public static int getLength(final Object array) {
1863        return array != null ? Array.getLength(array) : 0;
1864    }
1865
1866    /**
1867     * Gets a hash code for an array handling multidimensional arrays correctly.
1868     * <p>
1869     * Multi-dimensional primitive arrays are also handled correctly by this method.
1870     * </p>
1871     *
1872     * @param array  the array to get a hash code for, {@code null} returns zero
1873     * @return a hash code for the array
1874     */
1875    public static int hashCode(final Object array) {
1876        return new HashCodeBuilder().append(array).toHashCode();
1877    }
1878
1879    static <K> void increment(final Map<K, MutableInt> occurrences, final K boxed) {
1880        occurrences.computeIfAbsent(boxed, k -> new MutableInt()).increment();
1881    }
1882
1883    /**
1884     * Finds the indices of the given value in the array.
1885     * <p>
1886     * This method returns an empty BitSet for a {@code null} input array.
1887     * </p>
1888     *
1889     * @param array  the array to search for the object, may be {@code null}
1890     * @param valueToFind  the value to find
1891     * @return a BitSet of all the indices of the value within the array,
1892     *  an empty BitSet if not found or {@code null} array input
1893     * @since 3.10
1894     */
1895    public static BitSet indexesOf(final boolean[] array, final boolean valueToFind) {
1896        return indexesOf(array, valueToFind, 0);
1897    }
1898
1899    /**
1900     * Finds the indices of the given value in the array starting at the given index.
1901     * <p>
1902     * This method returns an empty BitSet for a {@code null} input array.
1903     * </p>
1904     * <p>
1905     * A negative startIndex is treated as zero. A startIndex larger than the array
1906     * length will return an empty BitSet ({@code -1}).
1907     * </p>
1908     *
1909     * @param array  the array to search for the object, may be {@code null}
1910     * @param valueToFind  the value to find
1911     * @param startIndex  the index to start searching at
1912     * @return a BitSet of all the indices of the value within the array,
1913     *  an empty BitSet if not found or {@code null}
1914     *  array input
1915     * @since 3.10
1916     */
1917    public static BitSet indexesOf(final boolean[] array, final boolean valueToFind, int startIndex) {
1918        final BitSet bitSet = new BitSet();
1919        if (array == null) {
1920            return bitSet;
1921        }
1922        while (startIndex < array.length) {
1923            startIndex = indexOf(array, valueToFind, startIndex);
1924            if (startIndex == INDEX_NOT_FOUND) {
1925                break;
1926            }
1927            bitSet.set(startIndex);
1928            ++startIndex;
1929        }
1930        return bitSet;
1931    }
1932
1933    /**
1934     * Finds the indices of the given value in the array.
1935     *
1936     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
1937     *
1938     * @param array  the array to search for the object, may be {@code null}
1939     * @param valueToFind  the value to find
1940     * @return a BitSet of all the indices of the value within the array,
1941     *  an empty BitSet if not found or {@code null} array input
1942     * @since 3.10
1943     */
1944    public static BitSet indexesOf(final byte[] array, final byte valueToFind) {
1945        return indexesOf(array, valueToFind, 0);
1946    }
1947
1948    /**
1949     * Finds the indices of the given value in the array starting at the given index.
1950     *
1951     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
1952     *
1953     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
1954     * length will return an empty BitSet.</p>
1955     *
1956     * @param array  the array to search for the object, may be {@code null}
1957     * @param valueToFind  the value to find
1958     * @param startIndex  the index to start searching at
1959     * @return a BitSet of all the indices of the value within the array,
1960     *  an empty BitSet if not found or {@code null} array input
1961     * @since 3.10
1962     */
1963    public static BitSet indexesOf(final byte[] array, final byte valueToFind, int startIndex) {
1964        final BitSet bitSet = new BitSet();
1965        if (array == null) {
1966            return bitSet;
1967        }
1968        while (startIndex < array.length) {
1969            startIndex = indexOf(array, valueToFind, startIndex);
1970            if (startIndex == INDEX_NOT_FOUND) {
1971                break;
1972            }
1973            bitSet.set(startIndex);
1974            ++startIndex;
1975        }
1976
1977        return bitSet;
1978    }
1979
1980    /**
1981     * Finds the indices of the given value in the array.
1982     *
1983     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
1984     *
1985     * @param array  the array to search for the object, may be {@code null}
1986     * @param valueToFind  the value to find
1987     * @return a BitSet of all the indices of the value within the array,
1988     *  an empty BitSet if not found or {@code null} array input
1989     * @since 3.10
1990     */
1991    public static BitSet indexesOf(final char[] array, final char valueToFind) {
1992        return indexesOf(array, valueToFind, 0);
1993    }
1994
1995    /**
1996     * Finds the indices of the given value in the array starting at the given index.
1997     *
1998     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
1999     *
2000     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2001     * length will return an empty BitSet.</p>
2002     *
2003     * @param array  the array to search for the object, may be {@code null}
2004     * @param valueToFind  the value to find
2005     * @param startIndex  the index to start searching at
2006     * @return a BitSet of all the indices of the value within the array,
2007     *  an empty BitSet if not found or {@code null} array input
2008     * @since 3.10
2009     */
2010    public static BitSet indexesOf(final char[] array, final char valueToFind, int startIndex) {
2011        final BitSet bitSet = new BitSet();
2012        if (array == null) {
2013            return bitSet;
2014        }
2015        while (startIndex < array.length) {
2016            startIndex = indexOf(array, valueToFind, startIndex);
2017            if (startIndex == INDEX_NOT_FOUND) {
2018                break;
2019            }
2020            bitSet.set(startIndex);
2021            ++startIndex;
2022        }
2023        return bitSet;
2024    }
2025
2026    /**
2027     * Finds the indices of the given value in the array.
2028     *
2029     * <p>This method returns empty BitSet for a {@code null} input array.</p>
2030     *
2031     * @param array  the array to search for the object, may be {@code null}
2032     * @param valueToFind  the value to find
2033     * @return a BitSet of all the indices of the value within the array,
2034     *  an empty BitSet if not found or {@code null} array input
2035     * @since 3.10
2036     */
2037    public static BitSet indexesOf(final double[] array, final double valueToFind) {
2038        return indexesOf(array, valueToFind, 0);
2039    }
2040
2041    /**
2042     * Finds the indices of the given value within a given tolerance in the array.
2043     *
2044     * <p>
2045     * This method will return all the indices of the value which fall between the region
2046     * defined by valueToFind - tolerance and valueToFind + tolerance, each time between the nearest integers.
2047     * </p>
2048     *
2049     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2050     *
2051     * @param array  the array to search for the object, may be {@code null}
2052     * @param valueToFind  the value to find
2053     * @param tolerance tolerance of the search
2054     * @return a BitSet of all the indices of the value within the array,
2055     *  an empty BitSet if not found or {@code null} array input
2056     * @since 3.10
2057     */
2058    public static BitSet indexesOf(final double[] array, final double valueToFind, final double tolerance) {
2059        return indexesOf(array, valueToFind, 0, tolerance);
2060    }
2061
2062    /**
2063     * Finds the indices of the given value in the array starting at the given index.
2064     *
2065     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2066     *
2067     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2068     * length will return an empty BitSet.</p>
2069     *
2070     * @param array  the array to search for the object, may be {@code null}
2071     * @param valueToFind  the value to find
2072     * @param startIndex  the index to start searching at
2073     * @return a BitSet of the indices of the value within the array,
2074     *  an empty BitSet if not found or {@code null} array input
2075     * @since 3.10
2076     */
2077    public static BitSet indexesOf(final double[] array, final double valueToFind, int startIndex) {
2078        final BitSet bitSet = new BitSet();
2079        if (array == null) {
2080            return bitSet;
2081        }
2082        while (startIndex < array.length) {
2083            startIndex = indexOf(array, valueToFind, startIndex);
2084            if (startIndex == INDEX_NOT_FOUND) {
2085                break;
2086            }
2087            bitSet.set(startIndex);
2088            ++startIndex;
2089        }
2090        return bitSet;
2091    }
2092
2093    /**
2094     * Finds the indices of the given value in the array starting at the given index.
2095     *
2096     * <p>
2097     * This method will return the indices of the values which fall between the region
2098     * defined by valueToFind - tolerance and valueToFind + tolerance, between the nearest integers.
2099     * </p>
2100     *
2101     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2102     *
2103     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2104     * length will return an empty BitSet.</p>
2105     *
2106     * @param array  the array to search for the object, may be {@code null}
2107     * @param valueToFind  the value to find
2108     * @param startIndex  the index to start searching at
2109     * @param tolerance tolerance of the search
2110     * @return a BitSet of the indices of the value within the array,
2111     *  an empty BitSet if not found or {@code null} array input
2112     * @since 3.10
2113     */
2114    public static BitSet indexesOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
2115        final BitSet bitSet = new BitSet();
2116        if (array == null) {
2117            return bitSet;
2118        }
2119        while (startIndex < array.length) {
2120            startIndex = indexOf(array, valueToFind, startIndex, tolerance);
2121            if (startIndex == INDEX_NOT_FOUND) {
2122                break;
2123            }
2124            bitSet.set(startIndex);
2125            ++startIndex;
2126        }
2127        return bitSet;
2128    }
2129
2130    /**
2131     * Finds the indices of the given value in the array.
2132     *
2133     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2134     *
2135     * @param array  the array to search for the object, may be {@code null}
2136     * @param valueToFind  the value to find
2137     * @return a BitSet of all the indices of the value within the array,
2138     *  an empty BitSet if not found or {@code null} array input
2139     * @since 3.10
2140     */
2141    public static BitSet indexesOf(final float[] array, final float valueToFind) {
2142        return indexesOf(array, valueToFind, 0);
2143    }
2144
2145    /**
2146     * Finds the indices of the given value in the array starting at the given index.
2147     *
2148     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2149     *
2150     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2151     * length will return empty BitSet.</p>
2152     *
2153     * @param array  the array to search for the object, may be {@code null}
2154     * @param valueToFind  the value to find
2155     * @param startIndex  the index to start searching at
2156     * @return a BitSet of all the indices of the value within the array,
2157     *  an empty BitSet if not found or {@code null} array input
2158     * @since 3.10
2159     */
2160    public static BitSet indexesOf(final float[] array, final float valueToFind, int startIndex) {
2161        final BitSet bitSet = new BitSet();
2162        if (array == null) {
2163            return bitSet;
2164        }
2165        while (startIndex < array.length) {
2166            startIndex = indexOf(array, valueToFind, startIndex);
2167            if (startIndex == INDEX_NOT_FOUND) {
2168                break;
2169            }
2170            bitSet.set(startIndex);
2171            ++startIndex;
2172        }
2173        return bitSet;
2174    }
2175
2176    /**
2177     * Finds the indices of the given value in the array.
2178     *
2179     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2180     *
2181     * @param array  the array to search for the object, may be {@code null}
2182     * @param valueToFind  the value to find
2183     * @return a BitSet of all the indices of the value within the array,
2184     *  an empty BitSet if not found or {@code null} array input
2185     * @since 3.10
2186     */
2187    public static BitSet indexesOf(final int[] array, final int valueToFind) {
2188        return indexesOf(array, valueToFind, 0);
2189    }
2190
2191    /**
2192     * Finds the indices of the given value in the array starting at the given index.
2193     *
2194     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2195     *
2196     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2197     * length will return an empty BitSet.</p>
2198     *
2199     * @param array  the array to search for the object, may be {@code null}
2200     * @param valueToFind  the value to find
2201     * @param startIndex  the index to start searching at
2202     * @return a BitSet of all the indices of the value within the array,
2203     *  an empty BitSet if not found or {@code null} array input
2204     * @since 3.10
2205     */
2206    public static BitSet indexesOf(final int[] array, final int valueToFind, int startIndex) {
2207        final BitSet bitSet = new BitSet();
2208        if (array == null) {
2209            return bitSet;
2210        }
2211        while (startIndex < array.length) {
2212            startIndex = indexOf(array, valueToFind, startIndex);
2213
2214            if (startIndex == INDEX_NOT_FOUND) {
2215                break;
2216            }
2217            bitSet.set(startIndex);
2218            ++startIndex;
2219        }
2220        return bitSet;
2221    }
2222
2223    /**
2224     * Finds the indices of the given value in the array.
2225     *
2226     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2227     *
2228     * @param array  the array to search for the object, may be {@code null}
2229     * @param valueToFind  the value to find
2230     * @return a BitSet of all the indices of the value within the array,
2231     *  an empty BitSet if not found or {@code null} array input
2232     * @since 3.10
2233     */
2234    public static BitSet indexesOf(final long[] array, final long valueToFind) {
2235        return indexesOf(array, valueToFind, 0);
2236    }
2237
2238    /**
2239     * Finds the indices of the given value in the array starting at the given index.
2240     *
2241     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2242     *
2243     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2244     * length will return an empty BitSet.</p>
2245     *
2246     * @param array  the array to search for the object, may be {@code null}
2247     * @param valueToFind  the value to find
2248     * @param startIndex  the index to start searching at
2249     * @return a BitSet of all the indices of the value within the array,
2250     *  an empty BitSet if not found or {@code null} array input
2251     * @since 3.10
2252     */
2253    public static BitSet indexesOf(final long[] array, final long valueToFind, int startIndex) {
2254        final BitSet bitSet = new BitSet();
2255        if (array == null) {
2256            return bitSet;
2257        }
2258        while (startIndex < array.length) {
2259            startIndex = indexOf(array, valueToFind, startIndex);
2260            if (startIndex == INDEX_NOT_FOUND) {
2261                break;
2262            }
2263            bitSet.set(startIndex);
2264            ++startIndex;
2265        }
2266        return bitSet;
2267    }
2268
2269    /**
2270     * Finds the indices of the given object in the array.
2271     *
2272     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2273     *
2274     * @param array  the array to search for the object, may be {@code null}.
2275     * @param objectToFind  the object to find, may be {@code null}.
2276     * @return a BitSet of all the indices of the object within the array,
2277     *  an empty BitSet if not found or {@code null} array input
2278     * @since 3.10
2279     */
2280    public static BitSet indexesOf(final Object[] array, final Object objectToFind) {
2281        return indexesOf(array, objectToFind, 0);
2282    }
2283
2284    /**
2285     * Finds the indices of the given object in the array starting at the given index.
2286     *
2287     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2288     *
2289     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2290     * length will return an empty BitSet.</p>
2291     *
2292     * @param array  the array to search for the object, may be {@code null}.
2293     * @param objectToFind  the object to find, may be {@code null}.
2294     * @param startIndex  the index to start searching at
2295     * @return a BitSet of all the indices of the object within the array starting at the index,
2296     *  an empty BitSet if not found or {@code null} array input
2297     * @since 3.10
2298     */
2299    public static BitSet indexesOf(final Object[] array, final Object objectToFind, int startIndex) {
2300        final BitSet bitSet = new BitSet();
2301        if (array == null) {
2302            return bitSet;
2303        }
2304        while (startIndex < array.length) {
2305            startIndex = indexOf(array, objectToFind, startIndex);
2306            if (startIndex == INDEX_NOT_FOUND) {
2307                break;
2308            }
2309            bitSet.set(startIndex);
2310            ++startIndex;
2311        }
2312        return bitSet;
2313    }
2314
2315    /**
2316     * Finds the indices of the given value in the array.
2317     *
2318     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2319     *
2320     * @param array  the array to search for the object, may be {@code null}
2321     * @param valueToFind  the value to find
2322     * @return a BitSet of all the indices of the value within the array,
2323     *  an empty BitSet if not found or {@code null} array input
2324     * @since 3.10
2325     */
2326    public static BitSet indexesOf(final short[] array, final short valueToFind) {
2327        return indexesOf(array, valueToFind, 0);
2328    }
2329
2330    /**
2331     * Finds the indices of the given value in the array starting at the given index.
2332     *
2333     * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2334     *
2335     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2336     * length will return an empty BitSet.</p>
2337     *
2338     * @param array  the array to search for the object, may be {@code null}
2339     * @param valueToFind  the value to find
2340     * @param startIndex  the index to start searching at
2341     * @return a BitSet of all the indices of the value within the array,
2342     *  an empty BitSet if not found or {@code null} array input
2343     * @since 3.10
2344     */
2345    public static BitSet indexesOf(final short[] array, final short valueToFind, int startIndex) {
2346        final BitSet bitSet = new BitSet();
2347        if (array == null) {
2348            return bitSet;
2349        }
2350        while (startIndex < array.length) {
2351            startIndex = indexOf(array, valueToFind, startIndex);
2352            if (startIndex == INDEX_NOT_FOUND) {
2353                break;
2354            }
2355            bitSet.set(startIndex);
2356            ++startIndex;
2357        }
2358        return bitSet;
2359    }
2360
2361    /**
2362     * Finds the index of the given value in the array.
2363     * <p>
2364     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2365     * </p>
2366     *
2367     * @param array  the array to search for the object, may be {@code null}
2368     * @param valueToFind  the value to find
2369     * @return the index of the value within the array,
2370     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2371     */
2372    public static int indexOf(final boolean[] array, final boolean valueToFind) {
2373        return indexOf(array, valueToFind, 0);
2374    }
2375
2376    /**
2377     * Finds the index of the given value in the array starting at the given index.
2378     * <p>
2379     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2380     * </p>
2381     * <p>
2382     * A negative startIndex is treated as zero. A startIndex larger than the array
2383     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2384     * </p>
2385     *
2386     * @param array  the array to search for the object, may be {@code null}
2387     * @param valueToFind  the value to find
2388     * @param startIndex  the index to start searching at
2389     * @return the index of the value within the array,
2390     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null}
2391     *  array input
2392     */
2393    public static int indexOf(final boolean[] array, final boolean valueToFind, final int startIndex) {
2394        if (isEmpty(array)) {
2395            return INDEX_NOT_FOUND;
2396        }
2397        for (int i = max0(startIndex); i < array.length; i++) {
2398            if (valueToFind == array[i]) {
2399                return i;
2400            }
2401        }
2402        return INDEX_NOT_FOUND;
2403    }
2404
2405    /**
2406     * Finds the index of the given value in the array.
2407     * <p>
2408     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2409     * </p>
2410     *
2411     * @param array  the array to search for the object, may be {@code null}
2412     * @param valueToFind  the value to find
2413     * @return the index of the value within the array,
2414     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2415     */
2416    public static int indexOf(final byte[] array, final byte valueToFind) {
2417        return indexOf(array, valueToFind, 0);
2418    }
2419
2420    /**
2421     * Finds the index of the given value in the array starting at the given index.
2422     * <p>
2423     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2424     * </p>
2425     * <p>
2426     * A negative startIndex is treated as zero. A startIndex larger than the array
2427     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2428     * </p>
2429     *
2430     * @param array  the array to search for the object, may be {@code null}
2431     * @param valueToFind  the value to find
2432     * @param startIndex  the index to start searching at
2433     * @return the index of the value within the array,
2434     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2435     */
2436    public static int indexOf(final byte[] array, final byte valueToFind, final int startIndex) {
2437        if (array == null) {
2438            return INDEX_NOT_FOUND;
2439        }
2440        for (int i = max0(startIndex); i < array.length; i++) {
2441            if (valueToFind == array[i]) {
2442                return i;
2443            }
2444        }
2445        return INDEX_NOT_FOUND;
2446    }
2447
2448    /**
2449     * Finds the index of the given value in the array.
2450     * <p>
2451     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2452     * </p>
2453     *
2454     * @param array  the array to search for the object, may be {@code null}
2455     * @param valueToFind  the value to find
2456     * @return the index of the value within the array,
2457     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2458     * @since 2.1
2459     */
2460    public static int indexOf(final char[] array, final char valueToFind) {
2461        return indexOf(array, valueToFind, 0);
2462    }
2463
2464    /**
2465     * Finds the index of the given value in the array starting at the given index.
2466     * <p>
2467     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2468     * </p>
2469     * <p>
2470     * A negative startIndex is treated as zero. A startIndex larger than the array
2471     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2472     * </p>
2473     *
2474     * @param array  the array to search for the object, may be {@code null}
2475     * @param valueToFind  the value to find
2476     * @param startIndex  the index to start searching at
2477     * @return the index of the value within the array,
2478     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2479     * @since 2.1
2480     */
2481    public static int indexOf(final char[] array, final char valueToFind, final int startIndex) {
2482        if (array == null) {
2483            return INDEX_NOT_FOUND;
2484        }
2485        for (int i = max0(startIndex); i < array.length; i++) {
2486            if (valueToFind == array[i]) {
2487                return i;
2488            }
2489        }
2490        return INDEX_NOT_FOUND;
2491    }
2492
2493    /**
2494     * Finds the index of the given value in the array.
2495     * <p>
2496     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2497     * </p>
2498     *
2499     * @param array  the array to search for the object, may be {@code null}
2500     * @param valueToFind  the value to find
2501     * @return the index of the value within the array,
2502     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2503     */
2504    public static int indexOf(final double[] array, final double valueToFind) {
2505        return indexOf(array, valueToFind, 0);
2506    }
2507
2508    /**
2509     * Finds the index of the given value within a given tolerance in the array.
2510     * This method will return the index of the first value which falls between the region
2511     * defined by valueToFind - tolerance and valueToFind + tolerance.
2512     * <p>
2513     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2514     * </p>
2515     *
2516     * @param array  the array to search for the object, may be {@code null}
2517     * @param valueToFind  the value to find
2518     * @param tolerance tolerance of the search
2519     * @return the index of the value within the array,
2520     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2521     */
2522    public static int indexOf(final double[] array, final double valueToFind, final double tolerance) {
2523        return indexOf(array, valueToFind, 0, tolerance);
2524    }
2525
2526    /**
2527     * Finds the index of the given value in the array starting at the given index.
2528     * <p>
2529     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2530     * </p>
2531     * <p>
2532     * A negative startIndex is treated as zero. A startIndex larger than the array
2533     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2534     * </p>
2535     *
2536     * @param array  the array to search for the object, may be {@code null}
2537     * @param valueToFind  the value to find
2538     * @param startIndex  the index to start searching at
2539     * @return the index of the value within the array,
2540     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2541     */
2542    public static int indexOf(final double[] array, final double valueToFind, final int startIndex) {
2543        if (isEmpty(array)) {
2544            return INDEX_NOT_FOUND;
2545        }
2546        final boolean searchNaN = Double.isNaN(valueToFind);
2547        for (int i = max0(startIndex); i < array.length; i++) {
2548            final double element = array[i];
2549            if (valueToFind == element || searchNaN && Double.isNaN(element)) {
2550                return i;
2551            }
2552        }
2553        return INDEX_NOT_FOUND;
2554    }
2555
2556    /**
2557     * Finds the index of the given value in the array starting at the given index.
2558     * This method will return the index of the first value which falls between the region
2559     * defined by valueToFind - tolerance and valueToFind + tolerance.
2560     * <p>
2561     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2562     * </p>
2563     * <p>
2564     * A negative startIndex is treated as zero. A startIndex larger than the array
2565     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2566     * </p>
2567     *
2568     * @param array  the array to search for the object, may be {@code null}
2569     * @param valueToFind  the value to find
2570     * @param startIndex  the index to start searching at
2571     * @param tolerance tolerance of the search
2572     * @return the index of the value within the array,
2573     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2574     */
2575    public static int indexOf(final double[] array, final double valueToFind, final int startIndex, final double tolerance) {
2576        if (isEmpty(array)) {
2577            return INDEX_NOT_FOUND;
2578        }
2579        final double min = valueToFind - tolerance;
2580        final double max = valueToFind + tolerance;
2581        for (int i = max0(startIndex); i < array.length; i++) {
2582            if (array[i] >= min && array[i] <= max) {
2583                return i;
2584            }
2585        }
2586        return INDEX_NOT_FOUND;
2587    }
2588
2589    /**
2590     * Finds the index of the given value in the array.
2591     * <p>
2592     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2593     * </p>
2594     *
2595     * @param array  the array to search for the object, may be {@code null}
2596     * @param valueToFind  the value to find
2597     * @return the index of the value within the array,
2598     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2599     */
2600    public static int indexOf(final float[] array, final float valueToFind) {
2601        return indexOf(array, valueToFind, 0);
2602    }
2603
2604    /**
2605     * Finds the index of the given value in the array starting at the given index.
2606     * <p>
2607     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2608     * </p>
2609     * <p>
2610     * A negative startIndex is treated as zero. A startIndex larger than the array
2611     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2612     * </p>
2613     *
2614     * @param array  the array to search for the object, may be {@code null}
2615     * @param valueToFind  the value to find
2616     * @param startIndex  the index to start searching at
2617     * @return the index of the value within the array,
2618     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2619     */
2620    public static int indexOf(final float[] array, final float valueToFind, final int startIndex) {
2621        if (isEmpty(array)) {
2622            return INDEX_NOT_FOUND;
2623        }
2624        final boolean searchNaN = Float.isNaN(valueToFind);
2625        for (int i = max0(startIndex); i < array.length; i++) {
2626            final float element = array[i];
2627            if (valueToFind == element || searchNaN && Float.isNaN(element)) {
2628                return i;
2629            }
2630        }
2631        return INDEX_NOT_FOUND;
2632    }
2633
2634    /**
2635     * Finds the index of the given value in the array.
2636     * <p>
2637     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2638     * </p>
2639     *
2640     * @param array  the array to search for the object, may be {@code null}
2641     * @param valueToFind  the value to find
2642     * @return the index of the value within the array,
2643     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2644     */
2645    public static int indexOf(final int[] array, final int valueToFind) {
2646        return indexOf(array, valueToFind, 0);
2647    }
2648
2649    /**
2650     * Finds the index of the given value in the array starting at the given index.
2651     * <p>
2652     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2653     * </p>
2654     * <p>
2655     * A negative startIndex is treated as zero. A startIndex larger than the array
2656     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2657     * </p>
2658     *
2659     * @param array  the array to search for the object, may be {@code null}
2660     * @param valueToFind  the value to find
2661     * @param startIndex  the index to start searching at
2662     * @return the index of the value within the array,
2663     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2664     */
2665    public static int indexOf(final int[] array, final int valueToFind, final int startIndex) {
2666        if (array == null) {
2667            return INDEX_NOT_FOUND;
2668        }
2669        for (int i = max0(startIndex); i < array.length; i++) {
2670            if (valueToFind == array[i]) {
2671                return i;
2672            }
2673        }
2674        return INDEX_NOT_FOUND;
2675    }
2676
2677    /**
2678     * Finds the index of the given value in the array.
2679     * <p>
2680     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2681     * </p>
2682     *
2683     * @param array the array to search for the object, may be {@code null}
2684     * @param valueToFind the value to find
2685     * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null}
2686     *         array input
2687     */
2688    public static int indexOf(final long[] array, final long valueToFind) {
2689        return indexOf(array, valueToFind, 0);
2690    }
2691
2692    /**
2693     * Finds the index of the given value in the array starting at the given index.
2694     * <p>
2695     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2696     * </p>
2697     * <p>
2698     * A negative startIndex is treated as zero. A startIndex larger than the array
2699     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2700     * </p>
2701     *
2702     * @param array  the array to search for the object, may be {@code null}
2703     * @param valueToFind  the value to find
2704     * @param startIndex  the index to start searching at
2705     * @return the index of the value within the array,
2706     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2707     */
2708    public static int indexOf(final long[] array, final long valueToFind, final int startIndex) {
2709        if (array == null) {
2710            return INDEX_NOT_FOUND;
2711        }
2712        for (int i = max0(startIndex); i < array.length; i++) {
2713            if (valueToFind == array[i]) {
2714                return i;
2715            }
2716        }
2717        return INDEX_NOT_FOUND;
2718    }
2719
2720    /**
2721     * Finds the index of the given object in the array.
2722     * <p>
2723     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2724     * </p>
2725     *
2726     * @param array  the array to search for the object, may be {@code null}.
2727     * @param objectToFind  the object to find, may be {@code null}.
2728     * @return the index of the object within the array,
2729     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2730     */
2731    public static int indexOf(final Object[] array, final Object objectToFind) {
2732        return indexOf(array, objectToFind, 0);
2733    }
2734
2735    /**
2736     * Finds the index of the given object in the array starting at the given index.
2737     * <p>
2738     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2739     * </p>
2740     * <p>
2741     * A negative startIndex is treated as zero. A startIndex larger than the array
2742     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2743     * </p>
2744     *
2745     * @param array  the array to search for the object, may be {@code null}.
2746     * @param objectToFind  the object to find, may be {@code null}.
2747     * @param startIndex  the index to start searching at
2748     * @return the index of the object within the array starting at the index,
2749     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2750     */
2751    public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
2752        if (array == null) {
2753            return INDEX_NOT_FOUND;
2754        }
2755        startIndex = max0(startIndex);
2756        if (objectToFind == null) {
2757            for (int i = startIndex; i < array.length; i++) {
2758                if (array[i] == null) {
2759                    return i;
2760                }
2761            }
2762        } else {
2763            for (int i = startIndex; i < array.length; i++) {
2764                if (objectToFind.equals(array[i])) {
2765                    return i;
2766                }
2767            }
2768        }
2769        return INDEX_NOT_FOUND;
2770    }
2771
2772    /**
2773     * Finds the index of the given value in the array.
2774     * <p>
2775     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2776     * </p>
2777     *
2778     * @param array  the array to search for the object, may be {@code null}
2779     * @param valueToFind  the value to find
2780     * @return the index of the value within the array,
2781     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2782     */
2783    public static int indexOf(final short[] array, final short valueToFind) {
2784        return indexOf(array, valueToFind, 0);
2785    }
2786
2787    /**
2788     * Finds the index of the given value in the array starting at the given index.
2789     * <p>
2790     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2791     * </p>
2792     * <p>
2793     * A negative startIndex is treated as zero. A startIndex larger than the array
2794     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2795     * </p>
2796     *
2797     * @param array  the array to search for the object, may be {@code null}
2798     * @param valueToFind  the value to find
2799     * @param startIndex  the index to start searching at
2800     * @return the index of the value within the array,
2801     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2802     */
2803    public static int indexOf(final short[] array, final short valueToFind, final int startIndex) {
2804        if (array == null) {
2805            return INDEX_NOT_FOUND;
2806        }
2807        for (int i = max0(startIndex); i < array.length; i++) {
2808            if (valueToFind == array[i]) {
2809                return i;
2810            }
2811        }
2812        return INDEX_NOT_FOUND;
2813    }
2814
2815    /**
2816     * Inserts elements into an array at the given index (starting from zero).
2817     *
2818     * <p>When an array is returned, it is always a new array.</p>
2819     *
2820     * <pre>
2821     * ArrayUtils.insert(index, null, null)      = null
2822     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
2823     * ArrayUtils.insert(index, null, values)    = null
2824     * </pre>
2825     *
2826     * @param index the position within {@code array} to insert the new values
2827     * @param array the array to insert the values into, may be {@code null}
2828     * @param values the new values to insert, may be {@code null}
2829     * @return The new array or {@code null} if the given array is {@code null}.
2830     * @throws IndexOutOfBoundsException if {@code array} is provided
2831     * and either {@code index < 0} or {@code index > array.length}
2832     * @since 3.6
2833     */
2834    public static boolean[] insert(final int index, final boolean[] array, final boolean... values) {
2835        if (array == null) {
2836            return null;
2837        }
2838        if (isEmpty(values)) {
2839            return clone(array);
2840        }
2841        if (index < 0 || index > array.length) {
2842            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
2843        }
2844        final boolean[] result = new boolean[array.length + values.length];
2845        System.arraycopy(values, 0, result, index, values.length);
2846        if (index > 0) {
2847            System.arraycopy(array, 0, result, 0, index);
2848        }
2849        if (index < array.length) {
2850            System.arraycopy(array, index, result, index + values.length, array.length - index);
2851        }
2852        return result;
2853    }
2854
2855    /**
2856     * Inserts elements into an array at the given index (starting from zero).
2857     *
2858     * <p>When an array is returned, it is always a new array.</p>
2859     *
2860     * <pre>
2861     * ArrayUtils.insert(index, null, null)      = null
2862     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
2863     * ArrayUtils.insert(index, null, values)    = null
2864     * </pre>
2865     *
2866     * @param index the position within {@code array} to insert the new values
2867     * @param array the array to insert the values into, may be {@code null}
2868     * @param values the new values to insert, may be {@code null}
2869     * @return The new array or {@code null} if the given array is {@code null}.
2870     * @throws IndexOutOfBoundsException if {@code array} is provided
2871     * and either {@code index < 0} or {@code index > array.length}
2872     * @since 3.6
2873     */
2874    public static byte[] insert(final int index, final byte[] array, final byte... values) {
2875        if (array == null) {
2876            return null;
2877        }
2878        if (isEmpty(values)) {
2879            return clone(array);
2880        }
2881        if (index < 0 || index > array.length) {
2882            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
2883        }
2884        final byte[] result = new byte[array.length + values.length];
2885        System.arraycopy(values, 0, result, index, values.length);
2886        if (index > 0) {
2887            System.arraycopy(array, 0, result, 0, index);
2888        }
2889        if (index < array.length) {
2890            System.arraycopy(array, index, result, index + values.length, array.length - index);
2891        }
2892        return result;
2893    }
2894
2895    /**
2896     * Inserts elements into an array at the given index (starting from zero).
2897     *
2898     * <p>When an array is returned, it is always a new array.</p>
2899     *
2900     * <pre>
2901     * ArrayUtils.insert(index, null, null)      = null
2902     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
2903     * ArrayUtils.insert(index, null, values)    = null
2904     * </pre>
2905     *
2906     * @param index the position within {@code array} to insert the new values
2907     * @param array the array to insert the values into, may be {@code null}
2908     * @param values the new values to insert, may be {@code null}
2909     * @return The new array or {@code null} if the given array is {@code null}.
2910     * @throws IndexOutOfBoundsException if {@code array} is provided
2911     * and either {@code index < 0} or {@code index > array.length}
2912     * @since 3.6
2913     */
2914    public static char[] insert(final int index, final char[] array, final char... values) {
2915        if (array == null) {
2916            return null;
2917        }
2918        if (isEmpty(values)) {
2919            return clone(array);
2920        }
2921        if (index < 0 || index > array.length) {
2922            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
2923        }
2924        final char[] result = new char[array.length + values.length];
2925        System.arraycopy(values, 0, result, index, values.length);
2926        if (index > 0) {
2927            System.arraycopy(array, 0, result, 0, index);
2928        }
2929        if (index < array.length) {
2930            System.arraycopy(array, index, result, index + values.length, array.length - index);
2931        }
2932        return result;
2933    }
2934
2935    /**
2936     * Inserts elements into an array at the given index (starting from zero).
2937     *
2938     * <p>When an array is returned, it is always a new array.</p>
2939     *
2940     * <pre>
2941     * ArrayUtils.insert(index, null, null)      = null
2942     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
2943     * ArrayUtils.insert(index, null, values)    = null
2944     * </pre>
2945     *
2946     * @param index the position within {@code array} to insert the new values
2947     * @param array the array to insert the values into, may be {@code null}
2948     * @param values the new values to insert, may be {@code null}
2949     * @return The new array or {@code null} if the given array is {@code null}.
2950     * @throws IndexOutOfBoundsException if {@code array} is provided
2951     * and either {@code index < 0} or {@code index > array.length}
2952     * @since 3.6
2953     */
2954    public static double[] insert(final int index, final double[] array, final double... values) {
2955        if (array == null) {
2956            return null;
2957        }
2958        if (isEmpty(values)) {
2959            return clone(array);
2960        }
2961        if (index < 0 || index > array.length) {
2962            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
2963        }
2964        final double[] result = new double[array.length + values.length];
2965        System.arraycopy(values, 0, result, index, values.length);
2966        if (index > 0) {
2967            System.arraycopy(array, 0, result, 0, index);
2968        }
2969        if (index < array.length) {
2970            System.arraycopy(array, index, result, index + values.length, array.length - index);
2971        }
2972        return result;
2973    }
2974
2975    /**
2976     * Inserts elements into an array at the given index (starting from zero).
2977     *
2978     * <p>When an array is returned, it is always a new array.</p>
2979     *
2980     * <pre>
2981     * ArrayUtils.insert(index, null, null)      = null
2982     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
2983     * ArrayUtils.insert(index, null, values)    = null
2984     * </pre>
2985     *
2986     * @param index the position within {@code array} to insert the new values
2987     * @param array the array to insert the values into, may be {@code null}
2988     * @param values the new values to insert, may be {@code null}
2989     * @return The new array or {@code null} if the given array is {@code null}.
2990     * @throws IndexOutOfBoundsException if {@code array} is provided
2991     * and either {@code index < 0} or {@code index > array.length}
2992     * @since 3.6
2993     */
2994    public static float[] insert(final int index, final float[] array, final float... values) {
2995        if (array == null) {
2996            return null;
2997        }
2998        if (isEmpty(values)) {
2999            return clone(array);
3000        }
3001        if (index < 0 || index > array.length) {
3002            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3003        }
3004        final float[] result = new float[array.length + values.length];
3005        System.arraycopy(values, 0, result, index, values.length);
3006        if (index > 0) {
3007            System.arraycopy(array, 0, result, 0, index);
3008        }
3009        if (index < array.length) {
3010            System.arraycopy(array, index, result, index + values.length, array.length - index);
3011        }
3012        return result;
3013    }
3014
3015    /**
3016     * Inserts elements into an array at the given index (starting from zero).
3017     *
3018     * <p>When an array is returned, it is always a new array.</p>
3019     *
3020     * <pre>
3021     * ArrayUtils.insert(index, null, null)      = null
3022     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3023     * ArrayUtils.insert(index, null, values)    = null
3024     * </pre>
3025     *
3026     * @param index the position within {@code array} to insert the new values
3027     * @param array the array to insert the values into, may be {@code null}
3028     * @param values the new values to insert, may be {@code null}
3029     * @return The new array or {@code null} if the given array is {@code null}.
3030     * @throws IndexOutOfBoundsException if {@code array} is provided
3031     * and either {@code index < 0} or {@code index > array.length}
3032     * @since 3.6
3033     */
3034    public static int[] insert(final int index, final int[] array, final int... values) {
3035        if (array == null) {
3036            return null;
3037        }
3038        if (isEmpty(values)) {
3039            return clone(array);
3040        }
3041        if (index < 0 || index > array.length) {
3042            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3043        }
3044        final int[] result = new int[array.length + values.length];
3045        System.arraycopy(values, 0, result, index, values.length);
3046        if (index > 0) {
3047            System.arraycopy(array, 0, result, 0, index);
3048        }
3049        if (index < array.length) {
3050            System.arraycopy(array, index, result, index + values.length, array.length - index);
3051        }
3052        return result;
3053    }
3054
3055    /**
3056     * Inserts elements into an array at the given index (starting from zero).
3057     *
3058     * <p>When an array is returned, it is always a new array.</p>
3059     *
3060     * <pre>
3061     * ArrayUtils.insert(index, null, null)      = null
3062     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3063     * ArrayUtils.insert(index, null, values)    = null
3064     * </pre>
3065     *
3066     * @param index the position within {@code array} to insert the new values
3067     * @param array the array to insert the values into, may be {@code null}
3068     * @param values the new values to insert, may be {@code null}
3069     * @return The new array or {@code null} if the given array is {@code null}.
3070     * @throws IndexOutOfBoundsException if {@code array} is provided
3071     * and either {@code index < 0} or {@code index > array.length}
3072     * @since 3.6
3073     */
3074    public static long[] insert(final int index, final long[] array, final long... values) {
3075        if (array == null) {
3076            return null;
3077        }
3078        if (isEmpty(values)) {
3079            return clone(array);
3080        }
3081        if (index < 0 || index > array.length) {
3082            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3083        }
3084        final long[] result = new long[array.length + values.length];
3085        System.arraycopy(values, 0, result, index, values.length);
3086        if (index > 0) {
3087            System.arraycopy(array, 0, result, 0, index);
3088        }
3089        if (index < array.length) {
3090            System.arraycopy(array, index, result, index + values.length, array.length - index);
3091        }
3092        return result;
3093    }
3094
3095    /**
3096     * Inserts elements into an array at the given index (starting from zero).
3097     *
3098     * <p>When an array is returned, it is always a new array.</p>
3099     *
3100     * <pre>
3101     * ArrayUtils.insert(index, null, null)      = null
3102     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3103     * ArrayUtils.insert(index, null, values)    = null
3104     * </pre>
3105     *
3106     * @param index the position within {@code array} to insert the new values
3107     * @param array the array to insert the values into, may be {@code null}
3108     * @param values the new values to insert, may be {@code null}
3109     * @return The new array or {@code null} if the given array is {@code null}.
3110     * @throws IndexOutOfBoundsException if {@code array} is provided
3111     * and either {@code index < 0} or {@code index > array.length}
3112     * @since 3.6
3113     */
3114    public static short[] insert(final int index, final short[] array, final short... values) {
3115        if (array == null) {
3116            return null;
3117        }
3118        if (isEmpty(values)) {
3119            return clone(array);
3120        }
3121        if (index < 0 || index > array.length) {
3122            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3123        }
3124        final short[] result = new short[array.length + values.length];
3125        System.arraycopy(values, 0, result, index, values.length);
3126        if (index > 0) {
3127            System.arraycopy(array, 0, result, 0, index);
3128        }
3129        if (index < array.length) {
3130            System.arraycopy(array, index, result, index + values.length, array.length - index);
3131        }
3132        return result;
3133    }
3134
3135    /**
3136     * Inserts elements into an array at the given index (starting from zero).
3137     *
3138     * <p>When an array is returned, it is always a new array.</p>
3139     *
3140     * <pre>
3141     * ArrayUtils.insert(index, null, null)      = null
3142     * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3143     * ArrayUtils.insert(index, null, values)    = null
3144     * </pre>
3145     *
3146     * @param <T> The type of elements in {@code array} and {@code values}
3147     * @param index the position within {@code array} to insert the new values
3148     * @param array the array to insert the values into, may be {@code null}
3149     * @param values the new values to insert, may be {@code null}
3150     * @return The new array or {@code null} if the given array is {@code null}.
3151     * @throws IndexOutOfBoundsException if {@code array} is provided
3152     * and either {@code index < 0} or {@code index > array.length}
3153     * @since 3.6
3154     */
3155    @SafeVarargs
3156    public static <T> T[] insert(final int index, final T[] array, final T... values) {
3157        /*
3158         * Note on use of @SafeVarargs:
3159         *
3160         * By returning null when 'array' is null, we avoid returning the vararg
3161         * array to the caller. We also avoid relying on the type of the vararg
3162         * array, by inspecting the component type of 'array'.
3163         */
3164        if (array == null) {
3165            return null;
3166        }
3167        if (isEmpty(values)) {
3168            return clone(array);
3169        }
3170        if (index < 0 || index > array.length) {
3171            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3172        }
3173        final Class<T> type = getComponentType(array);
3174        final int length = array.length + values.length;
3175        final T[] result = newInstance(type, length);
3176        System.arraycopy(values, 0, result, index, values.length);
3177        if (index > 0) {
3178            System.arraycopy(array, 0, result, 0, index);
3179        }
3180        if (index < array.length) {
3181            System.arraycopy(array, index, result, index + values.length, array.length - index);
3182        }
3183        return result;
3184    }
3185
3186    /**
3187     * Checks if an array is empty or {@code null}.
3188     *
3189     * @param array the array to test
3190     * @return {@code true} if the array is empty or {@code null}
3191     */
3192    private static boolean isArrayEmpty(final Object array) {
3193        return getLength(array) == 0;
3194    }
3195
3196    /**
3197     * Tests whether a given array can safely be accessed at the given index.
3198     *
3199     * <pre>
3200     * ArrayUtils.isArrayIndexValid(null, 0)       = false
3201     * ArrayUtils.isArrayIndexValid([], 0)         = false
3202     * ArrayUtils.isArrayIndexValid(["a"], 0)      = true
3203     * </pre>
3204     *
3205     * @param <T> the component type of the array
3206     * @param array the array to inspect, may be {@code null}.
3207     * @param index the index of the array to be inspected
3208     * @return Whether the given index is safely-accessible in the given array
3209     * @since 3.8
3210     */
3211    public static <T> boolean isArrayIndexValid(final T[] array, final int index) {
3212        return index >= 0 && getLength(array) > index;
3213    }
3214
3215    /**
3216     * Tests whether an array of primitive booleans is empty or {@code null}.
3217     *
3218     * @param array  the array to test
3219     * @return {@code true} if the array is empty or {@code null}
3220     * @since 2.1
3221     */
3222    public static boolean isEmpty(final boolean[] array) {
3223        return isArrayEmpty(array);
3224    }
3225
3226    /**
3227     * Tests whether an array of primitive bytes is empty or {@code null}.
3228     *
3229     * @param array  the array to test
3230     * @return {@code true} if the array is empty or {@code null}
3231     * @since 2.1
3232     */
3233    public static boolean isEmpty(final byte[] array) {
3234        return isArrayEmpty(array);
3235    }
3236
3237    /**
3238     * Tests whether an array of primitive chars is empty or {@code null}.
3239     *
3240     * @param array  the array to test
3241     * @return {@code true} if the array is empty or {@code null}
3242     * @since 2.1
3243     */
3244    public static boolean isEmpty(final char[] array) {
3245        return isArrayEmpty(array);
3246    }
3247
3248    /**
3249     * Tests whether an array of primitive doubles is empty or {@code null}.
3250     *
3251     * @param array  the array to test
3252     * @return {@code true} if the array is empty or {@code null}
3253     * @since 2.1
3254     */
3255    public static boolean isEmpty(final double[] array) {
3256        return isArrayEmpty(array);
3257    }
3258
3259    /**
3260     * Tests whether an array of primitive floats is empty or {@code null}.
3261     *
3262     * @param array  the array to test
3263     * @return {@code true} if the array is empty or {@code null}
3264     * @since 2.1
3265     */
3266    public static boolean isEmpty(final float[] array) {
3267        return isArrayEmpty(array);
3268    }
3269
3270    /**
3271     * Tests whether an array of primitive ints is empty or {@code null}.
3272     *
3273     * @param array  the array to test
3274     * @return {@code true} if the array is empty or {@code null}
3275     * @since 2.1
3276     */
3277    public static boolean isEmpty(final int[] array) {
3278        return isArrayEmpty(array);
3279    }
3280
3281    /**
3282     * Tests whether an array of primitive longs is empty or {@code null}.
3283     *
3284     * @param array  the array to test
3285     * @return {@code true} if the array is empty or {@code null}
3286     * @since 2.1
3287     */
3288    public static boolean isEmpty(final long[] array) {
3289        return isArrayEmpty(array);
3290    }
3291
3292    /**
3293     * Tests whether an array of Objects is empty or {@code null}.
3294     *
3295     * @param array  the array to test
3296     * @return {@code true} if the array is empty or {@code null}
3297     * @since 2.1
3298     */
3299    public static boolean isEmpty(final Object[] array) {
3300        return isArrayEmpty(array);
3301    }
3302
3303    /**
3304     * Tests whether an array of primitive shorts is empty or {@code null}.
3305     *
3306     * @param array  the array to test
3307     * @return {@code true} if the array is empty or {@code null}
3308     * @since 2.1
3309     */
3310    public static boolean isEmpty(final short[] array) {
3311        return isArrayEmpty(array);
3312    }
3313
3314    /**
3315     * Tests whether two arrays have equal content, using equals(), handling multidimensional arrays
3316     * correctly.
3317     * <p>
3318     * Multi-dimensional primitive arrays are also handled correctly by this method.
3319     * </p>
3320     *
3321     * @param array1  the left-hand side array to compare, may be {@code null}
3322     * @param array2  the right-hand side array to compare, may be {@code null}
3323     * @return {@code true} if the arrays are equal
3324     * @deprecated this method has been replaced by {@code java.util.Objects.deepEquals(Object, Object)} and will be
3325     * removed from future releases.
3326     */
3327    @Deprecated
3328    public static boolean isEquals(final Object array1, final Object array2) {
3329        return new EqualsBuilder().append(array1, array2).isEquals();
3330    }
3331
3332    /**
3333     * Tests whether an array of primitive booleans is not empty and not {@code null}.
3334     *
3335     * @param array  the array to test
3336     * @return {@code true} if the array is not empty and not {@code null}
3337     * @since 2.5
3338     */
3339    public static boolean isNotEmpty(final boolean[] array) {
3340        return !isEmpty(array);
3341    }
3342
3343    /**
3344     * Tests whether an array of primitive bytes is not empty and not {@code null}.
3345     *
3346     * @param array  the array to test
3347     * @return {@code true} if the array is not empty and not {@code null}
3348     * @since 2.5
3349     */
3350    public static boolean isNotEmpty(final byte[] array) {
3351        return !isEmpty(array);
3352    }
3353
3354    /**
3355     * Tests whether an array of primitive chars is not empty and not {@code null}.
3356     *
3357     * @param array  the array to test
3358     * @return {@code true} if the array is not empty and not {@code null}
3359     * @since 2.5
3360     */
3361    public static boolean isNotEmpty(final char[] array) {
3362        return !isEmpty(array);
3363    }
3364
3365    /**
3366     * Tests whether an array of primitive doubles is not empty and not {@code null}.
3367     *
3368     * @param array  the array to test
3369     * @return {@code true} if the array is not empty and not {@code null}
3370     * @since 2.5
3371     */
3372    public static boolean isNotEmpty(final double[] array) {
3373        return !isEmpty(array);
3374    }
3375
3376    /**
3377     * Tests whether an array of primitive floats is not empty and not {@code null}.
3378     *
3379     * @param array  the array to test
3380     * @return {@code true} if the array is not empty and not {@code null}
3381     * @since 2.5
3382     */
3383    public static boolean isNotEmpty(final float[] array) {
3384        return !isEmpty(array);
3385    }
3386
3387    /**
3388     * Tests whether an array of primitive ints is not empty and not {@code null}.
3389     *
3390     * @param array  the array to test
3391     * @return {@code true} if the array is not empty and not {@code null}
3392     * @since 2.5
3393     */
3394    public static boolean isNotEmpty(final int[] array) {
3395        return !isEmpty(array);
3396    }
3397
3398    /**
3399     * Tests whether an array of primitive longs is not empty and not {@code null}.
3400     *
3401     * @param array  the array to test
3402     * @return {@code true} if the array is not empty and not {@code null}
3403     * @since 2.5
3404     */
3405    public static boolean isNotEmpty(final long[] array) {
3406        return !isEmpty(array);
3407    }
3408
3409    /**
3410     * Tests whether an array of primitive shorts is not empty and not {@code null}.
3411     *
3412     * @param array  the array to test
3413     * @return {@code true} if the array is not empty and not {@code null}
3414     * @since 2.5
3415     */
3416    public static boolean isNotEmpty(final short[] array) {
3417        return !isEmpty(array);
3418    }
3419
3420    /**
3421     * Tests whether an array of Objects is not empty and not {@code null}.
3422     *
3423     * @param <T> the component type of the array
3424     * @param array  the array to test
3425     * @return {@code true} if the array is not empty and not {@code null}
3426     * @since 2.5
3427     */
3428     public static <T> boolean isNotEmpty(final T[] array) {
3429         return !isEmpty(array);
3430     }
3431
3432    /**
3433     * Tests whether two arrays are the same length, treating
3434     * {@code null} arrays as length {@code 0}.
3435     *
3436     * @param array1 the first array, may be {@code null}
3437     * @param array2 the second array, may be {@code null}
3438     * @return {@code true} if length of arrays matches, treating
3439     *  {@code null} as an empty array
3440     */
3441    public static boolean isSameLength(final boolean[] array1, final boolean[] array2) {
3442        return getLength(array1) == getLength(array2);
3443    }
3444
3445    /**
3446     * Tests whether two arrays are the same length, treating
3447     * {@code null} arrays as length {@code 0}.
3448     *
3449     * @param array1 the first array, may be {@code null}
3450     * @param array2 the second array, may be {@code null}
3451     * @return {@code true} if length of arrays matches, treating
3452     *  {@code null} as an empty array
3453     */
3454    public static boolean isSameLength(final byte[] array1, final byte[] array2) {
3455        return getLength(array1) == getLength(array2);
3456    }
3457
3458    /**
3459     * Tests whether two arrays are the same length, treating
3460     * {@code null} arrays as length {@code 0}.
3461     *
3462     * @param array1 the first array, may be {@code null}
3463     * @param array2 the second array, may be {@code null}
3464     * @return {@code true} if length of arrays matches, treating
3465     *  {@code null} as an empty array
3466     */
3467    public static boolean isSameLength(final char[] array1, final char[] array2) {
3468        return getLength(array1) == getLength(array2);
3469    }
3470
3471    /**
3472     * Tests whether two arrays are the same length, treating
3473     * {@code null} arrays as length {@code 0}.
3474     *
3475     * @param array1 the first array, may be {@code null}
3476     * @param array2 the second array, may be {@code null}
3477     * @return {@code true} if length of arrays matches, treating
3478     *  {@code null} as an empty array
3479     */
3480    public static boolean isSameLength(final double[] array1, final double[] array2) {
3481        return getLength(array1) == getLength(array2);
3482    }
3483
3484    /**
3485     * Tests whether two arrays are the same length, treating
3486     * {@code null} arrays as length {@code 0}.
3487     *
3488     * @param array1 the first array, may be {@code null}
3489     * @param array2 the second array, may be {@code null}
3490     * @return {@code true} if length of arrays matches, treating
3491     *  {@code null} as an empty array
3492     */
3493    public static boolean isSameLength(final float[] array1, final float[] array2) {
3494        return getLength(array1) == getLength(array2);
3495    }
3496
3497    /**
3498     * Tests whether two arrays are the same length, treating
3499     * {@code null} arrays as length {@code 0}.
3500     *
3501     * @param array1 the first array, may be {@code null}
3502     * @param array2 the second array, may be {@code null}
3503     * @return {@code true} if length of arrays matches, treating
3504     *  {@code null} as an empty array
3505     */
3506    public static boolean isSameLength(final int[] array1, final int[] array2) {
3507        return getLength(array1) == getLength(array2);
3508    }
3509
3510    /**
3511     * Tests whether two arrays are the same length, treating
3512     * {@code null} arrays as length {@code 0}.
3513     *
3514     * @param array1 the first array, may be {@code null}
3515     * @param array2 the second array, may be {@code null}
3516     * @return {@code true} if length of arrays matches, treating
3517     *  {@code null} as an empty array
3518     */
3519    public static boolean isSameLength(final long[] array1, final long[] array2) {
3520        return getLength(array1) == getLength(array2);
3521    }
3522
3523    /**
3524     * Tests whether two arrays are the same length, treating
3525     * {@code null} arrays as length {@code 0}.
3526     * <p>
3527     * Any multi-dimensional aspects of the arrays are ignored.
3528     * </p>
3529     *
3530     * @param array1 the first array, may be {@code null}
3531     * @param array2 the second array, may be {@code null}
3532     * @return {@code true} if length of arrays matches, treating
3533     *  {@code null} as an empty array
3534     * @since 3.11
3535     */
3536    public static boolean isSameLength(final Object array1, final Object array2) {
3537        return getLength(array1) == getLength(array2);
3538    }
3539
3540    /**
3541     * Tests whether two arrays are the same length, treating
3542     * {@code null} arrays as length {@code 0}.
3543     * <p>
3544     * Any multi-dimensional aspects of the arrays are ignored.
3545     * </p>
3546     *
3547     * @param array1 the first array, may be {@code null}
3548     * @param array2 the second array, may be {@code null}
3549     * @return {@code true} if length of arrays matches, treating
3550     *  {@code null} as an empty array
3551     */
3552    public static boolean isSameLength(final Object[] array1, final Object[] array2) {
3553        return getLength(array1) == getLength(array2);
3554    }
3555
3556    /**
3557     * Tests whether two arrays are the same length, treating
3558     * {@code null} arrays as length {@code 0}.
3559     *
3560     * @param array1 the first array, may be {@code null}
3561     * @param array2 the second array, may be {@code null}
3562     * @return {@code true} if length of arrays matches, treating
3563     *  {@code null} as an empty array
3564     */
3565    public static boolean isSameLength(final short[] array1, final short[] array2) {
3566        return getLength(array1) == getLength(array2);
3567    }
3568
3569    /**
3570     * Tests whether two arrays are the same type taking into account
3571     * multidimensional arrays.
3572     *
3573     * @param array1 the first array, must not be {@code null}
3574     * @param array2 the second array, must not be {@code null}
3575     * @return {@code true} if type of arrays matches
3576     * @throws IllegalArgumentException if either array is {@code null}
3577     */
3578    public static boolean isSameType(final Object array1, final Object array2) {
3579        if (array1 == null || array2 == null) {
3580            throw new IllegalArgumentException("The Array must not be null");
3581        }
3582        return array1.getClass().getName().equals(array2.getClass().getName());
3583    }
3584
3585    /**
3586     * Tests whether whether the provided array is sorted according to natural ordering
3587     * ({@code false} before {@code true}).
3588     *
3589     * @param array the array to check
3590     * @return whether the array is sorted according to natural ordering
3591     * @since 3.4
3592     */
3593    public static boolean isSorted(final boolean[] array) {
3594        if (getLength(array) < 2) {
3595            return true;
3596        }
3597        boolean previous = array[0];
3598        final int n = array.length;
3599        for (int i = 1; i < n; i++) {
3600            final boolean current = array[i];
3601            if (BooleanUtils.compare(previous, current) > 0) {
3602                return false;
3603            }
3604            previous = current;
3605        }
3606        return true;
3607    }
3608
3609    /**
3610     * Tests whether the provided array is sorted according to natural ordering.
3611     *
3612     * @param array the array to check
3613     * @return whether the array is sorted according to natural ordering
3614     * @since 3.4
3615     */
3616    public static boolean isSorted(final byte[] array) {
3617        if (getLength(array) < 2) {
3618            return true;
3619        }
3620        byte previous = array[0];
3621        final int n = array.length;
3622        for (int i = 1; i < n; i++) {
3623            final byte current = array[i];
3624            if (Byte.compare(previous, current) > 0) {
3625                return false;
3626            }
3627            previous = current;
3628        }
3629        return true;
3630    }
3631
3632    /**
3633     * Tests whether the provided array is sorted according to natural ordering.
3634     *
3635     * @param array the array to check
3636     * @return whether the array is sorted according to natural ordering
3637     * @since 3.4
3638     */
3639    public static boolean isSorted(final char[] array) {
3640        if (getLength(array) < 2) {
3641            return true;
3642        }
3643        char previous = array[0];
3644        final int n = array.length;
3645        for (int i = 1; i < n; i++) {
3646            final char current = array[i];
3647            if (CharUtils.compare(previous, current) > 0) {
3648                return false;
3649            }
3650            previous = current;
3651        }
3652        return true;
3653    }
3654
3655    /**
3656     * Tests whether the provided array is sorted according to natural ordering.
3657     *
3658     * @param array the array to check
3659     * @return whether the array is sorted according to natural ordering
3660     * @since 3.4
3661     */
3662    public static boolean isSorted(final double[] array) {
3663        if (getLength(array) < 2) {
3664            return true;
3665        }
3666        double previous = array[0];
3667        final int n = array.length;
3668        for (int i = 1; i < n; i++) {
3669            final double current = array[i];
3670            if (Double.compare(previous, current) > 0) {
3671                return false;
3672            }
3673            previous = current;
3674        }
3675        return true;
3676    }
3677
3678    /**
3679     * Tests whether the provided array is sorted according to natural ordering.
3680     *
3681     * @param array the array to check
3682     * @return whether the array is sorted according to natural ordering
3683     * @since 3.4
3684     */
3685    public static boolean isSorted(final float[] array) {
3686        if (getLength(array) < 2) {
3687            return true;
3688        }
3689        float previous = array[0];
3690        final int n = array.length;
3691        for (int i = 1; i < n; i++) {
3692            final float current = array[i];
3693            if (Float.compare(previous, current) > 0) {
3694                return false;
3695            }
3696            previous = current;
3697        }
3698        return true;
3699    }
3700
3701    /**
3702     * Tests whether the provided array is sorted according to natural ordering.
3703     *
3704     * @param array the array to check
3705     * @return whether the array is sorted according to natural ordering
3706     * @since 3.4
3707     */
3708    public static boolean isSorted(final int[] array) {
3709        if (getLength(array) < 2) {
3710            return true;
3711        }
3712        int previous = array[0];
3713        final int n = array.length;
3714        for (int i = 1; i < n; i++) {
3715            final int current = array[i];
3716            if (Integer.compare(previous, current) > 0) {
3717                return false;
3718            }
3719            previous = current;
3720        }
3721        return true;
3722    }
3723
3724    /**
3725     * Tests whether the provided array is sorted according to natural ordering.
3726     *
3727     * @param array the array to check
3728     * @return whether the array is sorted according to natural ordering
3729     * @since 3.4
3730     */
3731    public static boolean isSorted(final long[] array) {
3732        if (getLength(array) < 2) {
3733            return true;
3734        }
3735        long previous = array[0];
3736        final int n = array.length;
3737        for (int i = 1; i < n; i++) {
3738            final long current = array[i];
3739            if (Long.compare(previous, current) > 0) {
3740                return false;
3741            }
3742            previous = current;
3743        }
3744        return true;
3745    }
3746
3747    /**
3748     * Tests whether the provided array is sorted according to natural ordering.
3749     *
3750     * @param array the array to check
3751     * @return whether the array is sorted according to natural ordering
3752     * @since 3.4
3753     */
3754    public static boolean isSorted(final short[] array) {
3755        if (getLength(array) < 2) {
3756            return true;
3757        }
3758        short previous = array[0];
3759        final int n = array.length;
3760        for (int i = 1; i < n; i++) {
3761            final short current = array[i];
3762            if (Short.compare(previous, current) > 0) {
3763                return false;
3764            }
3765            previous = current;
3766        }
3767        return true;
3768    }
3769
3770    /**
3771     * Tests whether the provided array is sorted according to the class's
3772     * {@code compareTo} method.
3773     *
3774     * @param array the array to check
3775     * @param <T> the datatype of the array to check, it must implement {@link Comparable}
3776     * @return whether the array is sorted
3777     * @since 3.4
3778     */
3779    public static <T extends Comparable<? super T>> boolean isSorted(final T[] array) {
3780        return isSorted(array, Comparable::compareTo);
3781    }
3782
3783    /**
3784     * Tests whether the provided array is sorted according to the provided {@link Comparator}.
3785     *
3786     * @param array the array to check
3787     * @param comparator the {@link Comparator} to compare over
3788     * @param <T> the datatype of the array
3789     * @return whether the array is sorted
3790     * @throws NullPointerException if {@code comparator} is {@code null}
3791     * @since 3.4
3792     */
3793    public static <T> boolean isSorted(final T[] array, final Comparator<T> comparator) {
3794        Objects.requireNonNull(comparator, "comparator");
3795        if (getLength(array) < 2) {
3796            return true;
3797        }
3798        T previous = array[0];
3799        final int n = array.length;
3800        for (int i = 1; i < n; i++) {
3801            final T current = array[i];
3802            if (comparator.compare(previous, current) > 0) {
3803                return false;
3804            }
3805            previous = current;
3806        }
3807        return true;
3808    }
3809
3810    /**
3811     * Finds the last index of the given value within the array.
3812     * <p>
3813     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) if
3814     * {@code null} array input.
3815     * </p>
3816     *
3817     * @param array  the array to traverse backwards looking for the object, may be {@code null}
3818     * @param valueToFind  the object to find
3819     * @return the last index of the value within the array,
3820     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3821     */
3822    public static int lastIndexOf(final boolean[] array, final boolean valueToFind) {
3823        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
3824    }
3825
3826    /**
3827     * Finds the last index of the given value in the array starting at the given index.
3828     * <p>
3829     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3830     * </p>
3831     * <p>
3832     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than
3833     * the array length will search from the end of the array.
3834     * </p>
3835     *
3836     * @param array  the array to traverse for looking for the object, may be {@code null}
3837     * @param valueToFind  the value to find
3838     * @param startIndex  the start index to traverse backwards from
3839     * @return the last index of the value within the array,
3840     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3841     */
3842    public static int lastIndexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
3843        if (isEmpty(array) || startIndex < 0) {
3844            return INDEX_NOT_FOUND;
3845        }
3846        if (startIndex >= array.length) {
3847            startIndex = array.length - 1;
3848        }
3849        for (int i = startIndex; i >= 0; i--) {
3850            if (valueToFind == array[i]) {
3851                return i;
3852            }
3853        }
3854        return INDEX_NOT_FOUND;
3855    }
3856
3857    /**
3858     * Finds the last index of the given value within the array.
3859     * <p>
3860     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3861     * </p>
3862     *
3863     * @param array  the array to traverse backwards looking for the object, may be {@code null}
3864     * @param valueToFind  the object to find
3865     * @return the last index of the value within the array,
3866     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3867     */
3868    public static int lastIndexOf(final byte[] array, final byte valueToFind) {
3869        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
3870    }
3871
3872    /**
3873     * Finds the last index of the given value in the array starting at the given index.
3874     * <p>
3875     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3876     * </p>
3877     * <p>
3878     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
3879     * array length will search from the end of the array.
3880     * </p>
3881     *
3882     * @param array  the array to traverse for looking for the object, may be {@code null}
3883     * @param valueToFind  the value to find
3884     * @param startIndex  the start index to traverse backwards from
3885     * @return the last index of the value within the array,
3886     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3887     */
3888    public static int lastIndexOf(final byte[] array, final byte valueToFind, int startIndex) {
3889        if (array == null || startIndex < 0) {
3890            return INDEX_NOT_FOUND;
3891        }
3892        if (startIndex >= array.length) {
3893            startIndex = array.length - 1;
3894        }
3895        for (int i = startIndex; i >= 0; i--) {
3896            if (valueToFind == array[i]) {
3897                return i;
3898            }
3899        }
3900        return INDEX_NOT_FOUND;
3901    }
3902
3903    /**
3904     * Finds the last index of the given value within the array.
3905     * <p>
3906     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3907     * </p>
3908     *
3909     * @param array  the array to traverse backwards looking for the object, may be {@code null}
3910     * @param valueToFind  the object to find
3911     * @return the last index of the value within the array,
3912     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3913     * @since 2.1
3914     */
3915    public static int lastIndexOf(final char[] array, final char valueToFind) {
3916        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
3917    }
3918
3919    /**
3920     * Finds the last index of the given value in the array starting at the given index.
3921     * <p>
3922     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3923     * </p>
3924     * <p>
3925     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
3926     * array length will search from the end of the array.
3927     * </p>
3928     *
3929     * @param array  the array to traverse for looking for the object, may be {@code null}
3930     * @param valueToFind  the value to find
3931     * @param startIndex  the start index to traverse backwards from
3932     * @return the last index of the value within the array,
3933     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3934     * @since 2.1
3935     */
3936    public static int lastIndexOf(final char[] array, final char valueToFind, int startIndex) {
3937        if (array == null || startIndex < 0) {
3938            return INDEX_NOT_FOUND;
3939        }
3940        if (startIndex >= array.length) {
3941            startIndex = array.length - 1;
3942        }
3943        for (int i = startIndex; i >= 0; i--) {
3944            if (valueToFind == array[i]) {
3945                return i;
3946            }
3947        }
3948        return INDEX_NOT_FOUND;
3949    }
3950
3951    /**
3952     * Finds the last index of the given value within the array.
3953     * <p>
3954     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3955     * </p>
3956     *
3957     * @param array  the array to traverse backwards looking for the object, may be {@code null}
3958     * @param valueToFind  the object to find
3959     * @return the last index of the value within the array,
3960     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3961     */
3962    public static int lastIndexOf(final double[] array, final double valueToFind) {
3963        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
3964    }
3965
3966    /**
3967     * Finds the last index of the given value within a given tolerance in the array.
3968     * This method will return the index of the last value which falls between the region
3969     * defined by valueToFind - tolerance and valueToFind + tolerance.
3970     * <p>
3971     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3972     * </p>
3973     *
3974     * @param array  the array to search for the object, may be {@code null}
3975     * @param valueToFind  the value to find
3976     * @param tolerance tolerance of the search
3977     * @return the index of the value within the array,
3978     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3979     */
3980    public static int lastIndexOf(final double[] array, final double valueToFind, final double tolerance) {
3981        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance);
3982    }
3983
3984    /**
3985     * Finds the last index of the given value in the array starting at the given index.
3986     * <p>
3987     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3988     * </p>
3989     * <p>
3990     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
3991     * array length will search from the end of the array.
3992     * </p>
3993     *
3994     * @param array  the array to traverse for looking for the object, may be {@code null}
3995     * @param valueToFind  the value to find
3996     * @param startIndex  the start index to traverse backwards from
3997     * @return the last index of the value within the array,
3998     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3999     */
4000    public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex) {
4001        if (isEmpty(array) || startIndex < 0) {
4002            return INDEX_NOT_FOUND;
4003        }
4004        if (startIndex >= array.length) {
4005            startIndex = array.length - 1;
4006        }
4007        for (int i = startIndex; i >= 0; i--) {
4008            if (valueToFind == array[i]) {
4009                return i;
4010            }
4011        }
4012        return INDEX_NOT_FOUND;
4013    }
4014
4015    /**
4016     * Finds the last index of the given value in the array starting at the given index.
4017     * This method will return the index of the last value which falls between the region
4018     * defined by valueToFind - tolerance and valueToFind + tolerance.
4019     * <p>
4020     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4021     * </p>
4022     * <p>
4023     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
4024     * array length will search from the end of the array.
4025     * </p>
4026     *
4027     * @param array  the array to traverse for looking for the object, may be {@code null}
4028     * @param valueToFind  the value to find
4029     * @param startIndex  the start index to traverse backwards from
4030     * @param tolerance  search for value within plus/minus this amount
4031     * @return the last index of the value within the array,
4032     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4033     */
4034    public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
4035        if (isEmpty(array) || startIndex < 0) {
4036            return INDEX_NOT_FOUND;
4037        }
4038        if (startIndex >= array.length) {
4039            startIndex = array.length - 1;
4040        }
4041        final double min = valueToFind - tolerance;
4042        final double max = valueToFind + tolerance;
4043        for (int i = startIndex; i >= 0; i--) {
4044            if (array[i] >= min && array[i] <= max) {
4045                return i;
4046            }
4047        }
4048        return INDEX_NOT_FOUND;
4049    }
4050
4051    /**
4052     * Finds the last index of the given value within the array.
4053     * <p>
4054     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4055     * </p>
4056     *
4057     * @param array  the array to traverse backwards looking for the object, may be {@code null}
4058     * @param valueToFind  the object to find
4059     * @return the last index of the value within the array,
4060     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4061     */
4062    public static int lastIndexOf(final float[] array, final float valueToFind) {
4063        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4064    }
4065
4066    /**
4067     * Finds the last index of the given value in the array starting at the given index.
4068     * <p>
4069     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4070     * </p>
4071     * <p>
4072     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
4073     * array length will search from the end of the array.
4074     * </p>
4075     *
4076     * @param array  the array to traverse for looking for the object, may be {@code null}
4077     * @param valueToFind  the value to find
4078     * @param startIndex  the start index to traverse backwards from
4079     * @return the last index of the value within the array,
4080     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4081     */
4082    public static int lastIndexOf(final float[] array, final float valueToFind, int startIndex) {
4083        if (isEmpty(array) || startIndex < 0) {
4084            return INDEX_NOT_FOUND;
4085        }
4086        if (startIndex >= array.length) {
4087            startIndex = array.length - 1;
4088        }
4089        for (int i = startIndex; i >= 0; i--) {
4090            if (valueToFind == array[i]) {
4091                return i;
4092            }
4093        }
4094        return INDEX_NOT_FOUND;
4095    }
4096
4097    /**
4098     * Finds the last index of the given value within the array.
4099     * <p>
4100     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4101     * </p>
4102     *
4103     * @param array  the array to traverse backwards looking for the object, may be {@code null}
4104     * @param valueToFind  the object to find
4105     * @return the last index of the value within the array,
4106     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4107     */
4108    public static int lastIndexOf(final int[] array, final int valueToFind) {
4109        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4110    }
4111
4112    /**
4113     * Finds the last index of the given value in the array starting at the given index.
4114     * <p>
4115     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4116     * </p>
4117     * <p>
4118     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
4119     * array length will search from the end of the array.
4120     * </p>
4121     *
4122     * @param array  the array to traverse for looking for the object, may be {@code null}
4123     * @param valueToFind  the value to find
4124     * @param startIndex  the start index to traverse backwards from
4125     * @return the last index of the value within the array,
4126     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4127     */
4128    public static int lastIndexOf(final int[] array, final int valueToFind, int startIndex) {
4129        if (array == null || startIndex < 0) {
4130            return INDEX_NOT_FOUND;
4131        }
4132        if (startIndex >= array.length) {
4133            startIndex = array.length - 1;
4134        }
4135        for (int i = startIndex; i >= 0; i--) {
4136            if (valueToFind == array[i]) {
4137                return i;
4138            }
4139        }
4140        return INDEX_NOT_FOUND;
4141    }
4142
4143    /**
4144     * Finds the last index of the given value within the array.
4145     * <p>
4146     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4147     * </p>
4148     *
4149     * @param array  the array to traverse backwards looking for the object, may be {@code null}
4150     * @param valueToFind  the object to find
4151     * @return the last index of the value within the array,
4152     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4153     */
4154    public static int lastIndexOf(final long[] array, final long valueToFind) {
4155        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4156    }
4157
4158    /**
4159     * Finds the last index of the given value in the array starting at the given index.
4160     * <p>
4161     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4162     * </p>
4163     * <p>
4164     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
4165     * array length will search from the end of the array.
4166     * </p>
4167     *
4168     * @param array  the array to traverse for looking for the object, may be {@code null}
4169     * @param valueToFind  the value to find
4170     * @param startIndex  the start index to traverse backwards from
4171     * @return the last index of the value within the array,
4172     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4173     */
4174    public static int lastIndexOf(final long[] array, final long valueToFind, int startIndex) {
4175        if (array == null || startIndex < 0) {
4176            return INDEX_NOT_FOUND;
4177        }
4178        if (startIndex >= array.length) {
4179            startIndex = array.length - 1;
4180        }
4181        for (int i = startIndex; i >= 0; i--) {
4182            if (valueToFind == array[i]) {
4183                return i;
4184            }
4185        }
4186        return INDEX_NOT_FOUND;
4187    }
4188
4189    /**
4190     * Finds the last index of the given object within the array.
4191     * <p>
4192     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4193     * </p>
4194     *
4195     * @param array  the array to traverse backwards looking for the object, may be {@code null}
4196     * @param objectToFind  the object to find, may be {@code null}
4197     * @return the last index of the object within the array,
4198     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4199     */
4200    public static int lastIndexOf(final Object[] array, final Object objectToFind) {
4201        return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
4202    }
4203
4204    /**
4205     * Finds the last index of the given object in the array starting at the given index.
4206     * <p>
4207     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4208     * </p>
4209     * <p>
4210     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than
4211     * the array length will search from the end of the array.
4212     * </p>
4213     *
4214     * @param array  the array to traverse for looking for the object, may be {@code null}
4215     * @param objectToFind  the object to find, may be {@code null}
4216     * @param startIndex  the start index to traverse backwards from
4217     * @return the last index of the object within the array,
4218     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4219     */
4220    public static int lastIndexOf(final Object[] array, final Object objectToFind, int startIndex) {
4221        if (array == null || startIndex < 0) {
4222            return INDEX_NOT_FOUND;
4223        }
4224        if (startIndex >= array.length) {
4225            startIndex = array.length - 1;
4226        }
4227        if (objectToFind == null) {
4228            for (int i = startIndex; i >= 0; i--) {
4229                if (array[i] == null) {
4230                    return i;
4231                }
4232            }
4233        } else if (array.getClass().getComponentType().isInstance(objectToFind)) {
4234            for (int i = startIndex; i >= 0; i--) {
4235                if (objectToFind.equals(array[i])) {
4236                    return i;
4237                }
4238            }
4239        }
4240        return INDEX_NOT_FOUND;
4241    }
4242
4243    /**
4244     * Finds the last index of the given value within the array.
4245     * <p>
4246     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4247     * </p>
4248     *
4249     * @param array  the array to traverse backwards looking for the object, may be {@code null}
4250     * @param valueToFind  the object to find
4251     * @return the last index of the value within the array,
4252     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4253     */
4254    public static int lastIndexOf(final short[] array, final short valueToFind) {
4255        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4256    }
4257
4258    /**
4259     * Finds the last index of the given value in the array starting at the given index.
4260     * <p>
4261     * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4262     * </p>
4263     * <p>
4264     * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
4265     * array length will search from the end of the array.
4266     * </p>
4267     *
4268     * @param array  the array to traverse for looking for the object, may be {@code null}
4269     * @param valueToFind  the value to find
4270     * @param startIndex  the start index to traverse backwards from
4271     * @return the last index of the value within the array,
4272     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4273     */
4274    public static int lastIndexOf(final short[] array, final short valueToFind, int startIndex) {
4275        if (array == null || startIndex < 0) {
4276            return INDEX_NOT_FOUND;
4277        }
4278        if (startIndex >= array.length) {
4279            startIndex = array.length - 1;
4280        }
4281        for (int i = startIndex; i >= 0; i--) {
4282            if (valueToFind == array[i]) {
4283                return i;
4284            }
4285        }
4286        return INDEX_NOT_FOUND;
4287    }
4288
4289    /**
4290     * Maps elements from an array into elements of a new array of a given type, while mapping old elements to new elements.
4291     *
4292     * @param <T>           The input array type.
4293     * @param <R>           The output array type.
4294     * @param <E>           The type of exceptions thrown when the mapper function fails.
4295     * @param array         The input array.
4296     * @param componentType the component type of the result array.
4297     * @param mapper        a non-interfering, stateless function to apply to each element
4298     * @return a new array
4299     * @throws E Thrown when the mapper function fails.
4300     */
4301    private static <T, R, E extends Throwable> R[] map(final T[] array, final Class<R> componentType, final FailableFunction<? super T, ? extends R, E> mapper)
4302            throws E {
4303        return ArrayFill.fill(newInstance(componentType, array.length), i -> mapper.apply(array[i]));
4304    }
4305
4306    private static int max0(final int other) {
4307        return Math.max(0, other);
4308    }
4309
4310    /**
4311     * Delegates to {@link Array#newInstance(Class,int)} using generics.
4312     *
4313     * @param <T> The array type.
4314     * @param componentType The array class.
4315     * @param length the array length
4316     * @return The new array.
4317     * @throws NullPointerException if the specified {@code componentType} parameter is null.
4318     * @since 3.13.0
4319     */
4320    @SuppressWarnings("unchecked") // OK, because array and values are of type T
4321    public static <T> T[] newInstance(final Class<T> componentType, final int length) {
4322        return (T[]) Array.newInstance(componentType, length);
4323    }
4324
4325    /**
4326     * Defensive programming technique to change a {@code null}
4327     * reference to an empty one.
4328     * <p>
4329     * This method returns a default array for a {@code null} input array.
4330     * </p>
4331     * <p>
4332     * As a memory optimizing technique an empty array passed in will be overridden with
4333     * the empty {@code public static} references in this class.
4334     * </p>
4335     *
4336     * @param <T> The array type.
4337     * @param array  the array to check for {@code null} or empty
4338     * @param defaultArray A default array, usually empty.
4339     * @return the same array, or defaultArray if {@code null} or empty input.
4340     * @since 3.15.0
4341     */
4342    public static <T> T[] nullTo(final T[] array, final T[] defaultArray) {
4343        return isEmpty(array) ? defaultArray : array;
4344    }
4345
4346    /**
4347     * Defensive programming technique to change a {@code null}
4348     * reference to an empty one.
4349     * <p>
4350     * This method returns an empty array for a {@code null} input array.
4351     * </p>
4352     * <p>
4353     * As a memory optimizing technique an empty array passed in will be overridden with
4354     * the empty {@code public static} references in this class.
4355     * </p>
4356     *
4357     * @param array  the array to check for {@code null} or empty
4358     * @return the same array, {@code public static} empty array if {@code null} or empty input
4359     * @since 2.5
4360     */
4361    public static boolean[] nullToEmpty(final boolean[] array) {
4362        return isEmpty(array) ? EMPTY_BOOLEAN_ARRAY : array;
4363    }
4364
4365    /**
4366     * Defensive programming technique to change a {@code null}
4367     * reference to an empty one.
4368     * <p>
4369     * This method returns an empty array for a {@code null} input array.
4370     * </p>
4371     * <p>
4372     * As a memory optimizing technique an empty array passed in will be overridden with
4373     * the empty {@code public static} references in this class.
4374     * </p>
4375     *
4376     * @param array  the array to check for {@code null} or empty
4377     * @return the same array, {@code public static} empty array if {@code null} or empty input
4378     * @since 2.5
4379     */
4380    public static Boolean[] nullToEmpty(final Boolean[] array) {
4381        return nullTo(array, EMPTY_BOOLEAN_OBJECT_ARRAY);
4382    }
4383
4384    /**
4385     * Defensive programming technique to change a {@code null}
4386     * reference to an empty one.
4387     * <p>
4388     * This method returns an empty array for a {@code null} input array.
4389     * </p>
4390     * <p>
4391     * As a memory optimizing technique an empty array passed in will be overridden with
4392     * the empty {@code public static} references in this class.
4393     * </p>
4394     *
4395     * @param array  the array to check for {@code null} or empty
4396     * @return the same array, {@code public static} empty array if {@code null} or empty input
4397     * @since 2.5
4398     */
4399    public static byte[] nullToEmpty(final byte[] array) {
4400        return isEmpty(array) ? EMPTY_BYTE_ARRAY : array;
4401    }
4402
4403    /**
4404     * Defensive programming technique to change a {@code null}
4405     * reference to an empty one.
4406     * <p>
4407     * This method returns an empty array for a {@code null} input array.
4408     * </p>
4409     * <p>
4410     * As a memory optimizing technique an empty array passed in will be overridden with
4411     * the empty {@code public static} references in this class.
4412     * </p>
4413     *
4414     * @param array  the array to check for {@code null} or empty
4415     * @return the same array, {@code public static} empty array if {@code null} or empty input
4416     * @since 2.5
4417     */
4418    public static Byte[] nullToEmpty(final Byte[] array) {
4419        return nullTo(array, EMPTY_BYTE_OBJECT_ARRAY);
4420    }
4421
4422    /**
4423     * Defensive programming technique to change a {@code null}
4424     * reference to an empty one.
4425     * <p>
4426     * This method returns an empty array for a {@code null} input array.
4427     * </p>
4428     * <p>
4429     * As a memory optimizing technique an empty array passed in will be overridden with
4430     * the empty {@code public static} references in this class.
4431     * </p>
4432     *
4433     * @param array  the array to check for {@code null} or empty
4434     * @return the same array, {@code public static} empty array if {@code null} or empty input
4435     * @since 2.5
4436     */
4437    public static char[] nullToEmpty(final char[] array) {
4438        return isEmpty(array) ? EMPTY_CHAR_ARRAY : array;
4439    }
4440
4441    /**
4442     * Defensive programming technique to change a {@code null}
4443     * reference to an empty one.
4444     * <p>
4445     * This method returns an empty array for a {@code null} input array.
4446     * </p>
4447     * <p>
4448     * As a memory optimizing technique an empty array passed in will be overridden with
4449     * the empty {@code public static} references in this class.
4450     * </p>
4451     *
4452     * @param array  the array to check for {@code null} or empty
4453     * @return the same array, {@code public static} empty array if {@code null} or empty input
4454     * @since 2.5
4455     */
4456    public static Character[] nullToEmpty(final Character[] array) {
4457        return nullTo(array, EMPTY_CHARACTER_OBJECT_ARRAY);
4458    }
4459
4460    /**
4461     * Defensive programming technique to change a {@code null}
4462     * reference to an empty one.
4463     * <p>
4464     * This method returns an empty array for a {@code null} input array.
4465     * </p>
4466     * <p>
4467     * As a memory optimizing technique an empty array passed in will be overridden with
4468     * the empty {@code public static} references in this class.
4469     * </p>
4470     *
4471     * @param array  the array to check for {@code null} or empty
4472     * @return the same array, {@code public static} empty array if {@code null} or empty input
4473     * @since 3.2
4474     */
4475    public static Class<?>[] nullToEmpty(final Class<?>[] array) {
4476        return nullTo(array, EMPTY_CLASS_ARRAY);
4477    }
4478
4479    /**
4480     * Defensive programming technique to change a {@code null}
4481     * reference to an empty one.
4482     * <p>
4483     * This method returns an empty array for a {@code null} input array.
4484     * </p>
4485     * <p>
4486     * As a memory optimizing technique an empty array passed in will be overridden with
4487     * the empty {@code public static} references in this class.
4488     * </p>
4489     *
4490     * @param array  the array to check for {@code null} or empty
4491     * @return the same array, {@code public static} empty array if {@code null} or empty input
4492     * @since 2.5
4493     */
4494    public static double[] nullToEmpty(final double[] array) {
4495        return isEmpty(array) ? EMPTY_DOUBLE_ARRAY : array;
4496    }
4497
4498    /**
4499     * Defensive programming technique to change a {@code null}
4500     * reference to an empty one.
4501     * <p>
4502     * This method returns an empty array for a {@code null} input array.
4503     * </p>
4504     * <p>
4505     * As a memory optimizing technique an empty array passed in will be overridden with
4506     * the empty {@code public static} references in this class.
4507     * </p>
4508     *
4509     * @param array  the array to check for {@code null} or empty
4510     * @return the same array, {@code public static} empty array if {@code null} or empty input
4511     * @since 2.5
4512     */
4513    public static Double[] nullToEmpty(final Double[] array) {
4514        return nullTo(array, EMPTY_DOUBLE_OBJECT_ARRAY);
4515    }
4516
4517    /**
4518     * Defensive programming technique to change a {@code null}
4519     * reference to an empty one.
4520     * <p>
4521     * This method returns an empty array for a {@code null} input array.
4522     * </p>
4523     * <p>
4524     * As a memory optimizing technique an empty array passed in will be overridden with
4525     * the empty {@code public static} references in this class.
4526     * </p>
4527     *
4528     * @param array  the array to check for {@code null} or empty
4529     * @return the same array, {@code public static} empty array if {@code null} or empty input
4530     * @since 2.5
4531     */
4532    public static float[] nullToEmpty(final float[] array) {
4533        return isEmpty(array) ? EMPTY_FLOAT_ARRAY : array;
4534    }
4535
4536    /**
4537     * Defensive programming technique to change a {@code null}
4538     * reference to an empty one.
4539     * <p>
4540     * This method returns an empty array for a {@code null} input array.
4541     * </p>
4542     * <p>
4543     * As a memory optimizing technique an empty array passed in will be overridden with
4544     * the empty {@code public static} references in this class.
4545     * </p>
4546     *
4547     * @param array  the array to check for {@code null} or empty
4548     * @return the same array, {@code public static} empty array if {@code null} or empty input
4549     * @since 2.5
4550     */
4551    public static Float[] nullToEmpty(final Float[] array) {
4552        return nullTo(array, EMPTY_FLOAT_OBJECT_ARRAY);
4553    }
4554
4555    /**
4556     * Defensive programming technique to change a {@code null}
4557     * reference to an empty one.
4558     * <p>
4559     * This method returns an empty array for a {@code null} input array.
4560     * </p>
4561     * <p>
4562     * As a memory optimizing technique an empty array passed in will be overridden with
4563     * the empty {@code public static} references in this class.
4564     * </p>
4565     *
4566     * @param array  the array to check for {@code null} or empty
4567     * @return the same array, {@code public static} empty array if {@code null} or empty input
4568     * @since 2.5
4569     */
4570    public static int[] nullToEmpty(final int[] array) {
4571        return isEmpty(array) ? EMPTY_INT_ARRAY : array;
4572    }
4573
4574    /**
4575     * Defensive programming technique to change a {@code null}
4576     * reference to an empty one.
4577     * <p>
4578     * This method returns an empty array for a {@code null} input array.
4579     * </p>
4580     * <p>
4581     * As a memory optimizing technique an empty array passed in will be overridden with
4582     * the empty {@code public static} references in this class.
4583     * </p>
4584     *
4585     * @param array  the array to check for {@code null} or empty
4586     * @return the same array, {@code public static} empty array if {@code null} or empty input
4587     * @since 2.5
4588     */
4589    public static Integer[] nullToEmpty(final Integer[] array) {
4590        return nullTo(array, EMPTY_INTEGER_OBJECT_ARRAY);
4591    }
4592
4593    /**
4594     * Defensive programming technique to change a {@code null}
4595     * reference to an empty one.
4596     * <p>
4597     * This method returns an empty array for a {@code null} input array.
4598     * </p>
4599     * <p>
4600     * As a memory optimizing technique an empty array passed in will be overridden with
4601     * the empty {@code public static} references in this class.
4602     * </p>
4603     *
4604     * @param array  the array to check for {@code null} or empty
4605     * @return the same array, {@code public static} empty array if {@code null} or empty input
4606     * @since 2.5
4607     */
4608    public static long[] nullToEmpty(final long[] array) {
4609        return isEmpty(array) ? EMPTY_LONG_ARRAY : array;
4610    }
4611
4612    /**
4613     * Defensive programming technique to change a {@code null}
4614     * reference to an empty one.
4615     * <p>
4616     * This method returns an empty array for a {@code null} input array.
4617     * </p>
4618     * <p>
4619     * As a memory optimizing technique an empty array passed in will be overridden with
4620     * the empty {@code public static} references in this class.
4621     * </p>
4622     *
4623     * @param array  the array to check for {@code null} or empty
4624     * @return the same array, {@code public static} empty array if {@code null} or empty input
4625     * @since 2.5
4626     */
4627    public static Long[] nullToEmpty(final Long[] array) {
4628        return nullTo(array, EMPTY_LONG_OBJECT_ARRAY);
4629    }
4630
4631    /**
4632     * Defensive programming technique to change a {@code null}
4633     * reference to an empty one.
4634     * <p>
4635     * This method returns an empty array for a {@code null} input array.
4636     * </p>
4637     * <p>
4638     * As a memory optimizing technique an empty array passed in will be overridden with
4639     * the empty {@code public static} references in this class.
4640     * </p>
4641     *
4642     * @param array  the array to check for {@code null} or empty
4643     * @return the same array, {@code public static} empty array if {@code null} or empty input
4644     * @since 2.5
4645     */
4646    public static Object[] nullToEmpty(final Object[] array) {
4647        return nullTo(array, EMPTY_OBJECT_ARRAY);
4648    }
4649
4650    /**
4651     * Defensive programming technique to change a {@code null}
4652     * reference to an empty one.
4653     * <p>
4654     * This method returns an empty array for a {@code null} input array.
4655     * </p>
4656     * <p>
4657     * As a memory optimizing technique an empty array passed in will be overridden with
4658     * the empty {@code public static} references in this class.
4659     * </p>
4660     *
4661     * @param array  the array to check for {@code null} or empty
4662     * @return the same array, {@code public static} empty array if {@code null} or empty input
4663     * @since 2.5
4664     */
4665    public static short[] nullToEmpty(final short[] array) {
4666        return isEmpty(array) ? EMPTY_SHORT_ARRAY : array;
4667    }
4668
4669    /**
4670     * Defensive programming technique to change a {@code null}
4671     * reference to an empty one.
4672     * <p>
4673     * This method returns an empty array for a {@code null} input array.
4674     * </p>
4675     * <p>
4676     * As a memory optimizing technique an empty array passed in will be overridden with
4677     * the empty {@code public static} references in this class.
4678     * </p>
4679     *
4680     * @param array  the array to check for {@code null} or empty
4681     * @return the same array, {@code public static} empty array if {@code null} or empty input
4682     * @since 2.5
4683     */
4684    public static Short[] nullToEmpty(final Short[] array) {
4685        return nullTo(array, EMPTY_SHORT_OBJECT_ARRAY);
4686    }
4687
4688    /**
4689     * Defensive programming technique to change a {@code null}
4690     * reference to an empty one.
4691     * <p>
4692     * This method returns an empty array for a {@code null} input array.
4693     * </p>
4694     * <p>
4695     * As a memory optimizing technique an empty array passed in will be overridden with
4696     * the empty {@code public static} references in this class.
4697     * </p>
4698     *
4699     * @param array  the array to check for {@code null} or empty
4700     * @return the same array, {@code public static} empty array if {@code null} or empty input
4701     * @since 2.5
4702     */
4703    public static String[] nullToEmpty(final String[] array) {
4704        return nullTo(array, EMPTY_STRING_ARRAY);
4705    }
4706
4707    /**
4708     * Defensive programming technique to change a {@code null}
4709     * reference to an empty one.
4710     * <p>
4711     * This method returns an empty array for a {@code null} input array.
4712     * </p>
4713     *
4714     * @param array  the array to check for {@code null} or empty
4715     * @param type   the class representation of the desired array
4716     * @param <T>  the class type
4717     * @return the same array, {@code public static} empty array if {@code null}
4718     * @throws IllegalArgumentException if the type argument is null
4719     * @since 3.5
4720     */
4721    public static <T> T[] nullToEmpty(final T[] array, final Class<T[]> type) {
4722        if (type == null) {
4723            throw new IllegalArgumentException("The type must not be null");
4724        }
4725        if (array == null) {
4726            return type.cast(Array.newInstance(type.getComponentType(), 0));
4727        }
4728        return array;
4729    }
4730
4731    /**
4732     * Gets the {@link ThreadLocalRandom} for {@code shuffle} methods that don't take a {@link Random} argument.
4733     *
4734     * @return the current ThreadLocalRandom.
4735     */
4736    private static ThreadLocalRandom random() {
4737        return ThreadLocalRandom.current();
4738    }
4739
4740    /**
4741     * Removes the element at the specified position from the specified array.
4742     * All subsequent elements are shifted to the left (subtracts one from
4743     * their indices).
4744     * <p>
4745     * This method returns a new array with the same elements of the input
4746     * array except the element on the specified position. The component
4747     * type of the returned array is always the same as that of the input
4748     * array.
4749     * </p>
4750     * <p>
4751     * If the input array is {@code null}, an IndexOutOfBoundsException
4752     * will be thrown, because in that case no valid index can be specified.
4753     * </p>
4754     * <pre>
4755     * ArrayUtils.remove([true], 0)              = []
4756     * ArrayUtils.remove([true, false], 0)       = [false]
4757     * ArrayUtils.remove([true, false], 1)       = [true]
4758     * ArrayUtils.remove([true, true, false], 1) = [true, false]
4759     * </pre>
4760     *
4761     * @param array  the array to remove the element from, may not be {@code null}
4762     * @param index  the position of the element to be removed
4763     * @return A new array containing the existing elements except the element
4764     *         at the specified position.
4765     * @throws IndexOutOfBoundsException if the index is out of range
4766     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4767     * @since 2.1
4768     */
4769    public static boolean[] remove(final boolean[] array, final int index) {
4770        return (boolean[]) remove((Object) array, index);
4771    }
4772
4773    /**
4774     * Removes the element at the specified position from the specified array.
4775     * All subsequent elements are shifted to the left (subtracts one from
4776     * their indices).
4777     * <p>
4778     * This method returns a new array with the same elements of the input
4779     * array except the element on the specified position. The component
4780     * type of the returned array is always the same as that of the input
4781     * array.
4782     * </p>
4783     * <p>
4784     * If the input array is {@code null}, an IndexOutOfBoundsException
4785     * will be thrown, because in that case no valid index can be specified.
4786     * </p>
4787     * <pre>
4788     * ArrayUtils.remove([1], 0)          = []
4789     * ArrayUtils.remove([1, 0], 0)       = [0]
4790     * ArrayUtils.remove([1, 0], 1)       = [1]
4791     * ArrayUtils.remove([1, 0, 1], 1)    = [1, 1]
4792     * </pre>
4793     *
4794     * @param array  the array to remove the element from, may not be {@code null}
4795     * @param index  the position of the element to be removed
4796     * @return A new array containing the existing elements except the element
4797     *         at the specified position.
4798     * @throws IndexOutOfBoundsException if the index is out of range
4799     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4800     * @since 2.1
4801     */
4802    public static byte[] remove(final byte[] array, final int index) {
4803        return (byte[]) remove((Object) array, index);
4804    }
4805
4806    /**
4807     * Removes the element at the specified position from the specified array.
4808     * All subsequent elements are shifted to the left (subtracts one from
4809     * their indices).
4810     * <p>
4811     * This method returns a new array with the same elements of the input
4812     * array except the element on the specified position. The component
4813     * type of the returned array is always the same as that of the input
4814     * array.
4815     * </p>
4816     * <p>
4817     * If the input array is {@code null}, an IndexOutOfBoundsException
4818     * will be thrown, because in that case no valid index can be specified.
4819     * </p>
4820     * <pre>
4821     * ArrayUtils.remove(['a'], 0)           = []
4822     * ArrayUtils.remove(['a', 'b'], 0)      = ['b']
4823     * ArrayUtils.remove(['a', 'b'], 1)      = ['a']
4824     * ArrayUtils.remove(['a', 'b', 'c'], 1) = ['a', 'c']
4825     * </pre>
4826     *
4827     * @param array  the array to remove the element from, may not be {@code null}
4828     * @param index  the position of the element to be removed
4829     * @return A new array containing the existing elements except the element
4830     *         at the specified position.
4831     * @throws IndexOutOfBoundsException if the index is out of range
4832     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4833     * @since 2.1
4834     */
4835    public static char[] remove(final char[] array, final int index) {
4836        return (char[]) remove((Object) array, index);
4837    }
4838
4839    /**
4840     * Removes the element at the specified position from the specified array.
4841     * All subsequent elements are shifted to the left (subtracts one from
4842     * their indices).
4843     * <p>
4844     * This method returns a new array with the same elements of the input
4845     * array except the element on the specified position. The component
4846     * type of the returned array is always the same as that of the input
4847     * array.
4848     * </p>
4849     * <p>
4850     * If the input array is {@code null}, an IndexOutOfBoundsException
4851     * will be thrown, because in that case no valid index can be specified.
4852     * </p>
4853     * <pre>
4854     * ArrayUtils.remove([1.1], 0)           = []
4855     * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
4856     * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
4857     * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
4858     * </pre>
4859     *
4860     * @param array  the array to remove the element from, may not be {@code null}
4861     * @param index  the position of the element to be removed
4862     * @return A new array containing the existing elements except the element
4863     *         at the specified position.
4864     * @throws IndexOutOfBoundsException if the index is out of range
4865     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4866     * @since 2.1
4867     */
4868    public static double[] remove(final double[] array, final int index) {
4869        return (double[]) remove((Object) array, index);
4870    }
4871
4872    /**
4873     * Removes the element at the specified position from the specified array.
4874     * All subsequent elements are shifted to the left (subtracts one from
4875     * their indices).
4876     * <p>
4877     * This method returns a new array with the same elements of the input
4878     * array except the element on the specified position. The component
4879     * type of the returned array is always the same as that of the input
4880     * array.
4881     * </p>
4882     * <p>
4883     * If the input array is {@code null}, an IndexOutOfBoundsException
4884     * will be thrown, because in that case no valid index can be specified.
4885     * </p>
4886     * <pre>
4887     * ArrayUtils.remove([1.1], 0)           = []
4888     * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
4889     * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
4890     * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
4891     * </pre>
4892     *
4893     * @param array  the array to remove the element from, may not be {@code null}
4894     * @param index  the position of the element to be removed
4895     * @return A new array containing the existing elements except the element
4896     *         at the specified position.
4897     * @throws IndexOutOfBoundsException if the index is out of range
4898     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4899     * @since 2.1
4900     */
4901    public static float[] remove(final float[] array, final int index) {
4902        return (float[]) remove((Object) array, index);
4903    }
4904
4905    /**
4906     * Removes the element at the specified position from the specified array.
4907     * All subsequent elements are shifted to the left (subtracts one from
4908     * their indices).
4909     * <p>
4910     * This method returns a new array with the same elements of the input
4911     * array except the element on the specified position. The component
4912     * type of the returned array is always the same as that of the input
4913     * array.
4914     * </p>
4915     * <p>
4916     * If the input array is {@code null}, an IndexOutOfBoundsException
4917     * will be thrown, because in that case no valid index can be specified.
4918     * </p>
4919     * <pre>
4920     * ArrayUtils.remove([1], 0)         = []
4921     * ArrayUtils.remove([2, 6], 0)      = [6]
4922     * ArrayUtils.remove([2, 6], 1)      = [2]
4923     * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
4924     * </pre>
4925     *
4926     * @param array  the array to remove the element from, may not be {@code null}
4927     * @param index  the position of the element to be removed
4928     * @return A new array containing the existing elements except the element
4929     *         at the specified position.
4930     * @throws IndexOutOfBoundsException if the index is out of range
4931     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4932     * @since 2.1
4933     */
4934    public static int[] remove(final int[] array, final int index) {
4935        return (int[]) remove((Object) array, index);
4936    }
4937
4938    /**
4939     * Removes the element at the specified position from the specified array.
4940     * All subsequent elements are shifted to the left (subtracts one from
4941     * their indices).
4942     * <p>
4943     * This method returns a new array with the same elements of the input
4944     * array except the element on the specified position. The component
4945     * type of the returned array is always the same as that of the input
4946     * array.
4947     * </p>
4948     * <p>
4949     * If the input array is {@code null}, an IndexOutOfBoundsException
4950     * will be thrown, because in that case no valid index can be specified.
4951     * </p>
4952     * <pre>
4953     * ArrayUtils.remove([1], 0)         = []
4954     * ArrayUtils.remove([2, 6], 0)      = [6]
4955     * ArrayUtils.remove([2, 6], 1)      = [2]
4956     * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
4957     * </pre>
4958     *
4959     * @param array  the array to remove the element from, may not be {@code null}
4960     * @param index  the position of the element to be removed
4961     * @return A new array containing the existing elements except the element
4962     *         at the specified position.
4963     * @throws IndexOutOfBoundsException if the index is out of range
4964     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4965     * @since 2.1
4966     */
4967    public static long[] remove(final long[] array, final int index) {
4968        return (long[]) remove((Object) array, index);
4969    }
4970
4971    /**
4972     * Removes the element at the specified position from the specified array.
4973     * All subsequent elements are shifted to the left (subtracts one from
4974     * their indices).
4975     * <p>
4976     * This method returns a new array with the same elements of the input
4977     * array except the element on the specified position. The component
4978     * type of the returned array is always the same as that of the input
4979     * array.
4980     * </p>
4981     * <p>
4982     * If the input array is {@code null}, an IndexOutOfBoundsException
4983     * will be thrown, because in that case no valid index can be specified.
4984     * </p>
4985     *
4986     * @param array  the array to remove the element from, may not be {@code null}
4987     * @param index  the position of the element to be removed
4988     * @return A new array containing the existing elements except the element
4989     *         at the specified position.
4990     * @throws IndexOutOfBoundsException if the index is out of range
4991     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4992     * @since 2.1
4993     */
4994    private static Object remove(final Object array, final int index) {
4995        final int length = getLength(array);
4996        if (index < 0 || index >= length) {
4997            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
4998        }
4999        final Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
5000        System.arraycopy(array, 0, result, 0, index);
5001        if (index < length - 1) {
5002            System.arraycopy(array, index + 1, result, index, length - index - 1);
5003        }
5004        return result;
5005    }
5006
5007    /**
5008     * Removes the element at the specified position from the specified array.
5009     * All subsequent elements are shifted to the left (subtracts one from
5010     * their indices).
5011     * <p>
5012     * This method returns a new array with the same elements of the input
5013     * array except the element on the specified position. The component
5014     * type of the returned array is always the same as that of the input
5015     * array.
5016     * </p>
5017     * <p>
5018     * If the input array is {@code null}, an IndexOutOfBoundsException
5019     * will be thrown, because in that case no valid index can be specified.
5020     * </p>
5021     * <pre>
5022     * ArrayUtils.remove([1], 0)         = []
5023     * ArrayUtils.remove([2, 6], 0)      = [6]
5024     * ArrayUtils.remove([2, 6], 1)      = [2]
5025     * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
5026     * </pre>
5027     *
5028     * @param array  the array to remove the element from, may not be {@code null}
5029     * @param index  the position of the element to be removed
5030     * @return A new array containing the existing elements except the element
5031     *         at the specified position.
5032     * @throws IndexOutOfBoundsException if the index is out of range
5033     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5034     * @since 2.1
5035     */
5036    public static short[] remove(final short[] array, final int index) {
5037        return (short[]) remove((Object) array, index);
5038    }
5039
5040    /**
5041     * Removes the element at the specified position from the specified array.
5042     * All subsequent elements are shifted to the left (subtracts one from
5043     * their indices).
5044     * <p>
5045     * This method returns a new array with the same elements of the input
5046     * array except the element on the specified position. The component
5047     * type of the returned array is always the same as that of the input
5048     * array.
5049     * </p>
5050     * <p>
5051     * If the input array is {@code null}, an IndexOutOfBoundsException
5052     * will be thrown, because in that case no valid index can be specified.
5053     * </p>
5054     * <pre>
5055     * ArrayUtils.remove(["a"], 0)           = []
5056     * ArrayUtils.remove(["a", "b"], 0)      = ["b"]
5057     * ArrayUtils.remove(["a", "b"], 1)      = ["a"]
5058     * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"]
5059     * </pre>
5060     *
5061     * @param <T> the component type of the array
5062     * @param array  the array to remove the element from, may not be {@code null}
5063     * @param index  the position of the element to be removed
5064     * @return A new array containing the existing elements except the element
5065     *         at the specified position.
5066     * @throws IndexOutOfBoundsException if the index is out of range
5067     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5068     * @since 2.1
5069     */
5070    @SuppressWarnings("unchecked") // remove() always creates an array of the same type as its input
5071    public static <T> T[] remove(final T[] array, final int index) {
5072        return (T[]) remove((Object) array, index);
5073    }
5074
5075    /**
5076     * Removes the elements at the specified positions from the specified array.
5077     * All remaining elements are shifted to the left.
5078     * <p>
5079     * This method returns a new array with the same elements of the input
5080     * array except those at the specified positions. The component
5081     * type of the returned array is always the same as that of the input
5082     * array.
5083     * </p>
5084     * <p>
5085     * If the input array is {@code null}, an IndexOutOfBoundsException
5086     * will be thrown, because in that case no valid index can be specified.
5087     * </p>
5088     * <pre>
5089     * ArrayUtils.removeAll([true, false, true], 0, 2) = [false]
5090     * ArrayUtils.removeAll([true, false, true], 1, 2) = [true]
5091     * </pre>
5092     *
5093     * @param array   the array to remove the element from, may not be {@code null}
5094     * @param indices the positions of the elements to be removed
5095     * @return A new array containing the existing elements except those
5096     *         at the specified positions.
5097     * @throws IndexOutOfBoundsException if any index is out of range
5098     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5099     * @since 3.0.1
5100     */
5101    public static boolean[] removeAll(final boolean[] array, final int... indices) {
5102        return (boolean[]) removeAll((Object) array, indices);
5103    }
5104
5105    /**
5106     * Removes the elements at the specified positions from the specified array.
5107     * All remaining elements are shifted to the left.
5108     * <p>
5109     * This method returns a new array with the same elements of the input
5110     * array except those at the specified positions. The component
5111     * type of the returned array is always the same as that of the input
5112     * array.
5113     * </p>
5114     * <p>
5115     * If the input array is {@code null}, an IndexOutOfBoundsException
5116     * will be thrown, because in that case no valid index can be specified.
5117     * </p>
5118     * <pre>
5119     * ArrayUtils.removeAll([1], 0)             = []
5120     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5121     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5122     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5123     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5124     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5125     * </pre>
5126     *
5127     * @param array   the array to remove the element from, may not be {@code null}
5128     * @param indices the positions of the elements to be removed
5129     * @return A new array containing the existing elements except those
5130     *         at the specified positions.
5131     * @throws IndexOutOfBoundsException if any index is out of range
5132     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5133     * @since 3.0.1
5134     */
5135    public static byte[] removeAll(final byte[] array, final int... indices) {
5136        return (byte[]) removeAll((Object) array, indices);
5137    }
5138
5139    /**
5140     * Removes the elements at the specified positions from the specified array.
5141     * All remaining elements are shifted to the left.
5142     * <p>
5143     * This method returns a new array with the same elements of the input
5144     * array except those at the specified positions. The component
5145     * type of the returned array is always the same as that of the input
5146     * array.
5147     * </p>
5148     * <p>
5149     * If the input array is {@code null}, an IndexOutOfBoundsException
5150     * will be thrown, because in that case no valid index can be specified.
5151     * </p>
5152     * <pre>
5153     * ArrayUtils.removeAll([1], 0)             = []
5154     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5155     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5156     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5157     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5158     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5159     * </pre>
5160     *
5161     * @param array   the array to remove the element from, may not be {@code null}
5162     * @param indices the positions of the elements to be removed
5163     * @return A new array containing the existing elements except those
5164     *         at the specified positions.
5165     * @throws IndexOutOfBoundsException if any index is out of range
5166     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5167     * @since 3.0.1
5168     */
5169    public static char[] removeAll(final char[] array, final int... indices) {
5170        return (char[]) removeAll((Object) array, indices);
5171    }
5172
5173    /**
5174     * Removes the elements at the specified positions from the specified array.
5175     * All remaining elements are shifted to the left.
5176     * <p>
5177     * This method returns a new array with the same elements of the input
5178     * array except those at the specified positions. The component
5179     * type of the returned array is always the same as that of the input
5180     * array.
5181     * </p>
5182     * <p>
5183     * If the input array is {@code null}, an IndexOutOfBoundsException
5184     * will be thrown, because in that case no valid index can be specified.
5185     * </p>
5186     * <pre>
5187     * ArrayUtils.removeAll([1], 0)             = []
5188     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5189     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5190     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5191     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5192     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5193     * </pre>
5194     *
5195     * @param array   the array to remove the element from, may not be {@code null}
5196     * @param indices the positions of the elements to be removed
5197     * @return A new array containing the existing elements except those
5198     *         at the specified positions.
5199     * @throws IndexOutOfBoundsException if any index is out of range
5200     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5201     * @since 3.0.1
5202     */
5203    public static double[] removeAll(final double[] array, final int... indices) {
5204        return (double[]) removeAll((Object) array, indices);
5205    }
5206
5207    /**
5208     * Removes the elements at the specified positions from the specified array.
5209     * All remaining elements are shifted to the left.
5210     * <p>
5211     * This method returns a new array with the same elements of the input
5212     * array except those at the specified positions. The component
5213     * type of the returned array is always the same as that of the input
5214     * array.
5215     * </p>
5216     * <p>
5217     * If the input array is {@code null}, an IndexOutOfBoundsException
5218     * will be thrown, because in that case no valid index can be specified.
5219     * </p>
5220     * <pre>
5221     * ArrayUtils.removeAll([1], 0)             = []
5222     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5223     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5224     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5225     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5226     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5227     * </pre>
5228     *
5229     * @param array   the array to remove the element from, may not be {@code null}
5230     * @param indices the positions of the elements to be removed
5231     * @return A new array containing the existing elements except those
5232     *         at the specified positions.
5233     * @throws IndexOutOfBoundsException if any index is out of range
5234     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5235     * @since 3.0.1
5236     */
5237    public static float[] removeAll(final float[] array, final int... indices) {
5238        return (float[]) removeAll((Object) array, indices);
5239    }
5240
5241    /**
5242     * Removes the elements at the specified positions from the specified array.
5243     * All remaining elements are shifted to the left.
5244     * <p>
5245     * This method returns a new array with the same elements of the input
5246     * array except those at the specified positions. The component
5247     * type of the returned array is always the same as that of the input
5248     * array.
5249     * </p>
5250     * <p>
5251     * If the input array is {@code null}, an IndexOutOfBoundsException
5252     * will be thrown, because in that case no valid index can be specified.
5253     * </p>
5254     * <pre>
5255     * ArrayUtils.removeAll([1], 0)             = []
5256     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5257     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5258     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5259     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5260     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5261     * </pre>
5262     *
5263     * @param array   the array to remove the element from, may not be {@code null}
5264     * @param indices the positions of the elements to be removed
5265     * @return A new array containing the existing elements except those
5266     *         at the specified positions.
5267     * @throws IndexOutOfBoundsException if any index is out of range
5268     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5269     * @since 3.0.1
5270     */
5271    public static int[] removeAll(final int[] array, final int... indices) {
5272        return (int[]) removeAll((Object) array, indices);
5273    }
5274
5275    /**
5276     * Removes the elements at the specified positions from the specified array.
5277     * All remaining elements are shifted to the left.
5278     * <p>
5279     * This method returns a new array with the same elements of the input
5280     * array except those at the specified positions. The component
5281     * type of the returned array is always the same as that of the input
5282     * array.
5283     * </p>
5284     * <p>
5285     * If the input array is {@code null}, an IndexOutOfBoundsException
5286     * will be thrown, because in that case no valid index can be specified.
5287     * </p>
5288     * <pre>
5289     * ArrayUtils.removeAll([1], 0)             = []
5290     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5291     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5292     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5293     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5294     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5295     * </pre>
5296     *
5297     * @param array   the array to remove the element from, may not be {@code null}
5298     * @param indices the positions of the elements to be removed
5299     * @return A new array containing the existing elements except those
5300     *         at the specified positions.
5301     * @throws IndexOutOfBoundsException if any index is out of range
5302     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5303     * @since 3.0.1
5304     */
5305    public static long[] removeAll(final long[] array, final int... indices) {
5306        return (long[]) removeAll((Object) array, indices);
5307    }
5308
5309    /**
5310     * Removes multiple array elements specified by index.
5311     *
5312     * @param array source
5313     * @param indices to remove
5314     * @return new array of same type minus elements specified by unique values of {@code indices}
5315     */
5316    // package protected for access by unit tests
5317    static Object removeAll(final Object array, final int... indices) {
5318        if (array == null) {
5319            return null;
5320        }
5321        final int length = getLength(array);
5322        int diff = 0; // number of distinct indexes, i.e. number of entries that will be removed
5323        final int[] clonedIndices = ArraySorter.sort(clone(indices));
5324        // identify length of result array
5325        if (isNotEmpty(clonedIndices)) {
5326            int i = clonedIndices.length;
5327            int prevIndex = length;
5328            while (--i >= 0) {
5329                final int index = clonedIndices[i];
5330                if (index < 0 || index >= length) {
5331                    throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
5332                }
5333                if (index >= prevIndex) {
5334                    continue;
5335                }
5336                diff++;
5337                prevIndex = index;
5338            }
5339        }
5340        // create result array
5341        final Object result = Array.newInstance(array.getClass().getComponentType(), length - diff);
5342        if (diff < length && clonedIndices != null) {
5343            int end = length; // index just after last copy
5344            int dest = length - diff; // number of entries so far not copied
5345            for (int i = clonedIndices.length - 1; i >= 0; i--) {
5346                final int index = clonedIndices[i];
5347                if (end - index > 1) { // same as (cp > 0)
5348                    final int cp = end - index - 1;
5349                    dest -= cp;
5350                    System.arraycopy(array, index + 1, result, dest, cp);
5351                    // After this copy, we still have room for dest items.
5352                }
5353                end = index;
5354            }
5355            if (end > 0) {
5356                System.arraycopy(array, 0, result, 0, end);
5357            }
5358        }
5359        return result;
5360    }
5361
5362    /**
5363     * Removes the elements at the specified positions from the specified array.
5364     * All remaining elements are shifted to the left.
5365     * <p>
5366     * This method returns a new array with the same elements of the input
5367     * array except those at the specified positions. The component
5368     * type of the returned array is always the same as that of the input
5369     * array.
5370     * </p>
5371     * <p>
5372     * If the input array is {@code null}, an IndexOutOfBoundsException
5373     * will be thrown, because in that case no valid index can be specified.
5374     * </p>
5375     * <pre>
5376     * ArrayUtils.removeAll([1], 0)             = []
5377     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5378     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5379     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5380     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5381     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5382     * </pre>
5383     *
5384     * @param array   the array to remove the element from, may not be {@code null}
5385     * @param indices the positions of the elements to be removed
5386     * @return A new array containing the existing elements except those
5387     *         at the specified positions.
5388     * @throws IndexOutOfBoundsException if any index is out of range
5389     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5390     * @since 3.0.1
5391     */
5392    public static short[] removeAll(final short[] array, final int... indices) {
5393        return (short[]) removeAll((Object) array, indices);
5394    }
5395
5396    /**
5397     * Removes the elements at the specified positions from the specified array.
5398     * All remaining elements are shifted to the left.
5399     * <p>
5400     * This method returns a new array with the same elements of the input
5401     * array except those at the specified positions. The component
5402     * type of the returned array is always the same as that of the input
5403     * array.
5404     * </p>
5405     * <p>
5406     * If the input array is {@code null}, an IndexOutOfBoundsException
5407     * will be thrown, because in that case no valid index can be specified.
5408     * </p>
5409     * <pre>
5410     * ArrayUtils.removeAll(["a", "b", "c"], 0, 2) = ["b"]
5411     * ArrayUtils.removeAll(["a", "b", "c"], 1, 2) = ["a"]
5412     * </pre>
5413     *
5414     * @param <T> the component type of the array
5415     * @param array   the array to remove the element from, may not be {@code null}
5416     * @param indices the positions of the elements to be removed
5417     * @return A new array containing the existing elements except those
5418     *         at the specified positions.
5419     * @throws IndexOutOfBoundsException if any index is out of range
5420     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5421     * @since 3.0.1
5422     */
5423    @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
5424    public static <T> T[] removeAll(final T[] array, final int... indices) {
5425        return (T[]) removeAll((Object) array, indices);
5426    }
5427
5428    /**
5429     * Removes the occurrences of the specified element from the specified boolean array.
5430     * <p>
5431     * All subsequent elements are shifted to the left (subtracts one from their indices).
5432     * If the array doesn't contain such an element, no elements are removed from the array.
5433     * {@code null} will be returned if the input array is {@code null}.
5434     * </p>
5435     *
5436     * @param array the input array, will not be modified, and may be {@code null}.
5437     * @param element the element to remove.
5438     * @return A new array containing the existing elements except the occurrences of the specified element.
5439     * @since 3.5
5440     * @deprecated Use {@link #removeAllOccurrences(boolean[], boolean)}
5441     */
5442    @Deprecated
5443    public static boolean[] removeAllOccurences(final boolean[] array, final boolean element) {
5444        return (boolean[]) removeAt(array, indexesOf(array, element));
5445    }
5446
5447    /**
5448     * Removes the occurrences of the specified element from the specified byte array.
5449     * <p>
5450     * All subsequent elements are shifted to the left (subtracts one from their indices).
5451     * If the array doesn't contain such an element, no elements are removed from the array.
5452     * {@code null} will be returned if the input array is {@code null}.
5453     * </p>
5454     *
5455     * @param array the input array, will not be modified, and may be {@code null}.
5456     * @param element the element to remove.
5457     * @return A new array containing the existing elements except the occurrences of the specified element.
5458     * @since 3.5
5459     * @deprecated Use {@link #removeAllOccurrences(byte[], byte)}
5460     */
5461    @Deprecated
5462    public static byte[] removeAllOccurences(final byte[] array, final byte element) {
5463        return (byte[]) removeAt(array, indexesOf(array, element));
5464    }
5465
5466    /**
5467     * Removes the occurrences of the specified element from the specified char array.
5468     * <p>
5469     * All subsequent elements are shifted to the left (subtracts one from their indices).
5470     * If the array doesn't contain such an element, no elements are removed from the array.
5471     * {@code null} will be returned if the input array is {@code null}.
5472     * </p>
5473     *
5474     * @param array the input array, will not be modified, and may be {@code null}.
5475     * @param element the element to remove.
5476     * @return A new array containing the existing elements except the occurrences of the specified element.
5477     * @since 3.5
5478     * @deprecated Use {@link #removeAllOccurrences(char[], char)}
5479     */
5480    @Deprecated
5481    public static char[] removeAllOccurences(final char[] array, final char element) {
5482        return (char[]) removeAt(array, indexesOf(array, element));
5483    }
5484
5485    /**
5486     * Removes the occurrences of the specified element from the specified double array.
5487     * <p>
5488     * All subsequent elements are shifted to the left (subtracts one from their indices).
5489     * If the array doesn't contain such an element, no elements are removed from the array.
5490     * {@code null} will be returned if the input array is {@code null}.
5491     * </p>
5492     *
5493     * @param array the input array, will not be modified, and may be {@code null}.
5494     * @param element the element to remove.
5495     * @return A new array containing the existing elements except the occurrences of the specified element.
5496     * @since 3.5
5497     * @deprecated Use {@link #removeAllOccurrences(double[], double)}
5498     */
5499    @Deprecated
5500    public static double[] removeAllOccurences(final double[] array, final double element) {
5501        return (double[]) removeAt(array, indexesOf(array, element));
5502    }
5503
5504    /**
5505     * Removes the occurrences of the specified element from the specified float array.
5506     * <p>
5507     * All subsequent elements are shifted to the left (subtracts one from their indices).
5508     * If the array doesn't contain such an element, no elements are removed from the array.
5509     * {@code null} will be returned if the input array is {@code null}.
5510     * </p>
5511     *
5512     * @param array the input array, will not be modified, and may be {@code null}.
5513     * @param element the element to remove.
5514     * @return A new array containing the existing elements except the occurrences of the specified element.
5515     * @since 3.5
5516     * @deprecated Use {@link #removeAllOccurrences(float[], float)}
5517     */
5518    @Deprecated
5519    public static float[] removeAllOccurences(final float[] array, final float element) {
5520        return (float[]) removeAt(array, indexesOf(array, element));
5521    }
5522
5523    /**
5524     * Removes the occurrences of the specified element from the specified int array.
5525     * <p>
5526     * All subsequent elements are shifted to the left (subtracts one from their indices).
5527     * If the array doesn't contain such an element, no elements are removed from the array.
5528     * {@code null} will be returned if the input array is {@code null}.
5529     * </p>
5530     *
5531     * @param array the input array, will not be modified, and may be {@code null}.
5532     * @param element the element to remove.
5533     * @return A new array containing the existing elements except the occurrences of the specified element.
5534     * @since 3.5
5535     * @deprecated Use {@link #removeAllOccurrences(int[], int)}
5536     */
5537    @Deprecated
5538    public static int[] removeAllOccurences(final int[] array, final int element) {
5539        return (int[]) removeAt(array, indexesOf(array, element));
5540    }
5541
5542    /**
5543     * Removes the occurrences of the specified element from the specified long array.
5544     * <p>
5545     * All subsequent elements are shifted to the left (subtracts one from their indices).
5546     * If the array doesn't contain such an element, no elements are removed from the array.
5547     * {@code null} will be returned if the input array is {@code null}.
5548     * </p>
5549     *
5550     * @param array the input array, will not be modified, and may be {@code null}.
5551     * @param element the element to remove.
5552     * @return A new array containing the existing elements except the occurrences of the specified element.
5553     * @since 3.5
5554     * @deprecated Use {@link #removeAllOccurrences(long[], long)}
5555     */
5556    @Deprecated
5557    public static long[] removeAllOccurences(final long[] array, final long element) {
5558        return (long[]) removeAt(array, indexesOf(array, element));
5559    }
5560
5561    /**
5562     * Removes the occurrences of the specified element from the specified short array.
5563     * <p>
5564     * All subsequent elements are shifted to the left (subtracts one from their indices).
5565     * If the array doesn't contain such an element, no elements are removed from the array.
5566     * {@code null} will be returned if the input array is {@code null}.
5567     * </p>
5568     *
5569     * @param array the input array, will not be modified, and may be {@code null}.
5570     * @param element the element to remove.
5571     * @return A new array containing the existing elements except the occurrences of the specified element.
5572     * @since 3.5
5573     * @deprecated Use {@link #removeAllOccurrences(short[], short)}
5574     */
5575    @Deprecated
5576    public static short[] removeAllOccurences(final short[] array, final short element) {
5577        return (short[]) removeAt(array, indexesOf(array, element));
5578    }
5579
5580    /**
5581     * Removes the occurrences of the specified element from the specified array.
5582     * <p>
5583     * All subsequent elements are shifted to the left (subtracts one from their indices).
5584     * If the array doesn't contain such an element, no elements are removed from the array.
5585     * {@code null} will be returned if the input array is {@code null}.
5586     * </p>
5587     *
5588     * @param <T> the type of object in the array, may be {@code null}.
5589     * @param array the input array, will not be modified, and may be {@code null}.
5590     * @param element the element to remove, may be {@code null}.
5591     * @return A new array containing the existing elements except the occurrences of the specified element.
5592     * @since 3.5
5593     * @deprecated Use {@link #removeAllOccurrences(Object[], Object)}
5594     */
5595    @Deprecated
5596    public static <T> T[] removeAllOccurences(final T[] array, final T element) {
5597        return (T[]) removeAt(array, indexesOf(array, element));
5598    }
5599
5600    /**
5601     * Removes the occurrences of the specified element from the specified boolean array.
5602     * <p>
5603     * All subsequent elements are shifted to the left (subtracts one from their indices).
5604     * If the array doesn't contain such an element, no elements are removed from the array.
5605     * {@code null} will be returned if the input array is {@code null}.
5606     * </p>
5607     *
5608     * @param array the input array, will not be modified, and may be {@code null}.
5609     * @param element the element to remove.
5610     * @return A new array containing the existing elements except the occurrences of the specified element.
5611     * @since 3.10
5612     */
5613    public static boolean[] removeAllOccurrences(final boolean[] array, final boolean element) {
5614        return (boolean[]) removeAt(array, indexesOf(array, element));
5615    }
5616
5617    /**
5618     * Removes the occurrences of the specified element from the specified byte array.
5619     * <p>
5620     * All subsequent elements are shifted to the left (subtracts one from their indices).
5621     * If the array doesn't contain such an element, no elements are removed from the array.
5622     * {@code null} will be returned if the input array is {@code null}.
5623     * </p>
5624     *
5625     * @param array the input array, will not be modified, and may be {@code null}.
5626     * @param element the element to remove.
5627     * @return A new array containing the existing elements except the occurrences of the specified element.
5628     * @since 3.10
5629     */
5630    public static byte[] removeAllOccurrences(final byte[] array, final byte element) {
5631        return (byte[]) removeAt(array, indexesOf(array, element));
5632    }
5633
5634    /**
5635     * Removes the occurrences of the specified element from the specified char array.
5636     * <p>
5637     * All subsequent elements are shifted to the left (subtracts one from their indices).
5638     * If the array doesn't contain such an element, no elements are removed from the array.
5639     * {@code null} will be returned if the input array is {@code null}.
5640     * </p>
5641     *
5642     * @param array the input array, will not be modified, and may be {@code null}.
5643     * @param element the element to remove.
5644     * @return A new array containing the existing elements except the occurrences of the specified element.
5645     * @since 3.10
5646     */
5647    public static char[] removeAllOccurrences(final char[] array, final char element) {
5648        return (char[]) removeAt(array, indexesOf(array, element));
5649    }
5650
5651    /**
5652     * Removes the occurrences of the specified element from the specified double array.
5653     * <p>
5654     * All subsequent elements are shifted to the left (subtracts one from their indices).
5655     * If the array doesn't contain such an element, no elements are removed from the array.
5656     * {@code null} will be returned if the input array is {@code null}.
5657     * </p>
5658     *
5659     * @param array the input array, will not be modified, and may be {@code null}.
5660     * @param element the element to remove.
5661     * @return A new array containing the existing elements except the occurrences of the specified element.
5662     * @since 3.10
5663     */
5664    public static double[] removeAllOccurrences(final double[] array, final double element) {
5665        return (double[]) removeAt(array, indexesOf(array, element));
5666    }
5667
5668    /**
5669     * Removes the occurrences of the specified element from the specified float array.
5670     * <p>
5671     * All subsequent elements are shifted to the left (subtracts one from their indices).
5672     * If the array doesn't contain such an element, no elements are removed from the array.
5673     * {@code null} will be returned if the input array is {@code null}.
5674     * </p>
5675     *
5676     * @param array the input array, will not be modified, and may be {@code null}.
5677     * @param element the element to remove.
5678     * @return A new array containing the existing elements except the occurrences of the specified element.
5679     * @since 3.10
5680     */
5681    public static float[] removeAllOccurrences(final float[] array, final float element) {
5682        return (float[]) removeAt(array, indexesOf(array, element));
5683    }
5684
5685    /**
5686     * Removes the occurrences of the specified element from the specified int array.
5687     * <p>
5688     * All subsequent elements are shifted to the left (subtracts one from their indices).
5689     * If the array doesn't contain such an element, no elements are removed from the array.
5690     * {@code null} will be returned if the input array is {@code null}.
5691     * </p>
5692     *
5693     * @param array the input array, will not be modified, and may be {@code null}.
5694     * @param element the element to remove.
5695     * @return A new array containing the existing elements except the occurrences of the specified element.
5696     * @since 3.10
5697     */
5698    public static int[] removeAllOccurrences(final int[] array, final int element) {
5699        return (int[]) removeAt(array, indexesOf(array, element));
5700    }
5701
5702    /**
5703     * Removes the occurrences of the specified element from the specified long array.
5704     * <p>
5705     * All subsequent elements are shifted to the left (subtracts one from their indices).
5706     * If the array doesn't contain such an element, no elements are removed from the array.
5707     * {@code null} will be returned if the input array is {@code null}.
5708     * </p>
5709     *
5710     * @param array the input array, will not be modified, and may be {@code null}.
5711     * @param element the element to remove.
5712     * @return A new array containing the existing elements except the occurrences of the specified element.
5713     * @since 3.10
5714     */
5715    public static long[] removeAllOccurrences(final long[] array, final long element) {
5716        return (long[]) removeAt(array, indexesOf(array, element));
5717    }
5718
5719    /**
5720     * Removes the occurrences of the specified element from the specified short array.
5721     * <p>
5722     * All subsequent elements are shifted to the left (subtracts one from their indices).
5723     * If the array doesn't contain such an element, no elements are removed from the array.
5724     * {@code null} will be returned if the input array is {@code null}.
5725     * </p>
5726     *
5727     * @param array the input array, will not be modified, and may be {@code null}.
5728     * @param element the element to remove.
5729     * @return A new array containing the existing elements except the occurrences of the specified element.
5730     * @since 3.10
5731     */
5732    public static short[] removeAllOccurrences(final short[] array, final short element) {
5733        return (short[]) removeAt(array, indexesOf(array, element));
5734    }
5735
5736    /**
5737     * Removes the occurrences of the specified element from the specified array.
5738     * <p>
5739     * All subsequent elements are shifted to the left (subtracts one from their indices).
5740     * If the array doesn't contain such an element, no elements are removed from the array.
5741     * {@code null} will be returned if the input array is {@code null}.
5742     * </p>
5743     *
5744     * @param <T> the type of object in the array, may be {@code null}.
5745     * @param array the input array, will not be modified, and may be {@code null}.
5746     * @param element the element to remove, may be {@code null}.
5747     * @return A new array containing the existing elements except the occurrences of the specified element.
5748     * @since 3.10
5749     */
5750    public static <T> T[] removeAllOccurrences(final T[] array, final T element) {
5751        return (T[]) removeAt(array, indexesOf(array, element));
5752    }
5753
5754    /**
5755     * Removes multiple array elements specified by indices.
5756     *
5757     * @param array the input array, will not be modified, and may be {@code null}.
5758     * @param indices to remove.
5759     * @return new array of same type minus elements specified by the set bits in {@code indices}.
5760     */
5761    // package protected for access by unit tests
5762    static Object removeAt(final Object array, final BitSet indices) {
5763        if (array == null) {
5764            return null;
5765        }
5766        final int srcLength = getLength(array);
5767        // No need to check maxIndex here, because method only currently called from removeElements()
5768        // which guarantee to generate only valid bit entries.
5769//        final int maxIndex = indices.length();
5770//        if (maxIndex > srcLength) {
5771//            throw new IndexOutOfBoundsException("Index: " + (maxIndex-1) + ", Length: " + srcLength);
5772//        }
5773        final int removals = indices.cardinality(); // true bits are items to remove
5774        final Object result = Array.newInstance(array.getClass().getComponentType(), srcLength - removals);
5775        int srcIndex = 0;
5776        int destIndex = 0;
5777        int count;
5778        int set;
5779        while ((set = indices.nextSetBit(srcIndex)) != -1) {
5780            count = set - srcIndex;
5781            if (count > 0) {
5782                System.arraycopy(array, srcIndex, result, destIndex, count);
5783                destIndex += count;
5784            }
5785            srcIndex = indices.nextClearBit(set);
5786        }
5787        count = srcLength - srcIndex;
5788        if (count > 0) {
5789            System.arraycopy(array, srcIndex, result, destIndex, count);
5790        }
5791        return result;
5792    }
5793
5794    /**
5795     * Removes the first occurrence of the specified element from the
5796     * specified array. All subsequent elements are shifted to the left
5797     * (subtracts one from their indices). If the array doesn't contain
5798     * such an element, no elements are removed from the array.
5799     * <p>
5800     * This method returns a new array with the same elements of the input
5801     * array except the first occurrence of the specified element. The component
5802     * type of the returned array is always the same as that of the input
5803     * array.
5804     * </p>
5805     * <pre>
5806     * ArrayUtils.removeElement(null, true)                = null
5807     * ArrayUtils.removeElement([], true)                  = []
5808     * ArrayUtils.removeElement([true], false)             = [true]
5809     * ArrayUtils.removeElement([true, false], false)      = [true]
5810     * ArrayUtils.removeElement([true, false, true], true) = [false, true]
5811     * </pre>
5812     *
5813     * @param array the input array, may be {@code null}.
5814     * @param element  the element to be removed.
5815     * @return A new array containing the existing elements except the first
5816     *         occurrence of the specified element.
5817     * @since 2.1
5818     */
5819    public static boolean[] removeElement(final boolean[] array, final boolean element) {
5820        final int index = indexOf(array, element);
5821        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
5822    }
5823
5824    /**
5825     * Removes the first occurrence of the specified element from the
5826     * specified array. All subsequent elements are shifted to the left
5827     * (subtracts one from their indices). If the array doesn't contain
5828     * such an element, no elements are removed from the array.
5829     * <p>
5830     * This method returns a new array with the same elements of the input
5831     * array except the first occurrence of the specified element. The component
5832     * type of the returned array is always the same as that of the input
5833     * array.
5834     * </p>
5835     * <pre>
5836     * ArrayUtils.removeElement(null, 1)        = null
5837     * ArrayUtils.removeElement([], 1)          = []
5838     * ArrayUtils.removeElement([1], 0)         = [1]
5839     * ArrayUtils.removeElement([1, 0], 0)      = [1]
5840     * ArrayUtils.removeElement([1, 0, 1], 1)   = [0, 1]
5841     * </pre>
5842     *
5843     * @param array the input array, may be {@code null}.
5844     * @param element  the element to be removed.
5845     * @return A new array containing the existing elements except the first
5846     *         occurrence of the specified element.
5847     * @since 2.1
5848     */
5849    public static byte[] removeElement(final byte[] array, final byte element) {
5850        final int index = indexOf(array, element);
5851        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
5852    }
5853
5854    /**
5855     * Removes the first occurrence of the specified element from the
5856     * specified array. All subsequent elements are shifted to the left
5857     * (subtracts one from their indices). If the array doesn't contain
5858     * such an element, no elements are removed from the array.
5859     * <p>
5860     * This method returns a new array with the same elements of the input
5861     * array except the first occurrence of the specified element. The component
5862     * type of the returned array is always the same as that of the input
5863     * array.
5864     * </p>
5865     * <pre>
5866     * ArrayUtils.removeElement(null, 'a')            = null
5867     * ArrayUtils.removeElement([], 'a')              = []
5868     * ArrayUtils.removeElement(['a'], 'b')           = ['a']
5869     * ArrayUtils.removeElement(['a', 'b'], 'a')      = ['b']
5870     * ArrayUtils.removeElement(['a', 'b', 'a'], 'a') = ['b', 'a']
5871     * </pre>
5872     *
5873     * @param array the input array, may be {@code null}.
5874     * @param element  the element to be removed.
5875     * @return A new array containing the existing elements except the first
5876     *         occurrence of the specified element.
5877     * @since 2.1
5878     */
5879    public static char[] removeElement(final char[] array, final char element) {
5880        final int index = indexOf(array, element);
5881        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
5882    }
5883
5884    /**
5885     * Removes the first occurrence of the specified element from the
5886     * specified array. All subsequent elements are shifted to the left
5887     * (subtracts one from their indices). If the array doesn't contain
5888     * such an element, no elements are removed from the array.
5889     * <p>
5890     * This method returns a new array with the same elements of the input
5891     * array except the first occurrence of the specified element. The component
5892     * type of the returned array is always the same as that of the input
5893     * array.
5894     * </p>
5895     * <pre>
5896     * ArrayUtils.removeElement(null, 1.1)            = null
5897     * ArrayUtils.removeElement([], 1.1)              = []
5898     * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
5899     * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
5900     * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
5901     * </pre>
5902     *
5903     * @param array the input array, may be {@code null}.
5904     * @param element  the element to be removed.
5905     * @return A new array containing the existing elements except the first
5906     *         occurrence of the specified element.
5907     * @since 2.1
5908     */
5909    public static double[] removeElement(final double[] array, final double element) {
5910        final int index = indexOf(array, element);
5911        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
5912    }
5913
5914    /**
5915     * Removes the first occurrence of the specified element from the
5916     * specified array. All subsequent elements are shifted to the left
5917     * (subtracts one from their indices). If the array doesn't contain
5918     * such an element, no elements are removed from the array.
5919     * <p>
5920     * This method returns a new array with the same elements of the input
5921     * array except the first occurrence of the specified element. The component
5922     * type of the returned array is always the same as that of the input
5923     * array.
5924     * </p>
5925     * <pre>
5926     * ArrayUtils.removeElement(null, 1.1)            = null
5927     * ArrayUtils.removeElement([], 1.1)              = []
5928     * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
5929     * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
5930     * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
5931     * </pre>
5932     *
5933     * @param array the input array, may be {@code null}.
5934     * @param element  the element to be removed.
5935     * @return A new array containing the existing elements except the first
5936     *         occurrence of the specified element.
5937     * @since 2.1
5938     */
5939    public static float[] removeElement(final float[] array, final float element) {
5940        final int index = indexOf(array, element);
5941        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
5942    }
5943
5944    /**
5945     * Removes the first occurrence of the specified element from the
5946     * specified array. All subsequent elements are shifted to the left
5947     * (subtracts one from their indices). If the array doesn't contain
5948     * such an element, no elements are removed from the array.
5949     * <p>
5950     * This method returns a new array with the same elements of the input
5951     * array except the first occurrence of the specified element. The component
5952     * type of the returned array is always the same as that of the input
5953     * array.
5954     * </p>
5955     * <pre>
5956     * ArrayUtils.removeElement(null, 1)      = null
5957     * ArrayUtils.removeElement([], 1)        = []
5958     * ArrayUtils.removeElement([1], 2)       = [1]
5959     * ArrayUtils.removeElement([1, 3], 1)    = [3]
5960     * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
5961     * </pre>
5962     *
5963     * @param array the input array, may be {@code null}.
5964     * @param element  the element to be removed.
5965     * @return A new array containing the existing elements except the first
5966     *         occurrence of the specified element.
5967     * @since 2.1
5968     */
5969    public static int[] removeElement(final int[] array, final int element) {
5970        final int index = indexOf(array, element);
5971        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
5972    }
5973
5974    /**
5975     * Removes the first occurrence of the specified element from the
5976     * specified array. All subsequent elements are shifted to the left
5977     * (subtracts one from their indices). If the array doesn't contain
5978     * such an element, no elements are removed from the array.
5979     * <p>
5980     * This method returns a new array with the same elements of the input
5981     * array except the first occurrence of the specified element. The component
5982     * type of the returned array is always the same as that of the input
5983     * array.
5984     * </p>
5985     * <pre>
5986     * ArrayUtils.removeElement(null, 1)      = null
5987     * ArrayUtils.removeElement([], 1)        = []
5988     * ArrayUtils.removeElement([1], 2)       = [1]
5989     * ArrayUtils.removeElement([1, 3], 1)    = [3]
5990     * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
5991     * </pre>
5992     *
5993     * @param array the input array, may be {@code null}.
5994     * @param element  the element to be removed.
5995     * @return A new array containing the existing elements except the first
5996     *         occurrence of the specified element.
5997     * @since 2.1
5998     */
5999    public static long[] removeElement(final long[] array, final long element) {
6000        final int index = indexOf(array, element);
6001        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6002    }
6003
6004    /**
6005     * Removes the first occurrence of the specified element from the
6006     * specified array. All subsequent elements are shifted to the left
6007     * (subtracts one from their indices). If the array doesn't contain
6008     * such an element, no elements are removed from the array.
6009     * <p>
6010     * This method returns a new array with the same elements of the input
6011     * array except the first occurrence of the specified element. The component
6012     * type of the returned array is always the same as that of the input
6013     * array.
6014     * </p>
6015     * <pre>
6016     * ArrayUtils.removeElement(null, 1)      = null
6017     * ArrayUtils.removeElement([], 1)        = []
6018     * ArrayUtils.removeElement([1], 2)       = [1]
6019     * ArrayUtils.removeElement([1, 3], 1)    = [3]
6020     * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
6021     * </pre>
6022     *
6023     * @param array the input array, may be {@code null}.
6024     * @param element  the element to be removed.
6025     * @return A new array containing the existing elements except the first
6026     *         occurrence of the specified element.
6027     * @since 2.1
6028     */
6029    public static short[] removeElement(final short[] array, final short element) {
6030        final int index = indexOf(array, element);
6031        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6032    }
6033
6034    /**
6035     * Removes the first occurrence of the specified element from the
6036     * specified array. All subsequent elements are shifted to the left
6037     * (subtracts one from their indices). If the array doesn't contain
6038     * such an element, no elements are removed from the array.
6039     * <p>
6040     * This method returns a new array with the same elements of the input
6041     * array except the first occurrence of the specified element. The component
6042     * type of the returned array is always the same as that of the input
6043     * array.
6044     * </p>
6045     * <pre>
6046     * ArrayUtils.removeElement(null, "a")            = null
6047     * ArrayUtils.removeElement([], "a")              = []
6048     * ArrayUtils.removeElement(["a"], "b")           = ["a"]
6049     * ArrayUtils.removeElement(["a", "b"], "a")      = ["b"]
6050     * ArrayUtils.removeElement(["a", "b", "a"], "a") = ["b", "a"]
6051     * </pre>
6052     *
6053     * @param <T> the component type of the array
6054     * @param array the input array, may be {@code null}.
6055     * @param element  the element to be removed, may be {@code null}.
6056     * @return A new array containing the existing elements except the first
6057     *         occurrence of the specified element.
6058     * @since 2.1
6059     */
6060    public static <T> T[] removeElement(final T[] array, final Object element) {
6061        final int index = indexOf(array, element);
6062        return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6063    }
6064
6065    /**
6066     * Removes occurrences of specified elements, in specified quantities,
6067     * from the specified array. All subsequent elements are shifted left.
6068     * For any element-to-be-removed specified in greater quantities than
6069     * contained in the original array, no change occurs beyond the
6070     * removal of the existing matching items.
6071     * <p>
6072     * This method returns a new array with the same elements of the input
6073     * array except for the earliest-encountered occurrences of the specified
6074     * elements. The component type of the returned array is always the same
6075     * as that of the input array.
6076     * </p>
6077     * <pre>
6078     * ArrayUtils.removeElements(null, true, false)               = null
6079     * ArrayUtils.removeElements([], true, false)                 = []
6080     * ArrayUtils.removeElements([true], false, false)            = [true]
6081     * ArrayUtils.removeElements([true, false], true, true)       = [false]
6082     * ArrayUtils.removeElements([true, false, true], true)       = [false, true]
6083     * ArrayUtils.removeElements([true, false, true], true, true) = [false]
6084     * </pre>
6085     *
6086     * @param array the input array, will not be modified, and may be {@code null}.
6087     * @param values  the values to be removed.
6088     * @return A new array containing the existing elements except the
6089     *         earliest-encountered occurrences of the specified elements.
6090     * @since 3.0.1
6091     */
6092    public static boolean[] removeElements(final boolean[] array, final boolean... values) {
6093        if (isEmpty(array) || isEmpty(values)) {
6094            return clone(array);
6095        }
6096        final HashMap<Boolean, MutableInt> occurrences = new HashMap<>(2); // only two possible values here
6097        for (final boolean v : values) {
6098            increment(occurrences, Boolean.valueOf(v));
6099        }
6100        final BitSet toRemove = new BitSet();
6101        for (int i = 0; i < array.length; i++) {
6102            final boolean key = array[i];
6103            final MutableInt count = occurrences.get(key);
6104            if (count != null) {
6105                if (count.decrementAndGet() == 0) {
6106                    occurrences.remove(key);
6107                }
6108                toRemove.set(i);
6109            }
6110        }
6111        return (boolean[]) removeAt(array, toRemove);
6112    }
6113
6114    /**
6115     * Removes occurrences of specified elements, in specified quantities,
6116     * from the specified array. All subsequent elements are shifted left.
6117     * For any element-to-be-removed specified in greater quantities than
6118     * contained in the original array, no change occurs beyond the
6119     * removal of the existing matching items.
6120     * <p>
6121     * This method returns a new array with the same elements of the input
6122     * array except for the earliest-encountered occurrences of the specified
6123     * elements. The component type of the returned array is always the same
6124     * as that of the input array.
6125     * </p>
6126     * <pre>
6127     * ArrayUtils.removeElements(null, 1, 2)      = null
6128     * ArrayUtils.removeElements([], 1, 2)        = []
6129     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6130     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6131     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6132     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6133     * </pre>
6134     *
6135     * @param array the input array, will not be modified, and may be {@code null}.
6136     * @param values  the values to be removed.
6137     * @return A new array containing the existing elements except the
6138     *         earliest-encountered occurrences of the specified elements.
6139     * @since 3.0.1
6140     */
6141    public static byte[] removeElements(final byte[] array, final byte... values) {
6142        if (isEmpty(array) || isEmpty(values)) {
6143            return clone(array);
6144        }
6145        final HashMap<Byte, MutableInt> occurrences = new HashMap<>(values.length);
6146        for (final byte v : values) {
6147            increment(occurrences, Byte.valueOf(v));
6148        }
6149        final BitSet toRemove = new BitSet();
6150        for (int i = 0; i < array.length; i++) {
6151            final byte key = array[i];
6152            final MutableInt count = occurrences.get(key);
6153            if (count != null) {
6154                if (count.decrementAndGet() == 0) {
6155                    occurrences.remove(key);
6156                }
6157                toRemove.set(i);
6158            }
6159        }
6160        return (byte[]) removeAt(array, toRemove);
6161    }
6162
6163    /**
6164     * Removes occurrences of specified elements, in specified quantities,
6165     * from the specified array. All subsequent elements are shifted left.
6166     * For any element-to-be-removed specified in greater quantities than
6167     * contained in the original array, no change occurs beyond the
6168     * removal of the existing matching items.
6169     * <p>
6170     * This method returns a new array with the same elements of the input
6171     * array except for the earliest-encountered occurrences of the specified
6172     * elements. The component type of the returned array is always the same
6173     * as that of the input array.
6174     * </p>
6175     * <pre>
6176     * ArrayUtils.removeElements(null, 1, 2)      = null
6177     * ArrayUtils.removeElements([], 1, 2)        = []
6178     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6179     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6180     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6181     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6182     * </pre>
6183     *
6184     * @param array the input array, will not be modified, and may be {@code null}.
6185     * @param values  the values to be removed.
6186     * @return A new array containing the existing elements except the
6187     *         earliest-encountered occurrences of the specified elements.
6188     * @since 3.0.1
6189     */
6190    public static char[] removeElements(final char[] array, final char... values) {
6191        if (isEmpty(array) || isEmpty(values)) {
6192            return clone(array);
6193        }
6194        final HashMap<Character, MutableInt> occurrences = new HashMap<>(values.length);
6195        for (final char v : values) {
6196            increment(occurrences, Character.valueOf(v));
6197        }
6198        final BitSet toRemove = new BitSet();
6199        for (int i = 0; i < array.length; i++) {
6200            final char key = array[i];
6201            final MutableInt count = occurrences.get(key);
6202            if (count != null) {
6203                if (count.decrementAndGet() == 0) {
6204                    occurrences.remove(key);
6205                }
6206                toRemove.set(i);
6207            }
6208        }
6209        return (char[]) removeAt(array, toRemove);
6210    }
6211
6212    /**
6213     * Removes occurrences of specified elements, in specified quantities,
6214     * from the specified array. All subsequent elements are shifted left.
6215     * For any element-to-be-removed specified in greater quantities than
6216     * contained in the original array, no change occurs beyond the
6217     * removal of the existing matching items.
6218     * <p>
6219     * This method returns a new array with the same elements of the input
6220     * array except for the earliest-encountered occurrences of the specified
6221     * elements. The component type of the returned array is always the same
6222     * as that of the input array.
6223     * </p>
6224     * <pre>
6225     * ArrayUtils.removeElements(null, 1, 2)      = null
6226     * ArrayUtils.removeElements([], 1, 2)        = []
6227     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6228     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6229     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6230     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6231     * </pre>
6232     *
6233     * @param array the input array, will not be modified, and may be {@code null}.
6234     * @param values  the values to be removed.
6235     * @return A new array containing the existing elements except the
6236     *         earliest-encountered occurrences of the specified elements.
6237     * @since 3.0.1
6238     */
6239    public static double[] removeElements(final double[] array, final double... values) {
6240        if (isEmpty(array) || isEmpty(values)) {
6241            return clone(array);
6242        }
6243        final HashMap<Double, MutableInt> occurrences = new HashMap<>(values.length);
6244        for (final double v : values) {
6245            increment(occurrences, Double.valueOf(v));
6246        }
6247        final BitSet toRemove = new BitSet();
6248        for (int i = 0; i < array.length; i++) {
6249            final double key = array[i];
6250            final MutableInt count = occurrences.get(key);
6251            if (count != null) {
6252                if (count.decrementAndGet() == 0) {
6253                    occurrences.remove(key);
6254                }
6255                toRemove.set(i);
6256            }
6257        }
6258        return (double[]) removeAt(array, toRemove);
6259    }
6260
6261    /**
6262     * Removes occurrences of specified elements, in specified quantities,
6263     * from the specified array. All subsequent elements are shifted left.
6264     * For any element-to-be-removed specified in greater quantities than
6265     * contained in the original array, no change occurs beyond the
6266     * removal of the existing matching items.
6267     * <p>
6268     * This method returns a new array with the same elements of the input
6269     * array except for the earliest-encountered occurrences of the specified
6270     * elements. The component type of the returned array is always the same
6271     * as that of the input array.
6272     * </p>
6273     * <pre>
6274     * ArrayUtils.removeElements(null, 1, 2)      = null
6275     * ArrayUtils.removeElements([], 1, 2)        = []
6276     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6277     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6278     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6279     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6280     * </pre>
6281     *
6282     * @param array the input array, will not be modified, and may be {@code null}.
6283     * @param values  the values to be removed.
6284     * @return A new array containing the existing elements except the
6285     *         earliest-encountered occurrences of the specified elements.
6286     * @since 3.0.1
6287     */
6288    public static float[] removeElements(final float[] array, final float... values) {
6289        if (isEmpty(array) || isEmpty(values)) {
6290            return clone(array);
6291        }
6292        final HashMap<Float, MutableInt> occurrences = new HashMap<>(values.length);
6293        for (final float v : values) {
6294            increment(occurrences, Float.valueOf(v));
6295        }
6296        final BitSet toRemove = new BitSet();
6297        for (int i = 0; i < array.length; i++) {
6298            final float key = array[i];
6299            final MutableInt count = occurrences.get(key);
6300            if (count != null) {
6301                if (count.decrementAndGet() == 0) {
6302                    occurrences.remove(key);
6303                }
6304                toRemove.set(i);
6305            }
6306        }
6307        return (float[]) removeAt(array, toRemove);
6308    }
6309
6310    /**
6311     * Removes occurrences of specified elements, in specified quantities,
6312     * from the specified array. All subsequent elements are shifted left.
6313     * For any element-to-be-removed specified in greater quantities than
6314     * contained in the original array, no change occurs beyond the
6315     * removal of the existing matching items.
6316     * <p>
6317     * This method returns a new array with the same elements of the input
6318     * array except for the earliest-encountered occurrences of the specified
6319     * elements. The component type of the returned array is always the same
6320     * as that of the input array.
6321     * </p>
6322     * <pre>
6323     * ArrayUtils.removeElements(null, 1, 2)      = null
6324     * ArrayUtils.removeElements([], 1, 2)        = []
6325     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6326     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6327     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6328     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6329     * </pre>
6330     *
6331     * @param array the input array, will not be modified, and may be {@code null}.
6332     * @param values  the values to be removed.
6333     * @return A new array containing the existing elements except the
6334     *         earliest-encountered occurrences of the specified elements.
6335     * @since 3.0.1
6336     */
6337    public static int[] removeElements(final int[] array, final int... values) {
6338        if (isEmpty(array) || isEmpty(values)) {
6339            return clone(array);
6340        }
6341        final HashMap<Integer, MutableInt> occurrences = new HashMap<>(values.length);
6342        for (final int v : values) {
6343            increment(occurrences, Integer.valueOf(v));
6344        }
6345        final BitSet toRemove = new BitSet();
6346        for (int i = 0; i < array.length; i++) {
6347            final int key = array[i];
6348            final MutableInt count = occurrences.get(key);
6349            if (count != null) {
6350                if (count.decrementAndGet() == 0) {
6351                    occurrences.remove(key);
6352                }
6353                toRemove.set(i);
6354            }
6355        }
6356        return (int[]) removeAt(array, toRemove);
6357    }
6358
6359    /**
6360     * Removes occurrences of specified elements, in specified quantities,
6361     * from the specified array. All subsequent elements are shifted left.
6362     * For any element-to-be-removed specified in greater quantities than
6363     * contained in the original array, no change occurs beyond the
6364     * removal of the existing matching items.
6365     * <p>
6366     * This method returns a new array with the same elements of the input
6367     * array except for the earliest-encountered occurrences of the specified
6368     * elements. The component type of the returned array is always the same
6369     * as that of the input array.
6370     * </p>
6371     * <pre>
6372     * ArrayUtils.removeElements(null, 1, 2)      = null
6373     * ArrayUtils.removeElements([], 1, 2)        = []
6374     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6375     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6376     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6377     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6378     * </pre>
6379     *
6380     * @param array the input array, will not be modified, and may be {@code null}.
6381     * @param values  the values to be removed.
6382     * @return A new array containing the existing elements except the
6383     *         earliest-encountered occurrences of the specified elements.
6384     * @since 3.0.1
6385     */
6386    public static long[] removeElements(final long[] array, final long... values) {
6387        if (isEmpty(array) || isEmpty(values)) {
6388            return clone(array);
6389        }
6390        final HashMap<Long, MutableInt> occurrences = new HashMap<>(values.length);
6391        for (final long v : values) {
6392            increment(occurrences, Long.valueOf(v));
6393        }
6394        final BitSet toRemove = new BitSet();
6395        for (int i = 0; i < array.length; i++) {
6396            final long key = array[i];
6397            final MutableInt count = occurrences.get(key);
6398            if (count != null) {
6399                if (count.decrementAndGet() == 0) {
6400                    occurrences.remove(key);
6401                }
6402                toRemove.set(i);
6403            }
6404        }
6405        return (long[]) removeAt(array, toRemove);
6406    }
6407
6408    /**
6409     * Removes occurrences of specified elements, in specified quantities,
6410     * from the specified array. All subsequent elements are shifted left.
6411     * For any element-to-be-removed specified in greater quantities than
6412     * contained in the original array, no change occurs beyond the
6413     * removal of the existing matching items.
6414     * <p>
6415     * This method returns a new array with the same elements of the input
6416     * array except for the earliest-encountered occurrences of the specified
6417     * elements. The component type of the returned array is always the same
6418     * as that of the input array.
6419     * </p>
6420     * <pre>
6421     * ArrayUtils.removeElements(null, 1, 2)      = null
6422     * ArrayUtils.removeElements([], 1, 2)        = []
6423     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6424     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6425     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6426     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6427     * </pre>
6428     *
6429     * @param array the input array, will not be modified, and may be {@code null}.
6430     * @param values  the values to be removed.
6431     * @return A new array containing the existing elements except the
6432     *         earliest-encountered occurrences of the specified elements.
6433     * @since 3.0.1
6434     */
6435    public static short[] removeElements(final short[] array, final short... values) {
6436        if (isEmpty(array) || isEmpty(values)) {
6437            return clone(array);
6438        }
6439        final HashMap<Short, MutableInt> occurrences = new HashMap<>(values.length);
6440        for (final short v : values) {
6441            increment(occurrences, Short.valueOf(v));
6442        }
6443        final BitSet toRemove = new BitSet();
6444        for (int i = 0; i < array.length; i++) {
6445            final short key = array[i];
6446            final MutableInt count = occurrences.get(key);
6447            if (count != null) {
6448                if (count.decrementAndGet() == 0) {
6449                    occurrences.remove(key);
6450                }
6451                toRemove.set(i);
6452            }
6453        }
6454        return (short[]) removeAt(array, toRemove);
6455    }
6456
6457    /**
6458     * Removes occurrences of specified elements, in specified quantities,
6459     * from the specified array. All subsequent elements are shifted left.
6460     * For any element-to-be-removed specified in greater quantities than
6461     * contained in the original array, no change occurs beyond the
6462     * removal of the existing matching items.
6463     * <p>
6464     * This method returns a new array with the same elements of the input
6465     * array except for the earliest-encountered occurrences of the specified
6466     * elements. The component type of the returned array is always the same
6467     * as that of the input array.
6468     * </p>
6469     * <pre>
6470     * ArrayUtils.removeElements(null, "a", "b")            = null
6471     * ArrayUtils.removeElements([], "a", "b")              = []
6472     * ArrayUtils.removeElements(["a"], "b", "c")           = ["a"]
6473     * ArrayUtils.removeElements(["a", "b"], "a", "c")      = ["b"]
6474     * ArrayUtils.removeElements(["a", "b", "a"], "a")      = ["b", "a"]
6475     * ArrayUtils.removeElements(["a", "b", "a"], "a", "a") = ["b"]
6476     * </pre>
6477     *
6478     * @param <T> the component type of the array
6479     * @param array the input array, will not be modified, and may be {@code null}.
6480     * @param values  the values to be removed.
6481     * @return A new array containing the existing elements except the
6482     *         earliest-encountered occurrences of the specified elements.
6483     * @since 3.0.1
6484     */
6485    @SafeVarargs
6486    public static <T> T[] removeElements(final T[] array, final T... values) {
6487        if (isEmpty(array) || isEmpty(values)) {
6488            return clone(array);
6489        }
6490        final HashMap<T, MutableInt> occurrences = new HashMap<>(values.length);
6491        for (final T v : values) {
6492            increment(occurrences, v);
6493        }
6494        final BitSet toRemove = new BitSet();
6495        for (int i = 0; i < array.length; i++) {
6496            final T key = array[i];
6497            final MutableInt count = occurrences.get(key);
6498            if (count != null) {
6499                if (count.decrementAndGet() == 0) {
6500                    occurrences.remove(key);
6501                }
6502                toRemove.set(i);
6503            }
6504        }
6505        @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
6506        final T[] result = (T[]) removeAt(array, toRemove);
6507        return result;
6508    }
6509
6510    /**
6511     * Reverses the order of the given array.
6512     * <p>
6513     * This method does nothing for a {@code null} input array.
6514     * </p>
6515     *
6516     * @param array  the array to reverse, may be {@code null}.
6517     */
6518    public static void reverse(final boolean[] array) {
6519        if (array == null) {
6520            return;
6521        }
6522        reverse(array, 0, array.length);
6523    }
6524
6525    /**
6526     * Reverses the order of the given array in the given range.
6527     * <p>
6528     * This method does nothing for a {@code null} input array.
6529     * </p>
6530     *
6531     * @param array
6532     *            the array to reverse, may be {@code null}.
6533     * @param startIndexInclusive
6534     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6535     *            change.
6536     * @param endIndexExclusive
6537     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6538     *            change. Overvalue (&gt;array.length) is demoted to array length.
6539     * @since 3.2
6540     */
6541    public static void reverse(final boolean[] array, final int startIndexInclusive, final int endIndexExclusive) {
6542        if (array == null) {
6543            return;
6544        }
6545        int i = Math.max(startIndexInclusive, 0);
6546        int j = Math.min(array.length, endIndexExclusive) - 1;
6547        boolean tmp;
6548        while (j > i) {
6549            tmp = array[j];
6550            array[j] = array[i];
6551            array[i] = tmp;
6552            j--;
6553            i++;
6554        }
6555    }
6556
6557    /**
6558     * Reverses the order of the given array.
6559     * <p>
6560     * This method does nothing for a {@code null} input array.
6561     * </p>
6562     *
6563     * @param array  the array to reverse, may be {@code null}
6564     */
6565    public static void reverse(final byte[] array) {
6566        if (array != null) {
6567            reverse(array, 0, array.length);
6568        }
6569    }
6570
6571    /**
6572     * Reverses the order of the given array in the given range.
6573     * <p>
6574     * This method does nothing for a {@code null} input array.
6575     * </p>
6576     *
6577     * @param array
6578     *            the array to reverse, may be {@code null}
6579     * @param startIndexInclusive
6580     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6581     *            change.
6582     * @param endIndexExclusive
6583     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6584     *            change. Overvalue (&gt;array.length) is demoted to array length.
6585     * @since 3.2
6586     */
6587    public static void reverse(final byte[] array, final int startIndexInclusive, final int endIndexExclusive) {
6588        if (array == null) {
6589            return;
6590        }
6591        int i = Math.max(startIndexInclusive, 0);
6592        int j = Math.min(array.length, endIndexExclusive) - 1;
6593        byte tmp;
6594        while (j > i) {
6595            tmp = array[j];
6596            array[j] = array[i];
6597            array[i] = tmp;
6598            j--;
6599            i++;
6600        }
6601    }
6602
6603    /**
6604     * Reverses the order of the given array.
6605     * <p>
6606     * This method does nothing for a {@code null} input array.
6607     * </p>
6608     *
6609     * @param array  the array to reverse, may be {@code null}
6610     */
6611    public static void reverse(final char[] array) {
6612        if (array != null) {
6613            reverse(array, 0, array.length);
6614        }
6615    }
6616
6617    /**
6618     * Reverses the order of the given array in the given range.
6619     * <p>
6620     * This method does nothing for a {@code null} input array.
6621     * </p>
6622     *
6623     * @param array
6624     *            the array to reverse, may be {@code null}
6625     * @param startIndexInclusive
6626     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6627     *            change.
6628     * @param endIndexExclusive
6629     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6630     *            change. Overvalue (&gt;array.length) is demoted to array length.
6631     * @since 3.2
6632     */
6633    public static void reverse(final char[] array, final int startIndexInclusive, final int endIndexExclusive) {
6634        if (array == null) {
6635            return;
6636        }
6637        int i = Math.max(startIndexInclusive, 0);
6638        int j = Math.min(array.length, endIndexExclusive) - 1;
6639        char tmp;
6640        while (j > i) {
6641            tmp = array[j];
6642            array[j] = array[i];
6643            array[i] = tmp;
6644            j--;
6645            i++;
6646        }
6647    }
6648
6649    /**
6650     * Reverses the order of the given array.
6651     * <p>
6652     * This method does nothing for a {@code null} input array.
6653     * </p>
6654     *
6655     * @param array  the array to reverse, may be {@code null}
6656     */
6657    public static void reverse(final double[] array) {
6658        if (array != null) {
6659            reverse(array, 0, array.length);
6660        }
6661    }
6662
6663    /**
6664     * Reverses the order of the given array in the given range.
6665     * <p>
6666     * This method does nothing for a {@code null} input array.
6667     * </p>
6668     *
6669     * @param array
6670     *            the array to reverse, may be {@code null}
6671     * @param startIndexInclusive
6672     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6673     *            change.
6674     * @param endIndexExclusive
6675     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6676     *            change. Overvalue (&gt;array.length) is demoted to array length.
6677     * @since 3.2
6678     */
6679    public static void reverse(final double[] array, final int startIndexInclusive, final int endIndexExclusive) {
6680        if (array == null) {
6681            return;
6682        }
6683        int i = Math.max(startIndexInclusive, 0);
6684        int j = Math.min(array.length, endIndexExclusive) - 1;
6685        double tmp;
6686        while (j > i) {
6687            tmp = array[j];
6688            array[j] = array[i];
6689            array[i] = tmp;
6690            j--;
6691            i++;
6692        }
6693    }
6694
6695    /**
6696     * Reverses the order of the given array.
6697     * <p>
6698     * This method does nothing for a {@code null} input array.
6699     * </p>
6700     *
6701     * @param array  the array to reverse, may be {@code null}.
6702     */
6703    public static void reverse(final float[] array) {
6704        if (array != null) {
6705            reverse(array, 0, array.length);
6706        }
6707    }
6708
6709    /**
6710     * Reverses the order of the given array in the given range.
6711     * <p>
6712     * This method does nothing for a {@code null} input array.
6713     * </p>
6714     *
6715     * @param array
6716     *            the array to reverse, may be {@code null}.
6717     * @param startIndexInclusive
6718     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6719     *            change.
6720     * @param endIndexExclusive
6721     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6722     *            change. Overvalue (&gt;array.length) is demoted to array length.
6723     * @since 3.2
6724     */
6725    public static void reverse(final float[] array, final int startIndexInclusive, final int endIndexExclusive) {
6726        if (array == null) {
6727            return;
6728        }
6729        int i = Math.max(startIndexInclusive, 0);
6730        int j = Math.min(array.length, endIndexExclusive) - 1;
6731        float tmp;
6732        while (j > i) {
6733            tmp = array[j];
6734            array[j] = array[i];
6735            array[i] = tmp;
6736            j--;
6737            i++;
6738        }
6739    }
6740
6741    /**
6742     * Reverses the order of the given array.
6743     * <p>
6744     * This method does nothing for a {@code null} input array.
6745     * </p>
6746     *
6747     * @param array  the array to reverse, may be {@code null}.
6748     */
6749    public static void reverse(final int[] array) {
6750        if (array != null) {
6751            reverse(array, 0, array.length);
6752        }
6753    }
6754
6755    /**
6756     * Reverses the order of the given array in the given range.
6757     * <p>
6758     * This method does nothing for a {@code null} input array.
6759     * </p>
6760     *
6761     * @param array
6762     *            the array to reverse, may be {@code null}.
6763     * @param startIndexInclusive
6764     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6765     *            change.
6766     * @param endIndexExclusive
6767     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6768     *            change. Overvalue (&gt;array.length) is demoted to array length.
6769     * @since 3.2
6770     */
6771    public static void reverse(final int[] array, final int startIndexInclusive, final int endIndexExclusive) {
6772        if (array == null) {
6773            return;
6774        }
6775        int i = Math.max(startIndexInclusive, 0);
6776        int j = Math.min(array.length, endIndexExclusive) - 1;
6777        int tmp;
6778        while (j > i) {
6779            tmp = array[j];
6780            array[j] = array[i];
6781            array[i] = tmp;
6782            j--;
6783            i++;
6784        }
6785    }
6786
6787    /**
6788     * Reverses the order of the given array.
6789     * <p>
6790     * This method does nothing for a {@code null} input array.
6791     * </p>
6792     *
6793     * @param array  the array to reverse, may be {@code null}.
6794     */
6795    public static void reverse(final long[] array) {
6796        if (array != null) {
6797            reverse(array, 0, array.length);
6798        }
6799    }
6800
6801    /**
6802     * Reverses the order of the given array in the given range.
6803     * <p>
6804     * This method does nothing for a {@code null} input array.
6805     * </p>
6806     *
6807     * @param array
6808     *            the array to reverse, may be {@code null}.
6809     * @param startIndexInclusive
6810     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6811     *            change.
6812     * @param endIndexExclusive
6813     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6814     *            change. Overvalue (&gt;array.length) is demoted to array length.
6815     * @since 3.2
6816     */
6817    public static void reverse(final long[] array, final int startIndexInclusive, final int endIndexExclusive) {
6818        if (array == null) {
6819            return;
6820        }
6821        int i = Math.max(startIndexInclusive, 0);
6822        int j = Math.min(array.length, endIndexExclusive) - 1;
6823        long tmp;
6824        while (j > i) {
6825            tmp = array[j];
6826            array[j] = array[i];
6827            array[i] = tmp;
6828            j--;
6829            i++;
6830        }
6831    }
6832
6833    /**
6834     * Reverses the order of the given array.
6835     * <p>
6836     * There is no special handling for multi-dimensional arrays.
6837     * </p>
6838     * <p>
6839     * This method does nothing for a {@code null} input array.
6840     * </p>
6841     *
6842     * @param array  the array to reverse, may be {@code null}.
6843     */
6844    public static void reverse(final Object[] array) {
6845        if (array != null) {
6846            reverse(array, 0, array.length);
6847        }
6848    }
6849
6850    /**
6851     * Reverses the order of the given array in the given range.
6852     * <p>
6853     * This method does nothing for a {@code null} input array.
6854     * </p>
6855     *
6856     * @param array
6857     *            the array to reverse, may be {@code null}.
6858     * @param startIndexInclusive
6859     *            the starting index. Under value (&lt;0) is promoted to 0, over value (&gt;array.length) results in no
6860     *            change.
6861     * @param endIndexExclusive
6862     *            elements up to endIndex-1 are reversed in the array. Under value (&lt; start index) results in no
6863     *            change. Over value (&gt;array.length) is demoted to array length.
6864     * @since 3.2
6865     */
6866    public static void reverse(final Object[] array, final int startIndexInclusive, final int endIndexExclusive) {
6867        if (array == null) {
6868            return;
6869        }
6870        int i = Math.max(startIndexInclusive, 0);
6871        int j = Math.min(array.length, endIndexExclusive) - 1;
6872        Object tmp;
6873        while (j > i) {
6874            tmp = array[j];
6875            array[j] = array[i];
6876            array[i] = tmp;
6877            j--;
6878            i++;
6879        }
6880    }
6881
6882    /**
6883     * Reverses the order of the given array.
6884     * <p>
6885     * This method does nothing for a {@code null} input array.
6886     * </p>
6887     *
6888     * @param array  the array to reverse, may be {@code null}.
6889     */
6890    public static void reverse(final short[] array) {
6891        if (array != null) {
6892            reverse(array, 0, array.length);
6893        }
6894    }
6895
6896    /**
6897     * Reverses the order of the given array in the given range.
6898     * <p>
6899     * This method does nothing for a {@code null} input array.
6900     * </p>
6901     *
6902     * @param array
6903     *            the array to reverse, may be {@code null}.
6904     * @param startIndexInclusive
6905     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6906     *            change.
6907     * @param endIndexExclusive
6908     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6909     *            change. Overvalue (&gt;array.length) is demoted to array length.
6910     * @since 3.2
6911     */
6912    public static void reverse(final short[] array, final int startIndexInclusive, final int endIndexExclusive) {
6913        if (array == null) {
6914            return;
6915        }
6916        int i = Math.max(startIndexInclusive, 0);
6917        int j = Math.min(array.length, endIndexExclusive) - 1;
6918        short tmp;
6919        while (j > i) {
6920            tmp = array[j];
6921            array[j] = array[i];
6922            array[i] = tmp;
6923            j--;
6924            i++;
6925        }
6926    }
6927
6928    /**
6929     * Sets all elements of the specified array, using the provided generator supplier to compute each element.
6930     * <p>
6931     * If the generator supplier throws an exception, it is relayed to the caller and the array is left in an indeterminate
6932     * state.
6933     * </p>
6934     *
6935     * @param <T> type of elements of the array, may be {@code null}.
6936     * @param array array to be initialized, may be {@code null}.
6937     * @param generator a function accepting an index and producing the desired value for that position.
6938     * @return the input array
6939     * @since 3.13.0
6940     */
6941    public static <T> T[] setAll(final T[] array, final IntFunction<? extends T> generator) {
6942        if (array != null && generator != null) {
6943            Arrays.setAll(array, generator);
6944        }
6945        return array;
6946    }
6947
6948    /**
6949     * Sets all elements of the specified array, using the provided generator supplier to compute each element.
6950     * <p>
6951     * If the generator supplier throws an exception, it is relayed to the caller and the array is left in an indeterminate
6952     * state.
6953     * </p>
6954     *
6955     * @param <T> type of elements of the array, may be {@code null}.
6956     * @param array array to be initialized, may be {@code null}.
6957     * @param generator a function accepting an index and producing the desired value for that position.
6958     * @return the input array
6959     * @since 3.13.0
6960     */
6961    public static <T> T[] setAll(final T[] array, final Supplier<? extends T> generator) {
6962        if (array != null && generator != null) {
6963            for (int i = 0; i < array.length; i++) {
6964                array[i] = generator.get();
6965            }
6966        }
6967        return array;
6968    }
6969
6970    /**
6971     * Shifts the order of the given boolean array.
6972     *
6973     * <p>There is no special handling for multi-dimensional arrays. This method
6974     * does nothing for {@code null} or empty input arrays.</p>
6975     *
6976     * @param array  the array to shift, may be {@code null}.
6977     * @param offset
6978     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
6979     *          rotate, than the effective offset is modulo the number of elements to rotate.
6980     * @since 3.5
6981     */
6982    public static void shift(final boolean[] array, final int offset) {
6983        if (array != null) {
6984            shift(array, 0, array.length, offset);
6985        }
6986    }
6987
6988    /**
6989     * Shifts the order of a series of elements in the given boolean array.
6990     *
6991     * <p>There is no special handling for multi-dimensional arrays. This method
6992     * does nothing for {@code null} or empty input arrays.</p>
6993     *
6994     * @param array
6995     *            the array to shift, may be {@code null}.
6996     * @param startIndexInclusive
6997     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6998     *            change.
6999     * @param endIndexExclusive
7000     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7001     *            change. Overvalue (&gt;array.length) is demoted to array length.
7002     * @param offset
7003     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7004     *          rotate, than the effective offset is modulo the number of elements to rotate.
7005     * @since 3.5
7006     */
7007    public static void shift(final boolean[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7008        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7009            return;
7010        }
7011        startIndexInclusive = max0(startIndexInclusive);
7012        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7013        int n = endIndexExclusive - startIndexInclusive;
7014        if (n <= 1) {
7015            return;
7016        }
7017        offset %= n;
7018        if (offset < 0) {
7019            offset += n;
7020        }
7021        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7022        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7023        while (n > 1 && offset > 0) {
7024            final int nOffset = n - offset;
7025            if (offset > nOffset) {
7026                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7027                n = offset;
7028                offset -= nOffset;
7029            } else if (offset < nOffset) {
7030                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7031                startIndexInclusive += offset;
7032                n = nOffset;
7033            } else {
7034                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7035                break;
7036            }
7037        }
7038    }
7039
7040    /**
7041     * Shifts the order of the given byte array.
7042     *
7043     * <p>There is no special handling for multi-dimensional arrays. This method
7044     * does nothing for {@code null} or empty input arrays.</p>
7045     *
7046     * @param array  the array to shift, may be {@code null}.
7047     * @param offset
7048     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7049     *          rotate, than the effective offset is modulo the number of elements to rotate.
7050     * @since 3.5
7051     */
7052    public static void shift(final byte[] array, final int offset) {
7053        if (array != null) {
7054            shift(array, 0, array.length, offset);
7055        }
7056    }
7057
7058    /**
7059     * Shifts the order of a series of elements in the given byte array.
7060     *
7061     * <p>There is no special handling for multi-dimensional arrays. This method
7062     * does nothing for {@code null} or empty input arrays.</p>
7063     *
7064     * @param array
7065     *            the array to shift, may be {@code null}.
7066     * @param startIndexInclusive
7067     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7068     *            change.
7069     * @param endIndexExclusive
7070     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7071     *            change. Overvalue (&gt;array.length) is demoted to array length.
7072     * @param offset
7073     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7074     *          rotate, than the effective offset is modulo the number of elements to rotate.
7075     * @since 3.5
7076     */
7077    public static void shift(final byte[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7078        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7079            return;
7080        }
7081        startIndexInclusive = max0(startIndexInclusive);
7082        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7083        int n = endIndexExclusive - startIndexInclusive;
7084        if (n <= 1) {
7085            return;
7086        }
7087        offset %= n;
7088        if (offset < 0) {
7089            offset += n;
7090        }
7091        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7092        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7093        while (n > 1 && offset > 0) {
7094            final int nOffset = n - offset;
7095            if (offset > nOffset) {
7096                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7097                n = offset;
7098                offset -= nOffset;
7099            } else if (offset < nOffset) {
7100                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7101                startIndexInclusive += offset;
7102                n = nOffset;
7103            } else {
7104                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7105                break;
7106            }
7107        }
7108    }
7109
7110    /**
7111     * Shifts the order of the given char array.
7112     *
7113     * <p>There is no special handling for multi-dimensional arrays. This method
7114     * does nothing for {@code null} or empty input arrays.</p>
7115     *
7116     * @param array  the array to shift, may be {@code null}.
7117     * @param offset
7118     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7119     *          rotate, than the effective offset is modulo the number of elements to rotate.
7120     * @since 3.5
7121     */
7122    public static void shift(final char[] array, final int offset) {
7123        if (array != null) {
7124            shift(array, 0, array.length, offset);
7125        }
7126    }
7127
7128    /**
7129     * Shifts the order of a series of elements in the given char array.
7130     *
7131     * <p>There is no special handling for multi-dimensional arrays. This method
7132     * does nothing for {@code null} or empty input arrays.</p>
7133     *
7134     * @param array
7135     *            the array to shift, may be {@code null}.
7136     * @param startIndexInclusive
7137     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7138     *            change.
7139     * @param endIndexExclusive
7140     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7141     *            change. Overvalue (&gt;array.length) is demoted to array length.
7142     * @param offset
7143     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7144     *          rotate, than the effective offset is modulo the number of elements to rotate.
7145     * @since 3.5
7146     */
7147    public static void shift(final char[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7148        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7149            return;
7150        }
7151        startIndexInclusive = max0(startIndexInclusive);
7152        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7153        int n = endIndexExclusive - startIndexInclusive;
7154        if (n <= 1) {
7155            return;
7156        }
7157        offset %= n;
7158        if (offset < 0) {
7159            offset += n;
7160        }
7161        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7162        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7163        while (n > 1 && offset > 0) {
7164            final int nOffset = n - offset;
7165            if (offset > nOffset) {
7166                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7167                n = offset;
7168                offset -= nOffset;
7169            } else if (offset < nOffset) {
7170                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7171                startIndexInclusive += offset;
7172                n = nOffset;
7173            } else {
7174                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7175                break;
7176            }
7177        }
7178    }
7179
7180    /**
7181     * Shifts the order of the given double array.
7182     *
7183     * <p>There is no special handling for multi-dimensional arrays. This method
7184     * does nothing for {@code null} or empty input arrays.</p>
7185     *
7186     * @param array  the array to shift, may be {@code null}.
7187     * @param offset
7188     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7189     *          rotate, than the effective offset is modulo the number of elements to rotate.
7190     * @since 3.5
7191     */
7192    public static void shift(final double[] array, final int offset) {
7193        if (array != null) {
7194            shift(array, 0, array.length, offset);
7195        }
7196    }
7197
7198    /**
7199     * Shifts the order of a series of elements in the given double array.
7200     *
7201     * <p>There is no special handling for multi-dimensional arrays. This method
7202     * does nothing for {@code null} or empty input arrays.</p>
7203     *
7204     * @param array
7205     *            the array to shift, may be {@code null}.
7206     * @param startIndexInclusive
7207     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7208     *            change.
7209     * @param endIndexExclusive
7210     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7211     *            change. Overvalue (&gt;array.length) is demoted to array length.
7212     * @param offset
7213     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7214     *          rotate, than the effective offset is modulo the number of elements to rotate.
7215     * @since 3.5
7216     */
7217    public static void shift(final double[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7218        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7219            return;
7220        }
7221        startIndexInclusive = max0(startIndexInclusive);
7222        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7223        int n = endIndexExclusive - startIndexInclusive;
7224        if (n <= 1) {
7225            return;
7226        }
7227        offset %= n;
7228        if (offset < 0) {
7229            offset += n;
7230        }
7231        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7232        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7233        while (n > 1 && offset > 0) {
7234            final int nOffset = n - offset;
7235            if (offset > nOffset) {
7236                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7237                n = offset;
7238                offset -= nOffset;
7239            } else if (offset < nOffset) {
7240                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7241                startIndexInclusive += offset;
7242                n = nOffset;
7243            } else {
7244                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7245                break;
7246            }
7247        }
7248    }
7249
7250    /**
7251     * Shifts the order of the given float array.
7252     *
7253     * <p>There is no special handling for multi-dimensional arrays. This method
7254     * does nothing for {@code null} or empty input arrays.</p>
7255     *
7256     * @param array  the array to shift, may be {@code null}.
7257     * @param offset
7258     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7259     *          rotate, than the effective offset is modulo the number of elements to rotate.
7260     * @since 3.5
7261     */
7262    public static void shift(final float[] array, final int offset) {
7263        if (array != null) {
7264            shift(array, 0, array.length, offset);
7265        }
7266    }
7267
7268    /**
7269     * Shifts the order of a series of elements in the given float array.
7270     *
7271     * <p>There is no special handling for multi-dimensional arrays. This method
7272     * does nothing for {@code null} or empty input arrays.</p>
7273     *
7274     * @param array
7275     *            the array to shift, may be {@code null}.
7276     * @param startIndexInclusive
7277     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7278     *            change.
7279     * @param endIndexExclusive
7280     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7281     *            change. Overvalue (&gt;array.length) is demoted to array length.
7282     * @param offset
7283     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7284     *          rotate, than the effective offset is modulo the number of elements to rotate.
7285     * @since 3.5
7286     */
7287    public static void shift(final float[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7288        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7289            return;
7290        }
7291        startIndexInclusive = max0(startIndexInclusive);
7292        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7293        int n = endIndexExclusive - startIndexInclusive;
7294        if (n <= 1) {
7295            return;
7296        }
7297        offset %= n;
7298        if (offset < 0) {
7299            offset += n;
7300        }
7301        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7302        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7303        while (n > 1 && offset > 0) {
7304            final int nOffset = n - offset;
7305            if (offset > nOffset) {
7306                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7307                n = offset;
7308                offset -= nOffset;
7309            } else if (offset < nOffset) {
7310                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7311                startIndexInclusive += offset;
7312                n = nOffset;
7313            } else {
7314                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7315                break;
7316            }
7317        }
7318    }
7319
7320    /**
7321     * Shifts the order of the given int array.
7322     *
7323     * <p>There is no special handling for multi-dimensional arrays. This method
7324     * does nothing for {@code null} or empty input arrays.</p>
7325     *
7326     * @param array  the array to shift, may be {@code null}.
7327     * @param offset
7328     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7329     *          rotate, than the effective offset is modulo the number of elements to rotate.
7330     * @since 3.5
7331     */
7332    public static void shift(final int[] array, final int offset) {
7333        if (array != null) {
7334            shift(array, 0, array.length, offset);
7335        }
7336    }
7337
7338    /**
7339     * Shifts the order of a series of elements in the given int array.
7340     *
7341     * <p>There is no special handling for multi-dimensional arrays. This method
7342     * does nothing for {@code null} or empty input arrays.</p>
7343     *
7344     * @param array
7345     *            the array to shift, may be {@code null}.
7346     * @param startIndexInclusive
7347     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7348     *            change.
7349     * @param endIndexExclusive
7350     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7351     *            change. Overvalue (&gt;array.length) is demoted to array length.
7352     * @param offset
7353     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7354     *          rotate, than the effective offset is modulo the number of elements to rotate.
7355     * @since 3.5
7356     */
7357    public static void shift(final int[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7358        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7359            return;
7360        }
7361        startIndexInclusive = max0(startIndexInclusive);
7362        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7363        int n = endIndexExclusive - startIndexInclusive;
7364        if (n <= 1) {
7365            return;
7366        }
7367        offset %= n;
7368        if (offset < 0) {
7369            offset += n;
7370        }
7371        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7372        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7373        while (n > 1 && offset > 0) {
7374            final int nOffset = n - offset;
7375            if (offset > nOffset) {
7376                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7377                n = offset;
7378                offset -= nOffset;
7379            } else if (offset < nOffset) {
7380                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7381                startIndexInclusive += offset;
7382                n = nOffset;
7383            } else {
7384                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7385                break;
7386            }
7387        }
7388    }
7389
7390    /**
7391     * Shifts the order of the given long array.
7392     *
7393     * <p>There is no special handling for multi-dimensional arrays. This method
7394     * does nothing for {@code null} or empty input arrays.</p>
7395     *
7396     * @param array  the array to shift, may be {@code null}.
7397     * @param offset
7398     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7399     *          rotate, than the effective offset is modulo the number of elements to rotate.
7400     * @since 3.5
7401     */
7402    public static void shift(final long[] array, final int offset) {
7403        if (array != null) {
7404            shift(array, 0, array.length, offset);
7405        }
7406    }
7407
7408    /**
7409     * Shifts the order of a series of elements in the given long array.
7410     *
7411     * <p>There is no special handling for multi-dimensional arrays. This method
7412     * does nothing for {@code null} or empty input arrays.</p>
7413     *
7414     * @param array
7415     *            the array to shift, may be {@code null}.
7416     * @param startIndexInclusive
7417     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7418     *            change.
7419     * @param endIndexExclusive
7420     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7421     *            change. Overvalue (&gt;array.length) is demoted to array length.
7422     * @param offset
7423     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7424     *          rotate, than the effective offset is modulo the number of elements to rotate.
7425     * @since 3.5
7426     */
7427    public static void shift(final long[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7428        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7429            return;
7430        }
7431        startIndexInclusive = max0(startIndexInclusive);
7432        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7433        int n = endIndexExclusive - startIndexInclusive;
7434        if (n <= 1) {
7435            return;
7436        }
7437        offset %= n;
7438        if (offset < 0) {
7439            offset += n;
7440        }
7441        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7442        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7443        while (n > 1 && offset > 0) {
7444            final int nOffset = n - offset;
7445            if (offset > nOffset) {
7446                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7447                n = offset;
7448                offset -= nOffset;
7449            } else if (offset < nOffset) {
7450                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7451                startIndexInclusive += offset;
7452                n = nOffset;
7453            } else {
7454                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7455                break;
7456            }
7457        }
7458    }
7459
7460    /**
7461     * Shifts the order of the given array.
7462     *
7463     * <p>There is no special handling for multi-dimensional arrays. This method
7464     * does nothing for {@code null} or empty input arrays.</p>
7465     *
7466     * @param array  the array to shift, may be {@code null}.
7467     * @param offset
7468     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7469     *          rotate, than the effective offset is modulo the number of elements to rotate.
7470     * @since 3.5
7471     */
7472    public static void shift(final Object[] array, final int offset) {
7473        if (array != null) {
7474            shift(array, 0, array.length, offset);
7475        }
7476    }
7477
7478    /**
7479     * Shifts the order of a series of elements in the given array.
7480     *
7481     * <p>There is no special handling for multi-dimensional arrays. This method
7482     * does nothing for {@code null} or empty input arrays.</p>
7483     *
7484     * @param array
7485     *            the array to shift, may be {@code null}.
7486     * @param startIndexInclusive
7487     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7488     *            change.
7489     * @param endIndexExclusive
7490     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7491     *            change. Overvalue (&gt;array.length) is demoted to array length.
7492     * @param offset
7493     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7494     *          rotate, than the effective offset is modulo the number of elements to rotate.
7495     * @since 3.5
7496     */
7497    public static void shift(final Object[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7498        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7499            return;
7500        }
7501        startIndexInclusive = max0(startIndexInclusive);
7502        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7503        int n = endIndexExclusive - startIndexInclusive;
7504        if (n <= 1) {
7505            return;
7506        }
7507        offset %= n;
7508        if (offset < 0) {
7509            offset += n;
7510        }
7511        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7512        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7513        while (n > 1 && offset > 0) {
7514            final int nOffset = n - offset;
7515            if (offset > nOffset) {
7516                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7517                n = offset;
7518                offset -= nOffset;
7519            } else if (offset < nOffset) {
7520                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7521                startIndexInclusive += offset;
7522                n = nOffset;
7523            } else {
7524                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7525                break;
7526            }
7527        }
7528    }
7529
7530    /**
7531     * Shifts the order of the given short array.
7532     *
7533     * <p>There is no special handling for multi-dimensional arrays. This method
7534     * does nothing for {@code null} or empty input arrays.</p>
7535     *
7536     * @param array  the array to shift, may be {@code null}.
7537     * @param offset
7538     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7539     *          rotate, than the effective offset is modulo the number of elements to rotate.
7540     * @since 3.5
7541     */
7542    public static void shift(final short[] array, final int offset) {
7543        if (array != null) {
7544            shift(array, 0, array.length, offset);
7545        }
7546    }
7547
7548    /**
7549     * Shifts the order of a series of elements in the given short array.
7550     *
7551     * <p>There is no special handling for multi-dimensional arrays. This method
7552     * does nothing for {@code null} or empty input arrays.</p>
7553     *
7554     * @param array
7555     *            the array to shift, may be {@code null}.
7556     * @param startIndexInclusive
7557     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7558     *            change.
7559     * @param endIndexExclusive
7560     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7561     *            change. Overvalue (&gt;array.length) is demoted to array length.
7562     * @param offset
7563     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7564     *          rotate, than the effective offset is modulo the number of elements to rotate.
7565     * @since 3.5
7566     */
7567    public static void shift(final short[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7568        if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7569            return;
7570        }
7571        startIndexInclusive = max0(startIndexInclusive);
7572        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7573        int n = endIndexExclusive - startIndexInclusive;
7574        if (n <= 1) {
7575            return;
7576        }
7577        offset %= n;
7578        if (offset < 0) {
7579            offset += n;
7580        }
7581        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7582        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7583        while (n > 1 && offset > 0) {
7584            final int nOffset = n - offset;
7585            if (offset > nOffset) {
7586                swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7587                n = offset;
7588                offset -= nOffset;
7589            } else if (offset < nOffset) {
7590                swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7591                startIndexInclusive += offset;
7592                n = nOffset;
7593            } else {
7594                swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7595                break;
7596            }
7597        }
7598    }
7599
7600    /**
7601     * 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
7602     * algorithm</a>.
7603     * <p>
7604     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7605     * </p>
7606     * <p>
7607     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7608     * with a {@link SecureRandom} argument.
7609     * </p>
7610     *
7611     * @param array the array to shuffle.
7612     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7613     * @since 3.6
7614     */
7615    public static void shuffle(final boolean[] array) {
7616        shuffle(array, random());
7617    }
7618
7619    /**
7620     * 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
7621     * algorithm</a>.
7622     *
7623     * @param array  the array to shuffle
7624     * @param random the source of randomness used to permute the elements
7625     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7626     * @since 3.6
7627     */
7628    public static void shuffle(final boolean[] array, final Random random) {
7629        for (int i = array.length; i > 1; i--) {
7630            swap(array, i - 1, random.nextInt(i), 1);
7631        }
7632    }
7633
7634    /**
7635     * 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
7636     * algorithm</a>.
7637     * <p>
7638     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7639     * </p>
7640     * <p>
7641     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7642     * with a {@link SecureRandom} argument.
7643     * </p>
7644     *
7645     * @param array the array to shuffle.
7646     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7647     * @since 3.6
7648     */
7649    public static void shuffle(final byte[] array) {
7650        shuffle(array, random());
7651    }
7652
7653    /**
7654     * 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
7655     * algorithm</a>.
7656     *
7657     * @param array  the array to shuffle
7658     * @param random the source of randomness used to permute the elements
7659     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7660     * @since 3.6
7661     */
7662    public static void shuffle(final byte[] array, final Random random) {
7663        for (int i = array.length; i > 1; i--) {
7664            swap(array, i - 1, random.nextInt(i), 1);
7665        }
7666    }
7667
7668    /**
7669     * 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
7670     * algorithm</a>.
7671     * <p>
7672     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7673     * </p>
7674     * <p>
7675     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7676     * with a {@link SecureRandom} argument.
7677     * </p>
7678     *
7679     * @param array the array to shuffle.
7680     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7681     * @since 3.6
7682     */
7683    public static void shuffle(final char[] array) {
7684        shuffle(array, random());
7685    }
7686
7687    /**
7688     * 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
7689     * algorithm</a>.
7690     *
7691     * @param array  the array to shuffle
7692     * @param random the source of randomness used to permute the elements
7693     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7694     * @since 3.6
7695     */
7696    public static void shuffle(final char[] array, final Random random) {
7697        for (int i = array.length; i > 1; i--) {
7698            swap(array, i - 1, random.nextInt(i), 1);
7699        }
7700    }
7701
7702    /**
7703     * 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
7704     * algorithm</a>.
7705     * <p>
7706     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7707     * </p>
7708     * <p>
7709     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7710     * with a {@link SecureRandom} argument.
7711     * </p>
7712     *
7713     * @param array the array to shuffle.
7714     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7715     * @since 3.6
7716     */
7717    public static void shuffle(final double[] array) {
7718        shuffle(array, random());
7719    }
7720
7721    /**
7722     * 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
7723     * algorithm</a>.
7724     *
7725     * @param array  the array to shuffle
7726     * @param random the source of randomness used to permute the elements
7727     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7728     * @since 3.6
7729     */
7730    public static void shuffle(final double[] array, final Random random) {
7731        for (int i = array.length; i > 1; i--) {
7732            swap(array, i - 1, random.nextInt(i), 1);
7733        }
7734    }
7735
7736    /**
7737     * 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
7738     * algorithm</a>.
7739     * <p>
7740     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7741     * </p>
7742     * <p>
7743     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7744     * with a {@link SecureRandom} argument.
7745     * </p>
7746     *
7747     * @param array the array to shuffle.
7748     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7749     * @since 3.6
7750     */
7751    public static void shuffle(final float[] array) {
7752        shuffle(array, random());
7753    }
7754
7755    /**
7756     * 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
7757     * algorithm</a>.
7758     *
7759     * @param array  the array to shuffle
7760     * @param random the source of randomness used to permute the elements
7761     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7762     * @since 3.6
7763     */
7764    public static void shuffle(final float[] array, final Random random) {
7765        for (int i = array.length; i > 1; i--) {
7766            swap(array, i - 1, random.nextInt(i), 1);
7767        }
7768    }
7769
7770    /**
7771     * 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
7772     * algorithm</a>.
7773     * <p>
7774     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7775     * </p>
7776     * <p>
7777     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7778     * with a {@link SecureRandom} argument.
7779     * </p>
7780     *
7781     * @param array the array to shuffle.
7782     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7783     * @since 3.6
7784     */
7785    public static void shuffle(final int[] array) {
7786        shuffle(array, random());
7787    }
7788
7789    /**
7790     * 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
7791     * algorithm</a>.
7792     *
7793     * @param array  the array to shuffle
7794     * @param random the source of randomness used to permute the elements
7795     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7796     * @since 3.6
7797     */
7798    public static void shuffle(final int[] array, final Random random) {
7799        for (int i = array.length; i > 1; i--) {
7800            swap(array, i - 1, random.nextInt(i), 1);
7801        }
7802    }
7803
7804    /**
7805     * 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
7806     * algorithm</a>.
7807     * <p>
7808     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7809     * </p>
7810     * <p>
7811     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7812     * with a {@link SecureRandom} argument.
7813     * </p>
7814     *
7815     * @param array the array to shuffle.
7816     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7817     * @since 3.6
7818     */
7819    public static void shuffle(final long[] array) {
7820        shuffle(array, random());
7821    }
7822
7823    /**
7824     * 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
7825     * algorithm</a>.
7826     *
7827     * @param array  the array to shuffle
7828     * @param random the source of randomness used to permute the elements
7829     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7830     * @since 3.6
7831     */
7832    public static void shuffle(final long[] array, final Random random) {
7833        for (int i = array.length; i > 1; i--) {
7834            swap(array, i - 1, random.nextInt(i), 1);
7835        }
7836    }
7837
7838    /**
7839     * 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
7840     * algorithm</a>.
7841     * <p>
7842     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7843     * </p>
7844     * <p>
7845     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7846     * with a {@link SecureRandom} argument.
7847     * </p>
7848     *
7849     * @param array the array to shuffle.
7850     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7851     * @since 3.6
7852     */
7853    public static void shuffle(final Object[] array) {
7854        shuffle(array, random());
7855    }
7856
7857    /**
7858     * 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
7859     * algorithm</a>.
7860     *
7861     * @param array  the array to shuffle
7862     * @param random the source of randomness used to permute the elements
7863     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7864     * @since 3.6
7865     */
7866    public static void shuffle(final Object[] array, final Random random) {
7867        for (int i = array.length; i > 1; i--) {
7868            swap(array, i - 1, random.nextInt(i), 1);
7869        }
7870    }
7871
7872    /**
7873     * 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
7874     * algorithm</a>.
7875     * <p>
7876     * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7877     * </p>
7878     * <p>
7879     * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7880     * with a {@link SecureRandom} argument.
7881     * </p>
7882     *
7883     * @param array the array to shuffle.
7884     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7885     * @since 3.6
7886     */
7887    public static void shuffle(final short[] array) {
7888        shuffle(array, random());
7889    }
7890
7891    /**
7892     * 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
7893     * algorithm</a>.
7894     *
7895     * @param array  the array to shuffle
7896     * @param random the source of randomness used to permute the elements
7897     * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7898     * @since 3.6
7899     */
7900    public static void shuffle(final short[] array, final Random random) {
7901        for (int i = array.length; i > 1; i--) {
7902            swap(array, i - 1, random.nextInt(i), 1);
7903        }
7904    }
7905
7906    /**
7907     * Tests whether the given data array starts with an expected array, for example, signature bytes.
7908     * <p>
7909     * If both arrays are null, the method returns true. The method return false when one array is null and the other not.
7910     * </p>
7911     *
7912     * @param data     The data to search, maybe larger than the expected data.
7913     * @param expected The expected data to find.
7914     * @return whether a match was found.
7915     * @since 3.18.0
7916     */
7917    public static boolean startsWith(final byte[] data, final byte[] expected) {
7918        if (data == expected) {
7919            return true;
7920        }
7921        if (data == null || expected == null) {
7922            return false;
7923        }
7924        final int dataLen = data.length;
7925        if (expected.length > dataLen) {
7926            return false;
7927        }
7928        if (expected.length == dataLen) {
7929            // delegate to Arrays.equals() which has optimizations on Java > 8
7930            return Arrays.equals(data, expected);
7931        }
7932        // Once we are on Java 9+ we can delegate to Arrays here as well (or not).
7933        for (int i = 0; i < expected.length; i++) {
7934            if (data[i] != expected[i]) {
7935                return false;
7936            }
7937        }
7938        return true;
7939    }
7940
7941    /**
7942     * Produces a new {@code boolean} array containing the elements
7943     * between the start and end indices.
7944     * <p>
7945     * The start index is inclusive, the end index exclusive.
7946     * Null array input produces null output.
7947     * </p>
7948     *
7949     * @param array  the array
7950     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
7951     *      is promoted to 0, overvalue (&gt;array.length) results
7952     *      in an empty array.
7953     * @param endIndexExclusive  elements up to endIndex-1 are present in the
7954     *      returned subarray. Undervalue (&lt; startIndex) produces
7955     *      empty array, overvalue (&gt;array.length) is demoted to
7956     *      array length.
7957     * @return a new array containing the elements between
7958     *      the start and end indices.
7959     * @since 2.1
7960     * @see Arrays#copyOfRange(boolean[], int, int)
7961     */
7962    public static boolean[] subarray(final boolean[] array, int startIndexInclusive, int endIndexExclusive) {
7963        if (array == null) {
7964            return null;
7965        }
7966        startIndexInclusive = max0(startIndexInclusive);
7967        endIndexExclusive = Math.min(endIndexExclusive, array.length);
7968        final int newSize = endIndexExclusive - startIndexInclusive;
7969        if (newSize <= 0) {
7970            return EMPTY_BOOLEAN_ARRAY;
7971        }
7972        return arraycopy(array, startIndexInclusive, 0, newSize, boolean[]::new);
7973    }
7974
7975    /**
7976     * Produces a new {@code byte} array containing the elements
7977     * between the start and end indices.
7978     * <p>
7979     * The start index is inclusive, the end index exclusive.
7980     * Null array input produces null output.
7981     * </p>
7982     *
7983     * @param array  the array
7984     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
7985     *      is promoted to 0, overvalue (&gt;array.length) results
7986     *      in an empty array.
7987     * @param endIndexExclusive  elements up to endIndex-1 are present in the
7988     *      returned subarray. Undervalue (&lt; startIndex) produces
7989     *      empty array, overvalue (&gt;array.length) is demoted to
7990     *      array length.
7991     * @return a new array containing the elements between
7992     *      the start and end indices.
7993     * @since 2.1
7994     * @see Arrays#copyOfRange(byte[], int, int)
7995     */
7996    public static byte[] subarray(final byte[] array, int startIndexInclusive, int endIndexExclusive) {
7997        if (array == null) {
7998            return null;
7999        }
8000        startIndexInclusive = max0(startIndexInclusive);
8001        endIndexExclusive = Math.min(endIndexExclusive, array.length);
8002        final int newSize = endIndexExclusive - startIndexInclusive;
8003        if (newSize <= 0) {
8004            return EMPTY_BYTE_ARRAY;
8005        }
8006        return arraycopy(array, startIndexInclusive, 0, newSize, byte[]::new);
8007    }
8008
8009    /**
8010     * Produces a new {@code char} array containing the elements
8011     * between the start and end indices.
8012     * <p>
8013     * The start index is inclusive, the end index exclusive.
8014     * Null array input produces null output.
8015     * </p>
8016     *
8017     * @param array  the array
8018     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
8019     *      is promoted to 0, overvalue (&gt;array.length) results
8020     *      in an empty array.
8021     * @param endIndexExclusive  elements up to endIndex-1 are present in the
8022     *      returned subarray. Undervalue (&lt; startIndex) produces
8023     *      empty array, overvalue (&gt;array.length) is demoted to
8024     *      array length.
8025     * @return a new array containing the elements between
8026     *      the start and end indices.
8027     * @since 2.1
8028     * @see Arrays#copyOfRange(char[], int, int)
8029     */
8030    public static char[] subarray(final char[] array, int startIndexInclusive, int endIndexExclusive) {
8031        if (array == null) {
8032            return null;
8033        }
8034        startIndexInclusive = max0(startIndexInclusive);
8035        endIndexExclusive = Math.min(endIndexExclusive, array.length);
8036        final int newSize = endIndexExclusive - startIndexInclusive;
8037        if (newSize <= 0) {
8038            return EMPTY_CHAR_ARRAY;
8039        }
8040        return arraycopy(array, startIndexInclusive, 0, newSize, char[]::new);
8041    }
8042
8043    /**
8044     * Produces a new {@code double} array containing the elements
8045     * between the start and end indices.
8046     * <p>
8047     * The start index is inclusive, the end index exclusive.
8048     * Null array input produces null output.
8049     * </p>
8050     *
8051     * @param array  the array
8052     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
8053     *      is promoted to 0, overvalue (&gt;array.length) results
8054     *      in an empty array.
8055     * @param endIndexExclusive  elements up to endIndex-1 are present in the
8056     *      returned subarray. Undervalue (&lt; startIndex) produces
8057     *      empty array, overvalue (&gt;array.length) is demoted to
8058     *      array length.
8059     * @return a new array containing the elements between
8060     *      the start and end indices.
8061     * @since 2.1
8062     * @see Arrays#copyOfRange(double[], int, int)
8063     */
8064    public static double[] subarray(final double[] array, int startIndexInclusive, int endIndexExclusive) {
8065        if (array == null) {
8066            return null;
8067        }
8068        startIndexInclusive = max0(startIndexInclusive);
8069        endIndexExclusive = Math.min(endIndexExclusive, array.length);
8070        final int newSize = endIndexExclusive - startIndexInclusive;
8071        if (newSize <= 0) {
8072            return EMPTY_DOUBLE_ARRAY;
8073        }
8074        return arraycopy(array, startIndexInclusive, 0, newSize, double[]::new);
8075    }
8076
8077    /**
8078     * Produces a new {@code float} array containing the elements
8079     * between the start and end indices.
8080     * <p>
8081     * The start index is inclusive, the end index exclusive.
8082     * Null array input produces null output.
8083     * </p>
8084     *
8085     * @param array  the array
8086     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
8087     *      is promoted to 0, overvalue (&gt;array.length) results
8088     *      in an empty array.
8089     * @param endIndexExclusive  elements up to endIndex-1 are present in the
8090     *      returned subarray. Undervalue (&lt; startIndex) produces
8091     *      empty array, overvalue (&gt;array.length) is demoted to
8092     *      array length.
8093     * @return a new array containing the elements between
8094     *      the start and end indices.
8095     * @since 2.1
8096     * @see Arrays#copyOfRange(float[], int, int)
8097     */
8098    public static float[] subarray(final float[] array, int startIndexInclusive, int endIndexExclusive) {
8099        if (array == null) {
8100            return null;
8101        }
8102        startIndexInclusive = max0(startIndexInclusive);
8103        endIndexExclusive = Math.min(endIndexExclusive, array.length);
8104        final int newSize = endIndexExclusive - startIndexInclusive;
8105        if (newSize <= 0) {
8106            return EMPTY_FLOAT_ARRAY;
8107        }
8108        return arraycopy(array, startIndexInclusive, 0, newSize, float[]::new);
8109    }
8110
8111    /**
8112     * Produces a new {@code int} array containing the elements
8113     * between the start and end indices.
8114     * <p>
8115     * The start index is inclusive, the end index exclusive.
8116     * Null array input produces null output.
8117     * </p>
8118     *
8119     * @param array  the array
8120     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
8121     *      is promoted to 0, overvalue (&gt;array.length) results
8122     *      in an empty array.
8123     * @param endIndexExclusive  elements up to endIndex-1 are present in the
8124     *      returned subarray. Undervalue (&lt; startIndex) produces
8125     *      empty array, overvalue (&gt;array.length) is demoted to
8126     *      array length.
8127     * @return a new array containing the elements between
8128     *      the start and end indices.
8129     * @since 2.1
8130     * @see Arrays#copyOfRange(int[], int, int)
8131     */
8132    public static int[] subarray(final int[] array, int startIndexInclusive, int endIndexExclusive) {
8133        if (array == null) {
8134            return null;
8135        }
8136        startIndexInclusive = max0(startIndexInclusive);
8137        endIndexExclusive = Math.min(endIndexExclusive, array.length);
8138        final int newSize = endIndexExclusive - startIndexInclusive;
8139        if (newSize <= 0) {
8140            return EMPTY_INT_ARRAY;
8141        }
8142        return arraycopy(array, startIndexInclusive, 0, newSize, int[]::new);
8143    }
8144
8145    /**
8146     * Produces a new {@code long} array containing the elements
8147     * between the start and end indices.
8148     * <p>
8149     * The start index is inclusive, the end index exclusive.
8150     * Null array input produces null output.
8151     * </p>
8152     *
8153     * @param array  the array
8154     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
8155     *      is promoted to 0, overvalue (&gt;array.length) results
8156     *      in an empty array.
8157     * @param endIndexExclusive  elements up to endIndex-1 are present in the
8158     *      returned subarray. Undervalue (&lt; startIndex) produces
8159     *      empty array, overvalue (&gt;array.length) is demoted to
8160     *      array length.
8161     * @return a new array containing the elements between
8162     *      the start and end indices.
8163     * @since 2.1
8164     * @see Arrays#copyOfRange(long[], int, int)
8165     */
8166    public static long[] subarray(final long[] array, int startIndexInclusive, int endIndexExclusive) {
8167        if (array == null) {
8168            return null;
8169        }
8170        startIndexInclusive = max0(startIndexInclusive);
8171        endIndexExclusive = Math.min(endIndexExclusive, array.length);
8172        final int newSize = endIndexExclusive - startIndexInclusive;
8173        if (newSize <= 0) {
8174            return EMPTY_LONG_ARRAY;
8175        }
8176        return arraycopy(array, startIndexInclusive, 0, newSize, long[]::new);
8177    }
8178
8179    /**
8180     * Produces a new {@code short} array containing the elements
8181     * between the start and end indices.
8182     * <p>
8183     * The start index is inclusive, the end index exclusive.
8184     * Null array input produces null output.
8185     * </p>
8186     *
8187     * @param array  the array
8188     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
8189     *      is promoted to 0, overvalue (&gt;array.length) results
8190     *      in an empty array.
8191     * @param endIndexExclusive  elements up to endIndex-1 are present in the
8192     *      returned subarray. Undervalue (&lt; startIndex) produces
8193     *      empty array, overvalue (&gt;array.length) is demoted to
8194     *      array length.
8195     * @return a new array containing the elements between
8196     *      the start and end indices.
8197     * @since 2.1
8198     * @see Arrays#copyOfRange(short[], int, int)
8199     */
8200    public static short[] subarray(final short[] array, int startIndexInclusive, int endIndexExclusive) {
8201        if (array == null) {
8202            return null;
8203        }
8204        startIndexInclusive = max0(startIndexInclusive);
8205        endIndexExclusive = Math.min(endIndexExclusive, array.length);
8206        final int newSize = endIndexExclusive - startIndexInclusive;
8207        if (newSize <= 0) {
8208            return EMPTY_SHORT_ARRAY;
8209        }
8210        return arraycopy(array, startIndexInclusive, 0, newSize, short[]::new);
8211    }
8212
8213    /**
8214     * Produces a new array containing the elements between
8215     * the start and end indices.
8216     * <p>
8217     * The start index is inclusive, the end index exclusive.
8218     * Null array input produces null output.
8219     * </p>
8220     * <p>
8221     * The component type of the subarray is always the same as
8222     * that of the input array. Thus, if the input is an array of type
8223     * {@link Date}, the following usage is envisaged:
8224     * </p>
8225     * <pre>
8226     * Date[] someDates = (Date[]) ArrayUtils.subarray(allDates, 2, 5);
8227     * </pre>
8228     *
8229     * @param <T> the component type of the array
8230     * @param array  the array
8231     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
8232     *      is promoted to 0, overvalue (&gt;array.length) results
8233     *      in an empty array.
8234     * @param endIndexExclusive  elements up to endIndex-1 are present in the
8235     *      returned subarray. Undervalue (&lt; startIndex) produces
8236     *      empty array, overvalue (&gt;array.length) is demoted to
8237     *      array length.
8238     * @return a new array containing the elements between
8239     *      the start and end indices.
8240     * @since 2.1
8241     * @see Arrays#copyOfRange(Object[], int, int)
8242     */
8243    public static <T> T[] subarray(final T[] array, int startIndexInclusive, int endIndexExclusive) {
8244        if (array == null) {
8245            return null;
8246        }
8247        startIndexInclusive = max0(startIndexInclusive);
8248        endIndexExclusive = Math.min(endIndexExclusive, array.length);
8249        final int newSize = endIndexExclusive - startIndexInclusive;
8250        final Class<T> type = getComponentType(array);
8251        if (newSize <= 0) {
8252            return newInstance(type, 0);
8253        }
8254        return arraycopy(array, startIndexInclusive, 0, newSize, () -> newInstance(type, newSize));
8255    }
8256
8257    /**
8258     * Swaps two elements in the given boolean array.
8259     *
8260     * <p>There is no special handling for multi-dimensional arrays. This method
8261     * does nothing for a {@code null} or empty input array or for overflow indices.
8262     * Negative indices are promoted to 0(zero).</p>
8263     *
8264     * Examples:
8265     * <ul>
8266     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8267     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8268     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8269     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8270     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8271     * </ul>
8272     *
8273     * @param array  the array to swap, may be {@code null}.
8274     * @param offset1 the index of the first element to swap
8275     * @param offset2 the index of the second element to swap
8276     * @since 3.5
8277     */
8278    public static void swap(final boolean[] array, final int offset1, final int offset2) {
8279        swap(array, offset1, offset2, 1);
8280    }
8281
8282    /**
8283     * Swaps a series of elements in the given boolean array.
8284     *
8285     * <p>This method does nothing for a {@code null} or empty input array or
8286     * for overflow indices. Negative indices are promoted to 0(zero). If any
8287     * of the sub-arrays to swap falls outside of the given array, then the
8288     * swap is stopped at the end of the array and as many as possible elements
8289     * are swapped.</p>
8290     *
8291     * Examples:
8292     * <ul>
8293     *     <li>ArrayUtils.swap([true, false, true, false], 0, 2, 1) -&gt; [true, false, true, false]</li>
8294     *     <li>ArrayUtils.swap([true, false, true, false], 0, 0, 1) -&gt; [true, false, true, false]</li>
8295     *     <li>ArrayUtils.swap([true, false, true, false], 0, 2, 2) -&gt; [true, false, true, false]</li>
8296     *     <li>ArrayUtils.swap([true, false, true, false], -3, 2, 2) -&gt; [true, false, true, false]</li>
8297     *     <li>ArrayUtils.swap([true, false, true, false], 0, 3, 3) -&gt; [false, false, true, true]</li>
8298     * </ul>
8299     *
8300     * @param array the array to swap, may be {@code null}.
8301     * @param offset1 the index of the first element in the series to swap
8302     * @param offset2 the index of the second element in the series to swap
8303     * @param len the number of elements to swap starting with the given indices
8304     * @since 3.5
8305     */
8306    public static void swap(final boolean[] array, int offset1, int offset2, int len) {
8307        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8308            return;
8309        }
8310        offset1 = max0(offset1);
8311        offset2 = max0(offset2);
8312        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8313        for (int i = 0; i < len; i++, offset1++, offset2++) {
8314            final boolean aux = array[offset1];
8315            array[offset1] = array[offset2];
8316            array[offset2] = aux;
8317        }
8318    }
8319
8320    /**
8321     * Swaps two elements in the given byte array.
8322     *
8323     * <p>There is no special handling for multi-dimensional arrays. This method
8324     * does nothing for a {@code null} or empty input array or for overflow indices.
8325     * Negative indices are promoted to 0(zero).</p>
8326     *
8327     * Examples:
8328     * <ul>
8329     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8330     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8331     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8332     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8333     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8334     * </ul>
8335     *
8336     * @param array  the array to swap, may be {@code null}.
8337     * @param offset1 the index of the first element to swap
8338     * @param offset2 the index of the second element to swap
8339     * @since 3.5
8340     */
8341    public static void swap(final byte[] array, final int offset1, final int offset2) {
8342        swap(array, offset1, offset2, 1);
8343    }
8344
8345    /**
8346     * Swaps a series of elements in the given byte array.
8347     *
8348     * <p>This method does nothing for a {@code null} or empty input array or
8349     * for overflow indices. Negative indices are promoted to 0(zero). If any
8350     * of the sub-arrays to swap falls outside of the given array, then the
8351     * swap is stopped at the end of the array and as many as possible elements
8352     * are swapped.</p>
8353     *
8354     * Examples:
8355     * <ul>
8356     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8357     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8358     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8359     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8360     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8361     * </ul>
8362     *
8363     * @param array the array to swap, may be {@code null}.
8364     * @param offset1 the index of the first element in the series to swap
8365     * @param offset2 the index of the second element in the series to swap
8366     * @param len the number of elements to swap starting with the given indices
8367     * @since 3.5
8368     */
8369    public static void swap(final byte[] array, int offset1, int offset2, int len) {
8370        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8371            return;
8372        }
8373        offset1 = max0(offset1);
8374        offset2 = max0(offset2);
8375        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8376        for (int i = 0; i < len; i++, offset1++, offset2++) {
8377            final byte aux = array[offset1];
8378            array[offset1] = array[offset2];
8379            array[offset2] = aux;
8380        }
8381    }
8382
8383    /**
8384     * Swaps two elements in the given char array.
8385     *
8386     * <p>There is no special handling for multi-dimensional arrays. This method
8387     * does nothing for a {@code null} or empty input array or for overflow indices.
8388     * Negative indices are promoted to 0(zero).</p>
8389     *
8390     * Examples:
8391     * <ul>
8392     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8393     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8394     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8395     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8396     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8397     * </ul>
8398     *
8399     * @param array  the array to swap, may be {@code null}.
8400     * @param offset1 the index of the first element to swap
8401     * @param offset2 the index of the second element to swap
8402     * @since 3.5
8403     */
8404    public static void swap(final char[] array, final int offset1, final int offset2) {
8405        swap(array, offset1, offset2, 1);
8406    }
8407
8408    /**
8409     * Swaps a series of elements in the given char array.
8410     *
8411     * <p>This method does nothing for a {@code null} or empty input array or
8412     * for overflow indices. Negative indices are promoted to 0(zero). If any
8413     * of the sub-arrays to swap falls outside of the given array, then the
8414     * swap is stopped at the end of the array and as many as possible elements
8415     * are swapped.</p>
8416     *
8417     * Examples:
8418     * <ul>
8419     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8420     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8421     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8422     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8423     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8424     * </ul>
8425     *
8426     * @param array the array to swap, may be {@code null}.
8427     * @param offset1 the index of the first element in the series to swap
8428     * @param offset2 the index of the second element in the series to swap
8429     * @param len the number of elements to swap starting with the given indices
8430     * @since 3.5
8431     */
8432    public static void swap(final char[] array, int offset1, int offset2, int len) {
8433        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8434            return;
8435        }
8436        offset1 = max0(offset1);
8437        offset2 = max0(offset2);
8438        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8439        for (int i = 0; i < len; i++, offset1++, offset2++) {
8440            final char aux = array[offset1];
8441            array[offset1] = array[offset2];
8442            array[offset2] = aux;
8443        }
8444    }
8445
8446    /**
8447     * Swaps two elements in the given double array.
8448     *
8449     * <p>There is no special handling for multi-dimensional arrays. This method
8450     * does nothing for a {@code null} or empty input array or for overflow indices.
8451     * Negative indices are promoted to 0(zero).</p>
8452     *
8453     * Examples:
8454     * <ul>
8455     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8456     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8457     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8458     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8459     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8460     * </ul>
8461     *
8462     * @param array  the array to swap, may be {@code null}.
8463     * @param offset1 the index of the first element to swap
8464     * @param offset2 the index of the second element to swap
8465     * @since 3.5
8466     */
8467    public static void swap(final double[] array, final int offset1, final int offset2) {
8468        swap(array, offset1, offset2, 1);
8469    }
8470
8471    /**
8472     * Swaps a series of elements in the given double array.
8473     *
8474     * <p>This method does nothing for a {@code null} or empty input array or
8475     * for overflow indices. Negative indices are promoted to 0(zero). If any
8476     * of the sub-arrays to swap falls outside of the given array, then the
8477     * swap is stopped at the end of the array and as many as possible elements
8478     * are swapped.</p>
8479     *
8480     * Examples:
8481     * <ul>
8482     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8483     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8484     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8485     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8486     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8487     * </ul>
8488     *
8489     * @param array the array to swap, may be {@code null}.
8490     * @param offset1 the index of the first element in the series to swap
8491     * @param offset2 the index of the second element in the series to swap
8492     * @param len the number of elements to swap starting with the given indices
8493     * @since 3.5
8494     */
8495    public static void swap(final double[] array,  int offset1, int offset2, int len) {
8496        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8497            return;
8498        }
8499        offset1 = max0(offset1);
8500        offset2 = max0(offset2);
8501        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8502        for (int i = 0; i < len; i++, offset1++, offset2++) {
8503            final double aux = array[offset1];
8504            array[offset1] = array[offset2];
8505            array[offset2] = aux;
8506        }
8507    }
8508
8509    /**
8510     * Swaps two elements in the given float array.
8511     *
8512     * <p>There is no special handling for multi-dimensional arrays. This method
8513     * does nothing for a {@code null} or empty input array or for overflow indices.
8514     * Negative indices are promoted to 0(zero).</p>
8515     *
8516     * Examples:
8517     * <ul>
8518     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8519     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8520     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8521     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8522     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8523     * </ul>
8524     *
8525     * @param array  the array to swap, may be {@code null}.
8526     * @param offset1 the index of the first element to swap
8527     * @param offset2 the index of the second element to swap
8528     * @since 3.5
8529     */
8530    public static void swap(final float[] array, final int offset1, final int offset2) {
8531        swap(array, offset1, offset2, 1);
8532    }
8533
8534    /**
8535     * Swaps a series of elements in the given float array.
8536     *
8537     * <p>This method does nothing for a {@code null} or empty input array or
8538     * for overflow indices. Negative indices are promoted to 0(zero). If any
8539     * of the sub-arrays to swap falls outside of the given array, then the
8540     * swap is stopped at the end of the array and as many as possible elements
8541     * are swapped.</p>
8542     *
8543     * Examples:
8544     * <ul>
8545     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8546     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8547     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8548     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8549     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8550     * </ul>
8551     *
8552     * @param array the array to swap, may be {@code null}.
8553     * @param offset1 the index of the first element in the series to swap
8554     * @param offset2 the index of the second element in the series to swap
8555     * @param len the number of elements to swap starting with the given indices
8556     * @since 3.5
8557     */
8558    public static void swap(final float[] array, int offset1, int offset2, int len) {
8559        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8560            return;
8561        }
8562        offset1 = max0(offset1);
8563        offset2 = max0(offset2);
8564        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8565        for (int i = 0; i < len; i++, offset1++, offset2++) {
8566            final float aux = array[offset1];
8567            array[offset1] = array[offset2];
8568            array[offset2] = aux;
8569        }
8570
8571    }
8572
8573    /**
8574     * Swaps two elements in the given int array.
8575     *
8576     * <p>There is no special handling for multi-dimensional arrays. This method
8577     * does nothing for a {@code null} or empty input array or for overflow indices.
8578     * Negative indices are promoted to 0(zero).</p>
8579     *
8580     * Examples:
8581     * <ul>
8582     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8583     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8584     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8585     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8586     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8587     * </ul>
8588     *
8589     * @param array  the array to swap, may be {@code null}
8590     * @param offset1 the index of the first element to swap
8591     * @param offset2 the index of the second element to swap
8592     * @since 3.5
8593     */
8594    public static void swap(final int[] array, final int offset1, final int offset2) {
8595        swap(array, offset1, offset2, 1);
8596    }
8597
8598    /**
8599     * Swaps a series of elements in the given int array.
8600     *
8601     * <p>This method does nothing for a {@code null} or empty input array or
8602     * for overflow indices. Negative indices are promoted to 0(zero). If any
8603     * of the sub-arrays to swap falls outside of the given array, then the
8604     * swap is stopped at the end of the array and as many as possible elements
8605     * are swapped.</p>
8606     *
8607     * Examples:
8608     * <ul>
8609     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8610     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8611     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8612     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8613     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8614     * </ul>
8615     *
8616     * @param array the array to swap, may be {@code null}
8617     * @param offset1 the index of the first element in the series to swap
8618     * @param offset2 the index of the second element in the series to swap
8619     * @param len the number of elements to swap starting with the given indices
8620     * @since 3.5
8621     */
8622    public static void swap(final int[] array,  int offset1, int offset2, int len) {
8623        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8624            return;
8625        }
8626        offset1 = max0(offset1);
8627        offset2 = max0(offset2);
8628        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8629        for (int i = 0; i < len; i++, offset1++, offset2++) {
8630            final int aux = array[offset1];
8631            array[offset1] = array[offset2];
8632            array[offset2] = aux;
8633        }
8634    }
8635
8636    /**
8637     * Swaps two elements in the given long array.
8638     *
8639     * <p>There is no special handling for multi-dimensional arrays. This method
8640     * does nothing for a {@code null} or empty input array or for overflow indices.
8641     * Negative indices are promoted to 0(zero).</p>
8642     *
8643     * Examples:
8644     * <ul>
8645     *     <li>ArrayUtils.swap([true, false, true], 0, 2) -&gt; [true, false, true]</li>
8646     *     <li>ArrayUtils.swap([true, false, true], 0, 0) -&gt; [true, false, true]</li>
8647     *     <li>ArrayUtils.swap([true, false, true], 1, 0) -&gt; [false, true, true]</li>
8648     *     <li>ArrayUtils.swap([true, false, true], 0, 5) -&gt; [true, false, true]</li>
8649     *     <li>ArrayUtils.swap([true, false, true], -1, 1) -&gt; [false, true, true]</li>
8650     * </ul>
8651     *
8652     * @param array  the array to swap, may be {@code null}
8653     * @param offset1 the index of the first element to swap
8654     * @param offset2 the index of the second element to swap
8655     * @since 3.5
8656     */
8657    public static void swap(final long[] array, final int offset1, final int offset2) {
8658        swap(array, offset1, offset2, 1);
8659    }
8660
8661    /**
8662     * Swaps a series of elements in the given long array.
8663     *
8664     * <p>This method does nothing for a {@code null} or empty input array or
8665     * for overflow indices. Negative indices are promoted to 0(zero). If any
8666     * of the sub-arrays to swap falls outside of the given array, then the
8667     * swap is stopped at the end of the array and as many as possible elements
8668     * are swapped.</p>
8669     *
8670     * Examples:
8671     * <ul>
8672     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8673     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8674     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8675     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8676     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8677     * </ul>
8678     *
8679     * @param array the array to swap, may be {@code null}
8680     * @param offset1 the index of the first element in the series to swap
8681     * @param offset2 the index of the second element in the series to swap
8682     * @param len the number of elements to swap starting with the given indices
8683     * @since 3.5
8684     */
8685    public static void swap(final long[] array,  int offset1, int offset2, int len) {
8686        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8687            return;
8688        }
8689        offset1 = max0(offset1);
8690        offset2 = max0(offset2);
8691        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8692        for (int i = 0; i < len; i++, offset1++, offset2++) {
8693            final long aux = array[offset1];
8694            array[offset1] = array[offset2];
8695            array[offset2] = aux;
8696        }
8697    }
8698
8699    /**
8700     * Swaps two elements in the given array.
8701     *
8702     * <p>There is no special handling for multi-dimensional arrays. This method
8703     * does nothing for a {@code null} or empty input array or for overflow indices.
8704     * Negative indices are promoted to 0(zero).</p>
8705     *
8706     * Examples:
8707     * <ul>
8708     *     <li>ArrayUtils.swap(["1", "2", "3"], 0, 2) -&gt; ["3", "2", "1"]</li>
8709     *     <li>ArrayUtils.swap(["1", "2", "3"], 0, 0) -&gt; ["1", "2", "3"]</li>
8710     *     <li>ArrayUtils.swap(["1", "2", "3"], 1, 0) -&gt; ["2", "1", "3"]</li>
8711     *     <li>ArrayUtils.swap(["1", "2", "3"], 0, 5) -&gt; ["1", "2", "3"]</li>
8712     *     <li>ArrayUtils.swap(["1", "2", "3"], -1, 1) -&gt; ["2", "1", "3"]</li>
8713     * </ul>
8714     *
8715     * @param array the array to swap, may be {@code null}
8716     * @param offset1 the index of the first element to swap
8717     * @param offset2 the index of the second element to swap
8718     * @since 3.5
8719     */
8720    public static void swap(final Object[] array, final int offset1, final int offset2) {
8721        swap(array, offset1, offset2, 1);
8722    }
8723
8724    /**
8725     * Swaps a series of elements in the given array.
8726     *
8727     * <p>This method does nothing for a {@code null} or empty input array or
8728     * for overflow indices. Negative indices are promoted to 0(zero). If any
8729     * of the sub-arrays to swap falls outside of the given array, then the
8730     * swap is stopped at the end of the array and as many as possible elements
8731     * are swapped.</p>
8732     *
8733     * Examples:
8734     * <ul>
8735     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 0, 2, 1) -&gt; ["3", "2", "1", "4"]</li>
8736     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 0, 0, 1) -&gt; ["1", "2", "3", "4"]</li>
8737     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 2, 0, 2) -&gt; ["3", "4", "1", "2"]</li>
8738     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], -3, 2, 2) -&gt; ["3", "4", "1", "2"]</li>
8739     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 0, 3, 3) -&gt; ["4", "2", "3", "1"]</li>
8740     * </ul>
8741     *
8742     * @param array the array to swap, may be {@code null}
8743     * @param offset1 the index of the first element in the series to swap
8744     * @param offset2 the index of the second element in the series to swap
8745     * @param len the number of elements to swap starting with the given indices
8746     * @since 3.5
8747     */
8748    public static void swap(final Object[] array,  int offset1, int offset2, int len) {
8749        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8750            return;
8751        }
8752        offset1 = max0(offset1);
8753        offset2 = max0(offset2);
8754        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8755        for (int i = 0; i < len; i++, offset1++, offset2++) {
8756            final Object aux = array[offset1];
8757            array[offset1] = array[offset2];
8758            array[offset2] = aux;
8759        }
8760    }
8761
8762    /**
8763     * Swaps two elements in the given short array.
8764     *
8765     * <p>There is no special handling for multi-dimensional arrays. This method
8766     * does nothing for a {@code null} or empty input array or for overflow indices.
8767     * Negative indices are promoted to 0(zero).</p>
8768     *
8769     * Examples:
8770     * <ul>
8771     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8772     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8773     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8774     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8775     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8776     * </ul>
8777     *
8778     * @param array  the array to swap, may be {@code null}
8779     * @param offset1 the index of the first element to swap
8780     * @param offset2 the index of the second element to swap
8781     * @since 3.5
8782     */
8783    public static void swap(final short[] array, final int offset1, final int offset2) {
8784        swap(array, offset1, offset2, 1);
8785    }
8786
8787    /**
8788     * Swaps a series of elements in the given short array.
8789     *
8790     * <p>This method does nothing for a {@code null} or empty input array or
8791     * for overflow indices. Negative indices are promoted to 0(zero). If any
8792     * of the sub-arrays to swap falls outside of the given array, then the
8793     * swap is stopped at the end of the array and as many as possible elements
8794     * are swapped.</p>
8795     *
8796     * Examples:
8797     * <ul>
8798     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8799     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8800     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8801     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8802     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8803     * </ul>
8804     *
8805     * @param array the array to swap, may be {@code null}
8806     * @param offset1 the index of the first element in the series to swap
8807     * @param offset2 the index of the second element in the series to swap
8808     * @param len the number of elements to swap starting with the given indices
8809     * @since 3.5
8810     */
8811    public static void swap(final short[] array, int offset1, int offset2, int len) {
8812        if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8813            return;
8814        }
8815        offset1 = max0(offset1);
8816        offset2 = max0(offset2);
8817        if (offset1 == offset2) {
8818            return;
8819        }
8820        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8821        for (int i = 0; i < len; i++, offset1++, offset2++) {
8822            final short aux = array[offset1];
8823            array[offset1] = array[offset2];
8824            array[offset2] = aux;
8825        }
8826    }
8827
8828    /**
8829     * Create a type-safe generic array.
8830     * <p>
8831     * The Java language does not allow an array to be created from a generic type:
8832     * </p>
8833     * <pre>
8834    public static &lt;T&gt; T[] createAnArray(int size) {
8835        return new T[size]; // compiler error here
8836    }
8837    public static &lt;T&gt; T[] createAnArray(int size) {
8838        return (T[]) new Object[size]; // ClassCastException at runtime
8839    }
8840     * </pre>
8841     * <p>
8842     * Therefore new arrays of generic types can be created with this method.
8843     * For example, an array of Strings can be created:
8844     * </p>
8845     * <pre>{@code
8846     * String[] array = ArrayUtils.toArray("1", "2");
8847     * String[] emptyArray = ArrayUtils.<String>toArray();
8848     * }</pre>
8849     * <p>
8850     * The method is typically used in scenarios, where the caller itself uses generic types
8851     * that have to be combined into an array.
8852     * </p>
8853     * <p>
8854     * Note, this method makes only sense to provide arguments of the same type so that the
8855     * compiler can deduce the type of the array itself. While it is possible to select the
8856     * type explicitly like in
8857     * {@code Number[] array = ArrayUtils.<Number>toArray(Integer.valueOf(42), Double.valueOf(Math.PI))},
8858     * there is no real advantage when compared to
8859     * {@code new Number[] {Integer.valueOf(42), Double.valueOf(Math.PI)}}.
8860     * </p>
8861     *
8862     * @param  <T>   the array's element type
8863     * @param  items  the varargs array items, null allowed
8864     * @return the array, not null unless a null array is passed in
8865     * @since 3.0
8866     */
8867    public static <T> T[] toArray(@SuppressWarnings("unchecked") final T... items) {
8868        return items;
8869    }
8870
8871    /**
8872     * Converts the given array into a {@link java.util.Map}. Each element of the array
8873     * must be either a {@link java.util.Map.Entry} or an Array, containing at least two
8874     * elements, where the first element is used as key and the second as
8875     * value.
8876     * <p>
8877     * This method can be used to initialize:
8878     * </p>
8879     * <pre>
8880     * // Create a Map mapping colors.
8881     * Map colorMap = ArrayUtils.toMap(new String[][] {
8882     *     {"RED", "#FF0000"},
8883     *     {"GREEN", "#00FF00"},
8884     *     {"BLUE", "#0000FF"}});
8885     * </pre>
8886     * <p>
8887     * This method returns {@code null} for a {@code null} input array.
8888     * </p>
8889     *
8890     * @param array  an array whose elements are either a {@link java.util.Map.Entry} or
8891     *  an Array containing at least two elements, may be {@code null}
8892     * @return a {@link Map} that was created from the array
8893     * @throws IllegalArgumentException  if one element of this Array is
8894     *  itself an Array containing less than two elements
8895     * @throws IllegalArgumentException  if the array contains elements other
8896     *  than {@link java.util.Map.Entry} and an Array
8897     */
8898    public static Map<Object, Object> toMap(final Object[] array) {
8899        if (array == null) {
8900            return null;
8901        }
8902        final Map<Object, Object> map = new HashMap<>((int) (array.length * 1.5));
8903        for (int i = 0; i < array.length; i++) {
8904            final Object object = array[i];
8905            if (object instanceof Map.Entry<?, ?>) {
8906                final Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
8907                map.put(entry.getKey(), entry.getValue());
8908            } else if (object instanceof Object[]) {
8909                final Object[] entry = (Object[]) object;
8910                if (entry.length < 2) {
8911                    throw new IllegalArgumentException("Array element " + i + ", '"
8912                        + object
8913                        + "', has a length less than 2");
8914                }
8915                map.put(entry[0], entry[1]);
8916            } else {
8917                throw new IllegalArgumentException("Array element " + i + ", '"
8918                        + object
8919                        + "', is neither of type Map.Entry nor an Array");
8920            }
8921        }
8922        return map;
8923    }
8924
8925    /**
8926     * Converts an array of primitive booleans to objects.
8927     *
8928     * <p>This method returns {@code null} for a {@code null} input array.</p>
8929     *
8930     * @param array  a {@code boolean} array
8931     * @return a {@link Boolean} array, {@code null} if null array input
8932     */
8933    public static Boolean[] toObject(final boolean[] array) {
8934        if (array == null) {
8935            return null;
8936        }
8937        if (array.length == 0) {
8938            return EMPTY_BOOLEAN_OBJECT_ARRAY;
8939        }
8940        return setAll(new Boolean[array.length], i -> array[i] ? Boolean.TRUE : Boolean.FALSE);
8941    }
8942
8943    /**
8944     * Converts an array of primitive bytes to objects.
8945     *
8946     * <p>This method returns {@code null} for a {@code null} input array.</p>
8947     *
8948     * @param array  a {@code byte} array
8949     * @return a {@link Byte} array, {@code null} if null array input
8950     */
8951    public static Byte[] toObject(final byte[] array) {
8952        if (array == null) {
8953            return null;
8954        }
8955        if (array.length == 0) {
8956            return EMPTY_BYTE_OBJECT_ARRAY;
8957        }
8958        return setAll(new Byte[array.length], i -> Byte.valueOf(array[i]));
8959    }
8960
8961    /**
8962     * Converts an array of primitive chars to objects.
8963     *
8964     * <p>This method returns {@code null} for a {@code null} input array.</p>
8965     *
8966     * @param array a {@code char} array
8967     * @return a {@link Character} array, {@code null} if null array input
8968     */
8969    public static Character[] toObject(final char[] array) {
8970        if (array == null) {
8971            return null;
8972        }
8973        if (array.length == 0) {
8974            return EMPTY_CHARACTER_OBJECT_ARRAY;
8975        }
8976        return setAll(new Character[array.length], i -> Character.valueOf(array[i]));
8977     }
8978
8979    /**
8980     * Converts an array of primitive doubles to objects.
8981     *
8982     * <p>This method returns {@code null} for a {@code null} input array.</p>
8983     *
8984     * @param array  a {@code double} array
8985     * @return a {@link Double} array, {@code null} if null array input
8986     */
8987    public static Double[] toObject(final double[] array) {
8988        if (array == null) {
8989            return null;
8990        }
8991        if (array.length == 0) {
8992            return EMPTY_DOUBLE_OBJECT_ARRAY;
8993        }
8994        return setAll(new Double[array.length], i -> Double.valueOf(array[i]));
8995    }
8996
8997    /**
8998     * Converts an array of primitive floats to objects.
8999     *
9000     * <p>This method returns {@code null} for a {@code null} input array.</p>
9001     *
9002     * @param array  a {@code float} array
9003     * @return a {@link Float} array, {@code null} if null array input
9004     */
9005    public static Float[] toObject(final float[] array) {
9006        if (array == null) {
9007            return null;
9008        }
9009        if (array.length == 0) {
9010            return EMPTY_FLOAT_OBJECT_ARRAY;
9011        }
9012        return setAll(new Float[array.length], i -> Float.valueOf(array[i]));
9013    }
9014
9015    /**
9016     * Converts an array of primitive ints to objects.
9017     *
9018     * <p>This method returns {@code null} for a {@code null} input array.</p>
9019     *
9020     * @param array  an {@code int} array
9021     * @return an {@link Integer} array, {@code null} if null array input
9022     */
9023    public static Integer[] toObject(final int[] array) {
9024        if (array == null) {
9025            return null;
9026        }
9027        if (array.length == 0) {
9028            return EMPTY_INTEGER_OBJECT_ARRAY;
9029        }
9030        return setAll(new Integer[array.length], i -> Integer.valueOf(array[i]));
9031    }
9032
9033    /**
9034     * Converts an array of primitive longs to objects.
9035     *
9036     * <p>This method returns {@code null} for a {@code null} input array.</p>
9037     *
9038     * @param array  a {@code long} array
9039     * @return a {@link Long} array, {@code null} if null array input
9040     */
9041    public static Long[] toObject(final long[] array) {
9042        if (array == null) {
9043            return null;
9044        }
9045        if (array.length == 0) {
9046            return EMPTY_LONG_OBJECT_ARRAY;
9047        }
9048        return setAll(new Long[array.length], i -> Long.valueOf(array[i]));
9049    }
9050
9051    /**
9052     * Converts an array of primitive shorts to objects.
9053     *
9054     * <p>This method returns {@code null} for a {@code null} input array.</p>
9055     *
9056     * @param array  a {@code short} array
9057     * @return a {@link Short} array, {@code null} if null array input
9058     */
9059    public static Short[] toObject(final short[] array) {
9060        if (array == null) {
9061            return null;
9062        }
9063        if (array.length == 0) {
9064            return EMPTY_SHORT_OBJECT_ARRAY;
9065        }
9066        return setAll(new Short[array.length], i -> Short.valueOf(array[i]));
9067    }
9068
9069    /**
9070     * Converts an array of object Booleans to primitives.
9071     * <p>
9072     * This method returns {@code null} for a {@code null} input array.
9073     * </p>
9074     * <p>
9075     * Null array elements map to false, like {@code Boolean.parseBoolean(null)} and its callers return false.
9076     * </p>
9077     *
9078     * @param array a {@link Boolean} array, may be {@code null}
9079     * @return a {@code boolean} array, {@code null} if null array input
9080     */
9081    public static boolean[] toPrimitive(final Boolean[] array) {
9082        return toPrimitive(array, false);
9083    }
9084
9085    /**
9086     * Converts an array of object Booleans to primitives handling {@code null}.
9087     * <p>
9088     * This method returns {@code null} for a {@code null} input array.
9089     * </p>
9090     *
9091     * @param array  a {@link Boolean} array, may be {@code null}
9092     * @param valueForNull  the value to insert if {@code null} found
9093     * @return a {@code boolean} array, {@code null} if null array input
9094     */
9095    public static boolean[] toPrimitive(final Boolean[] array, final boolean valueForNull) {
9096        if (array == null) {
9097            return null;
9098        }
9099        if (array.length == 0) {
9100            return EMPTY_BOOLEAN_ARRAY;
9101        }
9102        final boolean[] result = new boolean[array.length];
9103        for (int i = 0; i < array.length; i++) {
9104            final Boolean b = array[i];
9105            result[i] = b == null ? valueForNull : b.booleanValue();
9106        }
9107        return result;
9108    }
9109
9110    /**
9111     * Converts an array of object Bytes to primitives.
9112     * <p>
9113     * This method returns {@code null} for a {@code null} input array.
9114     * </p>
9115     *
9116     * @param array  a {@link Byte} array, may be {@code null}
9117     * @return a {@code byte} array, {@code null} if null array input
9118     * @throws NullPointerException if an array element is {@code null}
9119     */
9120    public static byte[] toPrimitive(final Byte[] array) {
9121        if (array == null) {
9122            return null;
9123        }
9124        if (array.length == 0) {
9125            return EMPTY_BYTE_ARRAY;
9126        }
9127        final byte[] result = new byte[array.length];
9128        for (int i = 0; i < array.length; i++) {
9129            result[i] = array[i].byteValue();
9130        }
9131        return result;
9132    }
9133
9134    /**
9135     * Converts an array of object Bytes to primitives handling {@code null}.
9136     * <p>
9137     * This method returns {@code null} for a {@code null} input array.
9138     * </p>
9139     *
9140     * @param array  a {@link Byte} array, may be {@code null}
9141     * @param valueForNull  the value to insert if {@code null} found
9142     * @return a {@code byte} array, {@code null} if null array input
9143     */
9144    public static byte[] toPrimitive(final Byte[] array, final byte valueForNull) {
9145        if (array == null) {
9146            return null;
9147        }
9148        if (array.length == 0) {
9149            return EMPTY_BYTE_ARRAY;
9150        }
9151        final byte[] result = new byte[array.length];
9152        for (int i = 0; i < array.length; i++) {
9153            final Byte b = array[i];
9154            result[i] = b == null ? valueForNull : b.byteValue();
9155        }
9156        return result;
9157    }
9158
9159    /**
9160     * Converts an array of object Characters to primitives.
9161     * <p>
9162     * This method returns {@code null} for a {@code null} input array.
9163     * </p>
9164     *
9165     * @param array  a {@link Character} array, may be {@code null}
9166     * @return a {@code char} array, {@code null} if null array input
9167     * @throws NullPointerException if an array element is {@code null}
9168     */
9169    public static char[] toPrimitive(final Character[] array) {
9170        if (array == null) {
9171            return null;
9172        }
9173        if (array.length == 0) {
9174            return EMPTY_CHAR_ARRAY;
9175        }
9176        final char[] result = new char[array.length];
9177        for (int i = 0; i < array.length; i++) {
9178            result[i] = array[i].charValue();
9179        }
9180        return result;
9181    }
9182
9183    /**
9184     * Converts an array of object Character to primitives handling {@code null}.
9185     * <p>
9186     * This method returns {@code null} for a {@code null} input array.
9187     * </p>
9188     *
9189     * @param array  a {@link Character} array, may be {@code null}
9190     * @param valueForNull  the value to insert if {@code null} found
9191     * @return a {@code char} array, {@code null} if null array input
9192     */
9193    public static char[] toPrimitive(final Character[] array, final char valueForNull) {
9194        if (array == null) {
9195            return null;
9196        }
9197        if (array.length == 0) {
9198            return EMPTY_CHAR_ARRAY;
9199        }
9200        final char[] result = new char[array.length];
9201        for (int i = 0; i < array.length; i++) {
9202            final Character b = array[i];
9203            result[i] = b == null ? valueForNull : b.charValue();
9204        }
9205        return result;
9206    }
9207
9208    /**
9209     * Converts an array of object Doubles to primitives.
9210     * <p>
9211     * This method returns {@code null} for a {@code null} input array.
9212     * </p>
9213     *
9214     * @param array  a {@link Double} array, may be {@code null}
9215     * @return a {@code double} array, {@code null} if null array input
9216     * @throws NullPointerException if an array element is {@code null}
9217     */
9218    public static double[] toPrimitive(final Double[] array) {
9219        if (array == null) {
9220            return null;
9221        }
9222        if (array.length == 0) {
9223            return EMPTY_DOUBLE_ARRAY;
9224        }
9225        final double[] result = new double[array.length];
9226        for (int i = 0; i < array.length; i++) {
9227            result[i] = array[i].doubleValue();
9228        }
9229        return result;
9230    }
9231
9232    /**
9233     * Converts an array of object Doubles to primitives handling {@code null}.
9234     * <p>
9235     * This method returns {@code null} for a {@code null} input array.
9236     * </p>
9237     *
9238     * @param array  a {@link Double} array, may be {@code null}
9239     * @param valueForNull  the value to insert if {@code null} found
9240     * @return a {@code double} array, {@code null} if null array input
9241     */
9242    public static double[] toPrimitive(final Double[] array, final double valueForNull) {
9243        if (array == null) {
9244            return null;
9245        }
9246        if (array.length == 0) {
9247            return EMPTY_DOUBLE_ARRAY;
9248        }
9249        final double[] result = new double[array.length];
9250        for (int i = 0; i < array.length; i++) {
9251            final Double b = array[i];
9252            result[i] = b == null ? valueForNull : b.doubleValue();
9253        }
9254        return result;
9255    }
9256
9257    /**
9258     * Converts an array of object Floats to primitives.
9259     * <p>
9260     * This method returns {@code null} for a {@code null} input array.
9261     * </p>
9262     *
9263     * @param array  a {@link Float} array, may be {@code null}
9264     * @return a {@code float} array, {@code null} if null array input
9265     * @throws NullPointerException if an array element is {@code null}
9266     */
9267    public static float[] toPrimitive(final Float[] array) {
9268        if (array == null) {
9269            return null;
9270        }
9271        if (array.length == 0) {
9272            return EMPTY_FLOAT_ARRAY;
9273        }
9274        final float[] result = new float[array.length];
9275        for (int i = 0; i < array.length; i++) {
9276            result[i] = array[i].floatValue();
9277        }
9278        return result;
9279    }
9280
9281    /**
9282     * Converts an array of object Floats to primitives handling {@code null}.
9283     * <p>
9284     * This method returns {@code null} for a {@code null} input array.
9285     * </p>
9286     *
9287     * @param array  a {@link Float} array, may be {@code null}
9288     * @param valueForNull  the value to insert if {@code null} found
9289     * @return a {@code float} array, {@code null} if null array input
9290     */
9291    public static float[] toPrimitive(final Float[] array, final float valueForNull) {
9292        if (array == null) {
9293            return null;
9294        }
9295        if (array.length == 0) {
9296            return EMPTY_FLOAT_ARRAY;
9297        }
9298        final float[] result = new float[array.length];
9299        for (int i = 0; i < array.length; i++) {
9300            final Float b = array[i];
9301            result[i] = b == null ? valueForNull : b.floatValue();
9302        }
9303        return result;
9304    }
9305
9306    /**
9307     * Converts an array of object Integers to primitives.
9308     * <p>
9309     * This method returns {@code null} for a {@code null} input array.
9310     * </p>
9311     *
9312     * @param array  a {@link Integer} array, may be {@code null}
9313     * @return an {@code int} array, {@code null} if null array input
9314     * @throws NullPointerException if an array element is {@code null}
9315     */
9316    public static int[] toPrimitive(final Integer[] array) {
9317        if (array == null) {
9318            return null;
9319        }
9320        if (array.length == 0) {
9321            return EMPTY_INT_ARRAY;
9322        }
9323        final int[] result = new int[array.length];
9324        for (int i = 0; i < array.length; i++) {
9325            result[i] = array[i].intValue();
9326        }
9327        return result;
9328    }
9329
9330    /**
9331     * Converts an array of object Integer to primitives handling {@code null}.
9332     * <p>
9333     * This method returns {@code null} for a {@code null} input array.
9334     * </p>
9335     *
9336     * @param array  a {@link Integer} array, may be {@code null}
9337     * @param valueForNull  the value to insert if {@code null} found
9338     * @return an {@code int} array, {@code null} if null array input
9339     */
9340    public static int[] toPrimitive(final Integer[] array, final int valueForNull) {
9341        if (array == null) {
9342            return null;
9343        }
9344        if (array.length == 0) {
9345            return EMPTY_INT_ARRAY;
9346        }
9347        final int[] result = new int[array.length];
9348        for (int i = 0; i < array.length; i++) {
9349            final Integer b = array[i];
9350            result[i] = b == null ? valueForNull : b.intValue();
9351        }
9352        return result;
9353    }
9354
9355    /**
9356     * Converts an array of object Longs to primitives.
9357     * <p>
9358     * This method returns {@code null} for a {@code null} input array.
9359     * </p>
9360     *
9361     * @param array  a {@link Long} array, may be {@code null}
9362     * @return a {@code long} array, {@code null} if null array input
9363     * @throws NullPointerException if an array element is {@code null}
9364     */
9365    public static long[] toPrimitive(final Long[] array) {
9366        if (array == null) {
9367            return null;
9368        }
9369        if (array.length == 0) {
9370            return EMPTY_LONG_ARRAY;
9371        }
9372        final long[] result = new long[array.length];
9373        for (int i = 0; i < array.length; i++) {
9374            result[i] = array[i].longValue();
9375        }
9376        return result;
9377    }
9378
9379    /**
9380     * Converts an array of object Long to primitives handling {@code null}.
9381     * <p>
9382     * This method returns {@code null} for a {@code null} input array.
9383     * </p>
9384     *
9385     * @param array  a {@link Long} array, may be {@code null}
9386     * @param valueForNull  the value to insert if {@code null} found
9387     * @return a {@code long} array, {@code null} if null array input
9388     */
9389    public static long[] toPrimitive(final Long[] array, final long valueForNull) {
9390        if (array == null) {
9391            return null;
9392        }
9393        if (array.length == 0) {
9394            return EMPTY_LONG_ARRAY;
9395        }
9396        final long[] result = new long[array.length];
9397        for (int i = 0; i < array.length; i++) {
9398            final Long b = array[i];
9399            result[i] = b == null ? valueForNull : b.longValue();
9400        }
9401        return result;
9402    }
9403
9404    /**
9405     * Create an array of primitive type from an array of wrapper types.
9406     * <p>
9407     * This method returns {@code null} for a {@code null} input array.
9408     * </p>
9409     *
9410     * @param array  an array of wrapper object
9411     * @return an array of the corresponding primitive type, or the original array
9412     * @since 3.5
9413     */
9414    public static Object toPrimitive(final Object array) {
9415        if (array == null) {
9416            return null;
9417        }
9418        final Class<?> ct = array.getClass().getComponentType();
9419        final Class<?> pt = ClassUtils.wrapperToPrimitive(ct);
9420        if (Boolean.TYPE.equals(pt)) {
9421            return toPrimitive((Boolean[]) array);
9422        }
9423        if (Character.TYPE.equals(pt)) {
9424            return toPrimitive((Character[]) array);
9425        }
9426        if (Byte.TYPE.equals(pt)) {
9427            return toPrimitive((Byte[]) array);
9428        }
9429        if (Integer.TYPE.equals(pt)) {
9430            return toPrimitive((Integer[]) array);
9431        }
9432        if (Long.TYPE.equals(pt)) {
9433            return toPrimitive((Long[]) array);
9434        }
9435        if (Short.TYPE.equals(pt)) {
9436            return toPrimitive((Short[]) array);
9437        }
9438        if (Double.TYPE.equals(pt)) {
9439            return toPrimitive((Double[]) array);
9440        }
9441        if (Float.TYPE.equals(pt)) {
9442            return toPrimitive((Float[]) array);
9443        }
9444        return array;
9445    }
9446
9447    /**
9448     * Converts an array of object Shorts to primitives.
9449     * <p>
9450     * This method returns {@code null} for a {@code null} input array.
9451     * </p>
9452     *
9453     * @param array  a {@link Short} array, may be {@code null}
9454     * @return a {@code byte} array, {@code null} if null array input
9455     * @throws NullPointerException if an array element is {@code null}
9456     */
9457    public static short[] toPrimitive(final Short[] array) {
9458        if (array == null) {
9459            return null;
9460        }
9461        if (array.length == 0) {
9462            return EMPTY_SHORT_ARRAY;
9463        }
9464        final short[] result = new short[array.length];
9465        for (int i = 0; i < array.length; i++) {
9466            result[i] = array[i].shortValue();
9467        }
9468        return result;
9469    }
9470
9471    /**
9472     * Converts an array of object Short to primitives handling {@code null}.
9473     * <p>
9474     * This method returns {@code null} for a {@code null} input array.
9475     * </p>
9476     *
9477     * @param array  a {@link Short} array, may be {@code null}
9478     * @param valueForNull  the value to insert if {@code null} found
9479     * @return a {@code byte} array, {@code null} if null array input
9480     */
9481    public static short[] toPrimitive(final Short[] array, final short valueForNull) {
9482        if (array == null) {
9483            return null;
9484        }
9485        if (array.length == 0) {
9486            return EMPTY_SHORT_ARRAY;
9487        }
9488        final short[] result = new short[array.length];
9489        for (int i = 0; i < array.length; i++) {
9490            final Short b = array[i];
9491            result[i] = b == null ? valueForNull : b.shortValue();
9492        }
9493        return result;
9494    }
9495
9496    /**
9497     * Outputs an array as a String, treating {@code null} as an empty array.
9498     * <p>
9499     * Multi-dimensional arrays are handled correctly, including
9500     * multi-dimensional primitive arrays.
9501     * </p>
9502     * <p>
9503     * The format is that of Java source code, for example {@code {a,b}}.
9504     * </p>
9505     *
9506     * @param array  the array to get a toString for, may be {@code null}
9507     * @return a String representation of the array, '{}' if null array input
9508     */
9509    public static String toString(final Object array) {
9510        return toString(array, "{}");
9511    }
9512
9513    /**
9514     * Outputs an array as a String handling {@code null}s.
9515     * <p>
9516     * Multi-dimensional arrays are handled correctly, including
9517     * multi-dimensional primitive arrays.
9518     * </p>
9519     * <p>
9520     * The format is that of Java source code, for example {@code {a,b}}.
9521     * </p>
9522     *
9523     * @param array  the array to get a toString for, may be {@code null}
9524     * @param stringIfNull  the String to return if the array is {@code null}
9525     * @return a String representation of the array
9526     */
9527    public static String toString(final Object array, final String stringIfNull) {
9528        if (array == null) {
9529            return stringIfNull;
9530        }
9531        return new ToStringBuilder(array, ToStringStyle.SIMPLE_STYLE).append(array).toString();
9532    }
9533
9534    /**
9535     * Returns an array containing the string representation of each element in the argument array.
9536     * <p>
9537     * This method returns {@code null} for a {@code null} input array.
9538     * </p>
9539     *
9540     * @param array the {@code Object[]} to be processed, may be {@code null}.
9541     * @return {@code String[]} of the same size as the source with its element's string representation,
9542     * {@code null} if null array input
9543     * @since 3.6
9544     */
9545    public static String[] toStringArray(final Object[] array) {
9546        return toStringArray(array, "null");
9547    }
9548
9549    /**
9550     * Returns an array containing the string representation of each element in the argument
9551     * array handling {@code null} elements.
9552     * <p>
9553     * This method returns {@code null} for a {@code null} input array.
9554     * </p>
9555     *
9556     * @param array the Object[] to be processed, may be {@code null}.
9557     * @param valueForNullElements the value to insert if {@code null} is found
9558     * @return a {@link String} array, {@code null} if null array input
9559     * @since 3.6
9560     */
9561    public static String[] toStringArray(final Object[] array, final String valueForNullElements) {
9562        if (null == array) {
9563            return null;
9564        }
9565        if (array.length == 0) {
9566            return EMPTY_STRING_ARRAY;
9567        }
9568        return map(array, String.class, e -> Objects.toString(e, valueForNullElements));
9569    }
9570
9571    /**
9572     * ArrayUtils instances should NOT be constructed in standard programming.
9573     * Instead, the class should be used as {@code ArrayUtils.clone(new int[] {2})}.
9574     * <p>
9575     * This constructor is public to permit tools that require a JavaBean instance
9576     * to operate.
9577     * </p>
9578     *
9579     * @deprecated TODO Make private in 4.0.
9580     */
9581    @Deprecated
9582    public ArrayUtils() {
9583        // empty
9584    }
9585}