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