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