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