View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3;
18  
19  import java.lang.reflect.Array;
20  import java.lang.reflect.Field;
21  import java.lang.reflect.Method;
22  import java.lang.reflect.Type;
23  import java.security.SecureRandom;
24  import java.util.Arrays;
25  import java.util.BitSet;
26  import java.util.Comparator;
27  import java.util.Date;
28  import java.util.HashMap;
29  import java.util.Map;
30  import java.util.Objects;
31  import java.util.Random;
32  import java.util.concurrent.ThreadLocalRandom;
33  import java.util.function.Function;
34  import java.util.function.IntFunction;
35  import java.util.function.Supplier;
36  
37  import org.apache.commons.lang3.builder.EqualsBuilder;
38  import org.apache.commons.lang3.builder.HashCodeBuilder;
39  import org.apache.commons.lang3.builder.ToStringBuilder;
40  import org.apache.commons.lang3.builder.ToStringStyle;
41  import org.apache.commons.lang3.function.FailableFunction;
42  import org.apache.commons.lang3.mutable.MutableInt;
43  import org.apache.commons.lang3.stream.IntStreams;
44  import org.apache.commons.lang3.stream.Streams;
45  
46  /**
47   * Operations on arrays, primitive arrays (like {@code int[]}) and
48   * primitive wrapper arrays (like {@code Integer[]}).
49   * <p>
50   * This class tries to handle {@code null} input gracefully.
51   * An exception will not be thrown for a {@code null}
52   * array input. However, an Object array that contains a {@code null}
53   * element may throw an exception. Each method documents its behavior.
54   * </p>
55   * <p>
56   * #ThreadSafe#
57   * </p>
58   *
59   * @since 2.0
60   */
61  public class ArrayUtils {
62  
63      /**
64       * Bridge class to {@link Math} methods for testing purposes.
65       */
66      static class MathBridge {
67          static int addExact(final int a, final int b) {
68              return Math.addExact(a, b);
69          }
70      }
71  
72      /**
73       * An empty immutable {@code boolean} array.
74       */
75      public static final boolean[] EMPTY_BOOLEAN_ARRAY = {};
76  
77      /**
78       * An empty immutable {@link Boolean} array.
79       */
80      public static final Boolean[] EMPTY_BOOLEAN_OBJECT_ARRAY = {};
81  
82      /**
83       * An empty immutable {@code byte} array.
84       */
85      public static final byte[] EMPTY_BYTE_ARRAY = {};
86  
87      /**
88       * An empty immutable {@link Byte} array.
89       */
90      public static final Byte[] EMPTY_BYTE_OBJECT_ARRAY = {};
91  
92      /**
93       * An empty immutable {@code char} array.
94       */
95      public static final char[] EMPTY_CHAR_ARRAY = {};
96  
97      /**
98       * An empty immutable {@link Character} array.
99       */
100     public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = {};
101 
102     /**
103      * An empty immutable {@link Class} array.
104      */
105     public static final Class<?>[] EMPTY_CLASS_ARRAY = {};
106 
107     /**
108      * An empty immutable {@code double} array.
109      */
110     public static final double[] EMPTY_DOUBLE_ARRAY = {};
111 
112     /**
113      * An empty immutable {@link Double} array.
114      */
115     public static final Double[] EMPTY_DOUBLE_OBJECT_ARRAY = {};
116 
117     /**
118      * An empty immutable {@link Field} array.
119      *
120      * @since 3.10
121      */
122     public static final Field[] EMPTY_FIELD_ARRAY = {};
123 
124     /**
125      * An empty immutable {@code float} array.
126      */
127     public static final float[] EMPTY_FLOAT_ARRAY = {};
128 
129     /**
130      * An empty immutable {@link Float} array.
131      */
132     public static final Float[] EMPTY_FLOAT_OBJECT_ARRAY = {};
133 
134     /**
135      * An empty immutable {@code int} array.
136      */
137     public static final int[] EMPTY_INT_ARRAY = {};
138 
139     /**
140      * An empty immutable {@link Integer} array.
141      */
142     public static final Integer[] EMPTY_INTEGER_OBJECT_ARRAY = {};
143 
144     /**
145      * An empty immutable {@code long} array.
146      */
147     public static final long[] EMPTY_LONG_ARRAY = {};
148 
149     /**
150      * An empty immutable {@link Long} array.
151      */
152     public static final Long[] EMPTY_LONG_OBJECT_ARRAY = {};
153 
154     /**
155      * An empty immutable {@link Method} array.
156      *
157      * @since 3.10
158      */
159     public static final Method[] EMPTY_METHOD_ARRAY = {};
160 
161     /**
162      * An empty immutable {@link Object} array.
163      */
164     public static final Object[] EMPTY_OBJECT_ARRAY = {};
165 
166     /**
167      * An empty immutable {@code short} array.
168      */
169     public static final short[] EMPTY_SHORT_ARRAY = {};
170 
171     /**
172      * An empty immutable {@link Short} array.
173      */
174     public static final Short[] EMPTY_SHORT_OBJECT_ARRAY = {};
175 
176     /**
177      * An empty immutable {@link String} array.
178      */
179     public static final String[] EMPTY_STRING_ARRAY = {};
180 
181     /**
182      * An empty immutable {@link Throwable} array.
183      *
184      * @since 3.10
185      */
186     public static final Throwable[] EMPTY_THROWABLE_ARRAY = {};
187 
188     /**
189      * An empty immutable {@link Type} array.
190      *
191      * @since 3.10
192      */
193     public static final Type[] EMPTY_TYPE_ARRAY = {};
194 
195     /**
196      * The index value when an element is not found in a list or array: {@code -1}.
197      * This value is returned by methods in this class and can also be used in comparisons with values returned by
198      * various method from {@link java.util.List}.
199      */
200     public static final int INDEX_NOT_FOUND = -1;
201 
202     /**
203      * The {@code SOFT_MAX_ARRAY_LENGTH} constant from Java's internal ArraySupport class.
204      *
205      * @since 3.19.0
206      * @deprecated This variable will be final in 4.0; to guarantee immutability now, use {@link #SAFE_MAX_ARRAY_LENGTH}.
207      */
208     @Deprecated
209     public static int SOFT_MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;
210 
211     /**
212      * The {@code MAX_ARRAY_LENGTH} constant from Java's internal ArraySupport class.
213      *
214      * @since 3.21.0
215      */
216     public static final int SAFE_MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;
217 
218     /**
219      * Copies the given array and adds the given element at the end of the new array.
220      * <p>
221      * The new array contains the same elements of the input
222      * array plus the given element in the last position. The component type of
223      * the new array is the same as that of the input array.
224      * </p>
225      * <p>
226      * If the input array is {@code null}, a new one element array is returned
227      * whose component type is the same as the element.
228      * </p>
229      * <pre>
230      * ArrayUtils.add(null, true)          = [true]
231      * ArrayUtils.add([true], false)       = [true, false]
232      * ArrayUtils.add([true, false], true) = [true, false, true]
233      * </pre>
234      *
235      * @param array  the array to copy and add the element to, may be {@code null}.
236      * @param element  the object to add at the last index of the new array.
237      * @return A new array containing the existing elements plus the new element.
238      * @since 2.1
239      */
240     public static boolean[] add(final boolean[] array, final boolean element) {
241         final boolean[] newArray = (boolean[]) copyArrayGrow1(array, Boolean.TYPE);
242         newArray[newArray.length - 1] = element;
243         return newArray;
244     }
245 
246     /**
247      * Inserts the specified element at the specified position in the array.
248      * Shifts the element currently at that position (if any) and any subsequent
249      * elements to the right (adds one to their indices).
250      * <p>
251      * This method returns a new array with the same elements of the input
252      * array plus the given element on the specified position. The component
253      * type of the returned array is always the same as that of the input
254      * array.
255      * </p>
256      * <p>
257      * If the input array is {@code null}, a new one element array is returned
258      * whose component type is the same as the element.
259      * </p>
260      * <pre>
261      * ArrayUtils.add(null, 0, true)          = [true]
262      * ArrayUtils.add([true], 0, false)       = [false, true]
263      * ArrayUtils.add([false], 1, true)       = [false, true]
264      * ArrayUtils.add([true, false], 1, true) = [true, true, false]
265      * </pre>
266      *
267      * @param array  the array to add the element to, may be {@code null}.
268      * @param index  the position of the new object.
269      * @param element  the object to add.
270      * @return A new array containing the existing elements and the new element.
271      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt; array.length).
272      * @deprecated this method has been superseded by {@link #insert(int, boolean[], boolean...)} and
273      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
274      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
275      */
276     @Deprecated
277     public static boolean[] add(final boolean[] array, final int index, final boolean element) {
278         return (boolean[]) add(array, index, Boolean.valueOf(element), Boolean.TYPE);
279     }
280 
281     /**
282      * Copies the given array and adds the given element at the end of the new array.
283      * <p>
284      * The new array contains the same elements of the input
285      * array plus the given element in the last position. The component type of
286      * the new array is the same as that of the input array.
287      * </p>
288      * <p>
289      * If the input array is {@code null}, a new one element array is returned
290      * whose component type is the same as the element.
291      * </p>
292      * <pre>
293      * ArrayUtils.add(null, 0)   = [0]
294      * ArrayUtils.add([1], 0)    = [1, 0]
295      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
296      * </pre>
297      *
298      * @param array  the array to copy and add the element to, may be {@code null}.
299      * @param element  the object to add at the last index of the new array.
300      * @return A new array containing the existing elements plus the new element.
301      * @since 2.1
302      */
303     public static byte[] add(final byte[] array, final byte element) {
304         final byte[] newArray = (byte[]) copyArrayGrow1(array, Byte.TYPE);
305         newArray[newArray.length - 1] = element;
306         return newArray;
307     }
308 
309     /**
310      * Inserts the specified element at the specified position in the array.
311      * Shifts the element currently at that position (if any) and any subsequent
312      * elements to the right (adds one to their indices).
313      * <p>
314      * This method returns a new array with the same elements of the input
315      * array plus the given element on the specified position. The component
316      * type of the returned array is always the same as that of the input
317      * array.
318      * </p>
319      * <p>
320      * If the input array is {@code null}, a new one element array is returned
321      * whose component type is the same as the element.
322      * </p>
323      * <pre>
324      * ArrayUtils.add([1], 0, 2)         = [2, 1]
325      * ArrayUtils.add([2, 6], 2, 3)      = [2, 6, 3]
326      * ArrayUtils.add([2, 6], 0, 1)      = [1, 2, 6]
327      * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
328      * </pre>
329      *
330      * @param array  the array to add the element to, may be {@code null}.
331      * @param index  the position of the new object.
332      * @param element  the object to add.
333      * @return A new array containing the existing elements and the new element.
334      * @throws IndexOutOfBoundsException if the index is out of range.
335      * (index &lt; 0 || index &gt; array.length).
336      * @deprecated this method has been superseded by {@link #insert(int, byte[], byte...)} and
337      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
338      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
339      */
340     @Deprecated
341     public static byte[] add(final byte[] array, final int index, final byte element) {
342         return (byte[]) add(array, index, Byte.valueOf(element), Byte.TYPE);
343     }
344 
345     /**
346      * Copies the given array and adds the given element at the end of the new array.
347      * <p>
348      * The new array contains the same elements of the input
349      * array plus the given element in the last position. The component type of
350      * the new array is the same as that of the input array.
351      * </p>
352      * <p>
353      * If the input array is {@code null}, a new one element array is returned
354      * whose component type is the same as the element.
355      * </p>
356      * <pre>
357      * ArrayUtils.add(null, '0')       = ['0']
358      * ArrayUtils.add(['1'], '0')      = ['1', '0']
359      * ArrayUtils.add(['1', '0'], '1') = ['1', '0', '1']
360      * </pre>
361      *
362      * @param array  the array to copy and add the element to, may be {@code null}.
363      * @param element  the object to add at the last index of the new array.
364      * @return A new array containing the existing elements plus the new element.
365      * @since 2.1
366      */
367     public static char[] add(final char[] array, final char element) {
368         final char[] newArray = (char[]) copyArrayGrow1(array, Character.TYPE);
369         newArray[newArray.length - 1] = element;
370         return newArray;
371     }
372 
373     /**
374      * Inserts the specified element at the specified position in the array.
375      * Shifts the element currently at that position (if any) and any subsequent
376      * elements to the right (adds one to their indices).
377      * <p>
378      * This method returns a new array with the same elements of the input
379      * array plus the given element on the specified position. The component
380      * type of the returned array is always the same as that of the input
381      * array.
382      * </p>
383      * <p>
384      * If the input array is {@code null}, a new one element array is returned
385      * whose component type is the same as the element.
386      * </p>
387      * <pre>
388      * ArrayUtils.add(null, 0, 'a')            = ['a']
389      * ArrayUtils.add(['a'], 0, 'b')           = ['b', 'a']
390      * ArrayUtils.add(['a', 'b'], 0, 'c')      = ['c', 'a', 'b']
391      * ArrayUtils.add(['a', 'b'], 1, 'k')      = ['a', 'k', 'b']
392      * ArrayUtils.add(['a', 'b', 'c'], 1, 't') = ['a', 't', 'b', 'c']
393      * </pre>
394      *
395      * @param array  the array to add the element to, may be {@code null}.
396      * @param index  the position of the new object.
397      * @param element  the object to add.
398      * @return A new array containing the existing elements and the new element.
399      * @throws IndexOutOfBoundsException if the index is out of range.
400      * (index &lt; 0 || index &gt; array.length).
401      * @deprecated this method has been superseded by {@link #insert(int, char[], char...)} and
402      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
403      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
404      */
405     @Deprecated
406     public static char[] add(final char[] array, final int index, final char element) {
407         return (char[]) add(array, index, Character.valueOf(element), Character.TYPE);
408     }
409 
410     /**
411      * Copies the given array and adds the given element at the end of the new array.
412      *
413      * <p>
414      * The new array contains the same elements of the input
415      * array plus the given element in the last position. The component type of
416      * the new array is the same as that of the input array.
417      * </p>
418      * <p>
419      * If the input array is {@code null}, a new one element array is returned
420      * whose component type is the same as the element.
421      * </p>
422      * <pre>
423      * ArrayUtils.add(null, 0)   = [0]
424      * ArrayUtils.add([1], 0)    = [1, 0]
425      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
426      * </pre>
427      *
428      * @param array  the array to copy and add the element to, may be {@code null}.
429      * @param element  the object to add at the last index of the new array.
430      * @return A new array containing the existing elements plus the new element.
431      * @since 2.1
432      */
433     public static double[] add(final double[] array, final double element) {
434         final double[] newArray = (double[]) copyArrayGrow1(array, Double.TYPE);
435         newArray[newArray.length - 1] = element;
436         return newArray;
437     }
438 
439     /**
440      * Inserts the specified element at the specified position in the array.
441      * Shifts the element currently at that position (if any) and any subsequent
442      * elements to the right (adds one to their indices).
443      * <p>
444      * This method returns a new array with the same elements of the input
445      * array plus the given element on the specified position. The component
446      * type of the returned array is always the same as that of the input
447      * array.
448      * </p>
449      * <p>
450      * If the input array is {@code null}, a new one element array is returned
451      * whose component type is the same as the element.
452      * </p>
453      * <pre>
454      * ArrayUtils.add([1.1], 0, 2.2)              = [2.2, 1.1]
455      * ArrayUtils.add([2.3, 6.4], 2, 10.5)        = [2.3, 6.4, 10.5]
456      * ArrayUtils.add([2.6, 6.7], 0, -4.8)        = [-4.8, 2.6, 6.7]
457      * ArrayUtils.add([2.9, 6.0, 0.3], 2, 1.0)    = [2.9, 6.0, 1.0, 0.3]
458      * </pre>
459      *
460      * @param array  the array to add the element to, may be {@code null}.
461      * @param index  the position of the new object.
462      * @param element  the object to add.
463      * @return A new array containing the existing elements and the new element.
464      * @throws IndexOutOfBoundsException if the index is out of range
465      * (index &lt; 0 || index &gt; array.length).
466      * @deprecated this method has been superseded by {@link #insert(int, double[], double...)} and
467      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
468      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
469      */
470     @Deprecated
471     public static double[] add(final double[] array, final int index, final double element) {
472         return (double[]) add(array, index, Double.valueOf(element), Double.TYPE);
473     }
474 
475     /**
476      * Copies the given array and adds the given element at the end of the new array.
477      * <p>
478      * The new array contains the same elements of the input
479      * array plus the given element in the last position. The component type of
480      * the new array is the same as that of the input array.
481      * </p>
482      * <p>
483      * If the input array is {@code null}, a new one element array is returned
484      * whose component type is the same as the element.
485      * </p>
486      * <pre>
487      * ArrayUtils.add(null, 0)   = [0]
488      * ArrayUtils.add([1], 0)    = [1, 0]
489      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
490      * </pre>
491      *
492      * @param array  the array to copy and add the element to, may be {@code null}.
493      * @param element  the object to add at the last index of the new array.
494      * @return A new array containing the existing elements plus the new element.
495      * @since 2.1
496      */
497     public static float[] add(final float[] array, final float element) {
498         final float[] newArray = (float[]) copyArrayGrow1(array, Float.TYPE);
499         newArray[newArray.length - 1] = element;
500         return newArray;
501     }
502 
503     /**
504      * Inserts the specified element at the specified position in the array.
505      * Shifts the element currently at that position (if any) and any subsequent
506      * elements to the right (adds one to their indices).
507      * <p>
508      * This method returns a new array with the same elements of the input
509      * array plus the given element on the specified position. The component
510      * type of the returned array is always the same as that of the input
511      * array.
512      * </p>
513      * <p>
514      * If the input array is {@code null}, a new one element array is returned
515      * whose component type is the same as the element.
516      * </p>
517      * <pre>
518      * ArrayUtils.add([1.1f], 0, 2.2f)               = [2.2f, 1.1f]
519      * ArrayUtils.add([2.3f, 6.4f], 2, 10.5f)        = [2.3f, 6.4f, 10.5f]
520      * ArrayUtils.add([2.6f, 6.7f], 0, -4.8f)        = [-4.8f, 2.6f, 6.7f]
521      * ArrayUtils.add([2.9f, 6.0f, 0.3f], 2, 1.0f)   = [2.9f, 6.0f, 1.0f, 0.3f]
522      * </pre>
523      *
524      * @param array  the array to add the element to, may be {@code null}.
525      * @param index  the position of the new object.
526      * @param element  the object to add.
527      * @return A new array containing the existing elements and the new element.
528      * @throws IndexOutOfBoundsException if the index is out of range
529      * (index &lt; 0 || index &gt; array.length).
530      * @deprecated this method has been superseded by {@link #insert(int, float[], float...)} and
531      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
532      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
533      */
534     @Deprecated
535     public static float[] add(final float[] array, final int index, final float element) {
536         return (float[]) add(array, index, Float.valueOf(element), Float.TYPE);
537     }
538 
539     /**
540      * Copies the given array and adds the given element at the end of the new array.
541      * <p>
542      * The new array contains the same elements of the input
543      * array plus the given element in the last position. The component type of
544      * the new array is the same as that of the input array.
545      * </p>
546      * <p>
547      * If the input array is {@code null}, a new one element array is returned
548      * whose component type is the same as the element.
549      * </p>
550      * <pre>
551      * ArrayUtils.add(null, 0)   = [0]
552      * ArrayUtils.add([1], 0)    = [1, 0]
553      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
554      * </pre>
555      *
556      * @param array  the array to copy and add the element to, may be {@code null}.
557      * @param element  the object to add at the last index of the new array.
558      * @return A new array containing the existing elements plus the new element.
559      * @since 2.1
560      */
561     public static int[] add(final int[] array, final int element) {
562         final int[] newArray = (int[]) copyArrayGrow1(array, Integer.TYPE);
563         newArray[newArray.length - 1] = element;
564         return newArray;
565     }
566 
567     /**
568      * Inserts the specified element at the specified position in the array.
569      * Shifts the element currently at that position (if any) and any subsequent
570      * elements to the right (adds one to their indices).
571      * <p>
572      * This method returns a new array with the same elements of the input
573      * array plus the given element on the specified position. The component
574      * type of the returned array is always the same as that of the input
575      * array.
576      * </p>
577      * <p>
578      * If the input array is {@code null}, a new one element array is returned
579      * whose component type is the same as the element.
580      * </p>
581      * <pre>
582      * ArrayUtils.add([1], 0, 2)         = [2, 1]
583      * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
584      * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
585      * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
586      * </pre>
587      *
588      * @param array  the array to add the element to, may be {@code null}.
589      * @param index  the position of the new object.
590      * @param element  the object to add.
591      * @return A new array containing the existing elements and the new element.
592      * @throws IndexOutOfBoundsException if the index is out of range
593      * (index &lt; 0 || index &gt; array.length).
594      * @deprecated this method has been superseded by {@link #insert(int, int[], int...)} and
595      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
596      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
597      */
598     @Deprecated
599     public static int[] add(final int[] array, final int index, final int element) {
600         return (int[]) add(array, index, Integer.valueOf(element), Integer.TYPE);
601     }
602 
603     /**
604      * Inserts the specified element at the specified position in the array.
605      * Shifts the element currently at that position (if any) and any subsequent
606      * elements to the right (adds one to their indices).
607      * <p>
608      * This method returns a new array with the same elements of the input
609      * array plus the given element on the specified position. The component
610      * type of the returned array is always the same as that of the input
611      * array.
612      * </p>
613      * <p>
614      * If the input array is {@code null}, a new one element array is returned
615      * whose component type is the same as the element.
616      * </p>
617      * <pre>
618      * ArrayUtils.add([1L], 0, 2L)           = [2L, 1L]
619      * ArrayUtils.add([2L, 6L], 2, 10L)      = [2L, 6L, 10L]
620      * ArrayUtils.add([2L, 6L], 0, -4L)      = [-4L, 2L, 6L]
621      * ArrayUtils.add([2L, 6L, 3L], 2, 1L)   = [2L, 6L, 1L, 3L]
622      * </pre>
623      *
624      * @param array  the array to add the element to, may be {@code null}.
625      * @param index  the position of the new object.
626      * @param element  the object to add.
627      * @return A new array containing the existing elements and the new element.
628      * @throws IndexOutOfBoundsException if the index is out of range
629      * (index &lt; 0 || index &gt; array.length).
630      * @deprecated this method has been superseded by {@link #insert(int, long[], long...)} and
631      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
632      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
633      */
634     @Deprecated
635     public static long[] add(final long[] array, final int index, final long element) {
636         return (long[]) add(array, index, Long.valueOf(element), Long.TYPE);
637     }
638 
639     /**
640      * Copies the given array and adds the given element at the end of the new array.
641      * <p>
642      * The new array contains the same elements of the input
643      * array plus the given element in the last position. The component type of
644      * the new array is the same as that of the input array.
645      * </p>
646      * <p>
647      * If the input array is {@code null}, a new one element array is returned
648      * whose component type is the same as the element.
649      * </p>
650      * <pre>
651      * ArrayUtils.add(null, 0)   = [0]
652      * ArrayUtils.add([1], 0)    = [1, 0]
653      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
654      * </pre>
655      *
656      * @param array  the array to copy and add the element to, may be {@code null}.
657      * @param element  the object to add at the last index of the new array.
658      * @return A new array containing the existing elements plus the new element.
659      * @since 2.1
660      */
661     public static long[] add(final long[] array, final long element) {
662         final long[] newArray = (long[]) copyArrayGrow1(array, Long.TYPE);
663         newArray[newArray.length - 1] = element;
664         return newArray;
665     }
666 
667     /**
668      * Underlying implementation of add(array, index, element) methods.
669      * The last parameter is the class, which may not equal element.getClass
670      * for primitives.
671      *
672      * @param array  the array to add the element to, may be {@code null}.
673      * @param index  the position of the new object.
674      * @param element  the object to add.
675      * @param clazz the type of the element being added.
676      * @return A new array containing the existing elements and the new element.
677      */
678     private static Object add(final Object array, final int index, final Object element, final Class<?> clazz) {
679         if (array == null) {
680             if (index != 0) {
681                 throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
682             }
683             final Object joinedArray = Array.newInstance(clazz, 1);
684             Array.set(joinedArray, 0, element);
685             return joinedArray;
686         }
687         final int length = Array.getLength(array);
688         if (index > length || index < 0) {
689             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
690         }
691         final Object result = arraycopy(array, 0, 0, index, () -> Array.newInstance(clazz, length + 1));
692         Array.set(result, index, element);
693         if (index < length) {
694             System.arraycopy(array, index, result, index + 1, length - index);
695         }
696         return result;
697     }
698 
699     /**
700      * Inserts the specified element at the specified position in the array.
701      * Shifts the element currently at that position (if any) and any subsequent
702      * elements to the right (adds one to their indices).
703      * <p>
704      * This method returns a new array with the same elements of the input
705      * array plus the given element on the specified position. The component
706      * type of the returned array is always the same as that of the input
707      * array.
708      * </p>
709      * <p>
710      * If the input array is {@code null}, a new one element array is returned
711      * whose component type is the same as the element.
712      * </p>
713      * <pre>
714      * ArrayUtils.add([1], 0, 2)         = [2, 1]
715      * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
716      * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
717      * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
718      * </pre>
719      *
720      * @param array  the array to add the element to, may be {@code null}.
721      * @param index  the position of the new object.
722      * @param element  the object to add.
723      * @return A new array containing the existing elements and the new element.
724      * @throws IndexOutOfBoundsException if the index is out of range
725      * (index &lt; 0 || index &gt; array.length).
726      * @deprecated this method has been superseded by {@link #insert(int, short[], short...)} and
727      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
728      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
729      */
730     @Deprecated
731     public static short[] add(final short[] array, final int index, final short element) {
732         return (short[]) add(array, index, Short.valueOf(element), Short.TYPE);
733     }
734 
735     /**
736      * Copies the given array and adds the given element at the end of the new array.
737      * <p>
738      * The new array contains the same elements of the input
739      * array plus the given element in the last position. The component type of
740      * the new array is the same as that of the input array.
741      * </p>
742      * <p>
743      * If the input array is {@code null}, a new one element array is returned
744      * whose component type is the same as the element.
745      * </p>
746      * <pre>
747      * ArrayUtils.add(null, 0)   = [0]
748      * ArrayUtils.add([1], 0)    = [1, 0]
749      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
750      * </pre>
751      *
752      * @param array  the array to copy and add the element to, may be {@code null}.
753      * @param element  the object to add at the last index of the new array.
754      * @return A new array containing the existing elements plus the new element.
755      * @since 2.1
756      */
757     public static short[] add(final short[] array, final short element) {
758         final short[] newArray = (short[]) copyArrayGrow1(array, Short.TYPE);
759         newArray[newArray.length - 1] = element;
760         return newArray;
761     }
762 
763     /**
764      * Inserts the specified element at the specified position in the array.
765      * Shifts the element currently at that position (if any) and any subsequent
766      * elements to the right (adds one to their indices).
767      * <p>
768      * This method returns a new array with the same elements of the input
769      * array plus the given element on the specified position. The component
770      * type of the returned array is always the same as that of the input
771      * array.
772      * </p>
773      * <p>
774      * If the input array is {@code null}, a new one element array is returned
775      * whose component type is the same as the element.
776      * </p>
777      * <pre>
778      * ArrayUtils.add(null, 0, null)      = Throws {@link IllegalArgumentException}
779      * ArrayUtils.add(null, 0, "a")       = ["a"]
780      * ArrayUtils.add(["a"], 1, null)     = ["a", null]
781      * ArrayUtils.add(["a"], 1, "b")      = ["a", "b"]
782      * ArrayUtils.add(["a", "b"], 3, "c") = ["a", "b", "c"]
783      * </pre>
784      *
785      * @param <T> the component type of the array.
786      * @param array  the array to add the element to, may be {@code null}.
787      * @param index  the position of the new object.
788      * @param element  the object to add.
789      * @return A new array containing the existing elements and the new element.
790      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt; array.length).
791      * @throws IllegalArgumentException if both array and element are null.
792      * @deprecated this method has been superseded by {@link #insert(int, Object[], Object...) insert(int, T[], T...)} and
793      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
794      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
795      */
796     @Deprecated
797     public static <T> T[] add(final T[] array, final int index, final T element) {
798         final Class<T> clazz;
799         if (array != null) {
800             clazz = getComponentType(array);
801         } else if (element != null) {
802             clazz = ObjectUtils.getClass(element);
803         } else {
804             throw new IllegalArgumentException("Array and element cannot both be null");
805         }
806         return (T[]) add(array, index, element, clazz);
807     }
808 
809     /**
810      * Copies the given array and adds the given element at the end of the new array.
811      * <p>
812      * The new array contains the same elements of the input
813      * array plus the given element in the last position. The component type of
814      * the new array is the same as that of the input array.
815      * </p>
816      * <p>
817      * If the input array is {@code null}, a new one element array is returned
818      * whose component type is the same as the element, unless the element itself is null,
819      * in which case the return type is Object[]
820      * </p>
821      * <pre>
822      * ArrayUtils.add(null, null)      = Throws {@link IllegalArgumentException}
823      * ArrayUtils.add(null, "a")       = ["a"]
824      * ArrayUtils.add(["a"], null)     = ["a", null]
825      * ArrayUtils.add(["a"], "b")      = ["a", "b"]
826      * ArrayUtils.add(["a", "b"], "c") = ["a", "b", "c"]
827      * </pre>
828      *
829      * @param <T> the component type of the array.
830      * @param array  the array to "add" the element to, may be {@code null}.
831      * @param element  the object to add, may be {@code null}.
832      * @return A new array containing the existing elements plus the new element
833      * The returned array type will be that of the input array (unless null),
834      * in which case it will have the same type as the element.
835      * If both are null, an IllegalArgumentException is thrown.
836      * @throws IllegalArgumentException if both arguments are null.
837      * @since 2.1
838      */
839     public static <T> T[] add(final T[] array, final T element) {
840         final Class<?> type;
841         if (array != null) {
842             type = array.getClass().getComponentType();
843         } else if (element != null) {
844             type = element.getClass();
845         } else {
846             throw new IllegalArgumentException("Arguments cannot both be null");
847         }
848         @SuppressWarnings("unchecked") // type must be T
849         final
850         T[] newArray = (T[]) copyArrayGrow1(array, type);
851         newArray[newArray.length - 1] = element;
852         return newArray;
853     }
854 
855     /**
856      * Adds all the elements of the given arrays into a new array.
857      * <p>
858      * The new array contains all of the element of {@code array1} followed
859      * by all of the elements {@code array2}. When an array is returned, it is always
860      * a new array.
861      * </p>
862      * <pre>
863      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
864      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
865      * ArrayUtils.addAll([], [])         = []
866      * ArrayUtils.addAll(null, null)     = null
867      * </pre>
868      *
869      * @param array1  the first array whose elements are added to the new array.
870      * @param array2  the second array whose elements are added to the new array.
871      * @return The new boolean[] array or {@code null}.
872      * @since 2.1
873      */
874     public static boolean[] addAll(final boolean[] array1, final boolean... array2) {
875         if (array1 == null) {
876             return clone(array2);
877         }
878         if (array2 == null) {
879             return clone(array1);
880         }
881         final boolean[] joinedArray = new boolean[array1.length + array2.length];
882         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
883         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
884         return joinedArray;
885     }
886 
887     /**
888      * Adds all the elements of the given arrays into a new array.
889      * <p>
890      * The new array contains all of the element of {@code array1} followed
891      * by all of the elements {@code array2}. When an array is returned, it is always
892      * a new array.
893      * </p>
894      * <pre>
895      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
896      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
897      * ArrayUtils.addAll([], [])         = []
898      * ArrayUtils.addAll(null, null)     = null
899      * </pre>
900      *
901      * @param array1  the first array whose elements are added to the new array.
902      * @param array2  the second array whose elements are added to the new array.
903      * @return The new byte[] array or {@code null}.
904      * @since 2.1
905      */
906     public static byte[] addAll(final byte[] array1, final byte... array2) {
907         if (array1 == null) {
908             return clone(array2);
909         }
910         if (array2 == null) {
911             return clone(array1);
912         }
913         final byte[] joinedArray = new byte[array1.length + array2.length];
914         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
915         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
916         return joinedArray;
917     }
918 
919     /**
920      * Adds all the elements of the given arrays into a new array.
921      * <p>
922      * The new array contains all of the element of {@code array1} followed
923      * by all of the elements {@code array2}. When an array is returned, it is always
924      * a new array.
925      * </p>
926      * <pre>
927      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
928      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
929      * ArrayUtils.addAll([], [])         = []
930      * ArrayUtils.addAll(null, null)     = null
931      * </pre>
932      *
933      * @param array1  the first array whose elements are added to the new array.
934      * @param array2  the second array whose elements are added to the new array.
935      * @return The new char[] array or {@code null}.
936      * @since 2.1
937      */
938     public static char[] addAll(final char[] array1, final char... array2) {
939         if (array1 == null) {
940             return clone(array2);
941         }
942         if (array2 == null) {
943             return clone(array1);
944         }
945         final char[] joinedArray = new char[array1.length + array2.length];
946         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
947         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
948         return joinedArray;
949     }
950 
951     /**
952      * Adds all the elements of the given arrays into a new array.
953      * <p>
954      * The new array contains all of the element of {@code array1} followed
955      * by all of the elements {@code array2}. When an array is returned, it is always
956      * a new array.
957      * </p>
958      * <pre>
959      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
960      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
961      * ArrayUtils.addAll([], [])         = []
962      * ArrayUtils.addAll(null, null)     = null
963      * </pre>
964      *
965      * @param array1  the first array whose elements are added to the new array.
966      * @param array2  the second array whose elements are added to the new array.
967      * @return The new double[] array or {@code null}.
968      * @since 2.1
969      */
970     public static double[] addAll(final double[] array1, final double... array2) {
971         if (array1 == null) {
972             return clone(array2);
973         }
974         if (array2 == null) {
975             return clone(array1);
976         }
977         final double[] joinedArray = new double[array1.length + array2.length];
978         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
979         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
980         return joinedArray;
981     }
982 
983     /**
984      * Adds all the elements of the given arrays into a new array.
985      * <p>
986      * The new array contains all of the element of {@code array1} followed
987      * by all of the elements {@code array2}. When an array is returned, it is always
988      * a new array.
989      * </p>
990      * <pre>
991      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
992      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
993      * ArrayUtils.addAll([], [])         = []
994      * ArrayUtils.addAll(null, null)     = null
995      * </pre>
996      *
997      * @param array1  the first array whose elements are added to the new array.
998      * @param array2  the second array whose elements are added to the new array.
999      * @return The new float[] array or {@code null}.
1000      * @since 2.1
1001      */
1002     public static float[] addAll(final float[] array1, final float... array2) {
1003         if (array1 == null) {
1004             return clone(array2);
1005         }
1006         if (array2 == null) {
1007             return clone(array1);
1008         }
1009         final float[] joinedArray = new float[array1.length + array2.length];
1010         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1011         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1012         return joinedArray;
1013     }
1014 
1015     /**
1016      * Adds all the elements of the given arrays into a new array.
1017      * <p>
1018      * The new array contains all of the element of {@code array1} followed
1019      * by all of the elements {@code array2}. When an array is returned, it is always
1020      * a new array.
1021      * </p>
1022      * <pre>
1023      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1024      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1025      * ArrayUtils.addAll([], [])         = []
1026      * ArrayUtils.addAll(null, null)     = null
1027      * </pre>
1028      *
1029      * @param array1  the first array whose elements are added to the new array.
1030      * @param array2  the second array whose elements are added to the new array.
1031      * @return The new int[] array or {@code null}.
1032      * @since 2.1
1033      */
1034     public static int[] addAll(final int[] array1, final int... array2) {
1035         if (array1 == null) {
1036             return clone(array2);
1037         }
1038         if (array2 == null) {
1039             return clone(array1);
1040         }
1041         final int[] joinedArray = new int[array1.length + array2.length];
1042         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1043         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1044         return joinedArray;
1045     }
1046 
1047     /**
1048      * Adds all the elements of the given arrays into a new array.
1049      * <p>
1050      * The new array contains all of the element of {@code array1} followed
1051      * by all of the elements {@code array2}. When an array is returned, it is always
1052      * a new array.
1053      * </p>
1054      * <pre>
1055      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1056      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1057      * ArrayUtils.addAll([], [])         = []
1058      * ArrayUtils.addAll(null, null)     = null
1059      * </pre>
1060      *
1061      * @param array1  the first array whose elements are added to the new array.
1062      * @param array2  the second array whose elements are added to the new array.
1063      * @return The new long[] array or {@code null}.
1064      * @since 2.1
1065      */
1066     public static long[] addAll(final long[] array1, final long... array2) {
1067         if (array1 == null) {
1068             return clone(array2);
1069         }
1070         if (array2 == null) {
1071             return clone(array1);
1072         }
1073         final long[] joinedArray = new long[array1.length + array2.length];
1074         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1075         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1076         return joinedArray;
1077     }
1078 
1079     /**
1080      * Adds all the elements of the given arrays into a new array.
1081      * <p>
1082      * The new array contains all of the element of {@code array1} followed
1083      * by all of the elements {@code array2}. When an array is returned, it is always
1084      * a new array.
1085      * </p>
1086      * <pre>
1087      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1088      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1089      * ArrayUtils.addAll([], [])         = []
1090      * ArrayUtils.addAll(null, null)     = null
1091      * </pre>
1092      *
1093      * @param array1  the first array whose elements are added to the new array.
1094      * @param array2  the second array whose elements are added to the new array.
1095      * @return The new short[] array or {@code null}.
1096      * @since 2.1
1097      */
1098     public static short[] addAll(final short[] array1, final short... array2) {
1099         if (array1 == null) {
1100             return clone(array2);
1101         }
1102         if (array2 == null) {
1103             return clone(array1);
1104         }
1105         final short[] joinedArray = new short[array1.length + array2.length];
1106         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1107         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1108         return joinedArray;
1109     }
1110 
1111     /**
1112      * Adds all the elements of the given arrays into a new array.
1113      * <p>
1114      * The new array contains all of the element of {@code array1} followed
1115      * by all of the elements {@code array2}. When an array is returned, it is always
1116      * a new array.
1117      * </p>
1118      * <pre>
1119      * ArrayUtils.addAll(null, null)     = null
1120      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1121      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1122      * ArrayUtils.addAll([], [])         = []
1123      * ArrayUtils.addAll(null, null)     = null
1124      * ArrayUtils.addAll([null], [null]) = [null, null]
1125      * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
1126      * </pre>
1127      *
1128      * @param <T> the component type of the array.
1129      * @param array1  the first array whose elements are added to the new array, may be {@code null}.
1130      * @param array2  the second array whose elements are added to the new array, may be {@code null}.
1131      * @return The new array, {@code null} if both arrays are {@code null}.
1132      *      The type of the new array is the type of the first array,
1133      *      unless the first array is null, in which case the type is the same as the second array.
1134      * @throws IllegalArgumentException if the array types are incompatible.
1135      * @since 2.1
1136      */
1137     public static <T> T[] addAll(final T[] array1, @SuppressWarnings("unchecked") final T... array2) {
1138         if (array1 == null) {
1139             return clone(array2);
1140         }
1141         if (array2 == null) {
1142             return clone(array1);
1143         }
1144         final Class<T> type1 = getComponentType(array1);
1145         final T[] joinedArray = arraycopy(array1, 0, 0, array1.length, () -> newInstance(type1, array1.length + array2.length));
1146         try {
1147             System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1148         } catch (final ArrayStoreException ase) {
1149             // Check if problem was due to incompatible types
1150             /*
1151              * 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
1152              * strict
1153              */
1154             final Class<?> type2 = array2.getClass().getComponentType();
1155             if (!type1.isAssignableFrom(type2)) {
1156                 throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of " + type1.getName(), ase);
1157             }
1158             throw ase; // No, so rethrow original
1159         }
1160         return joinedArray;
1161     }
1162 
1163     /**
1164      * Safely adds the length of an array to a running total, checking for overflow.
1165      *
1166      * @param totalLength the current accumulated length
1167      * @param array the array whose length should be added (can be {@code null},
1168      *              in which case its length is considered 0)
1169      * @return the new total length after adding the array's length
1170      * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1171      */
1172     private static int addExact(final int totalLength, final Object array) {
1173         try {
1174             final int length = MathBridge.addExact(totalLength, getLength(array));
1175             if (length > SAFE_MAX_ARRAY_LENGTH) {
1176                 throw new IllegalArgumentException("Total arrays length exceed " + SAFE_MAX_ARRAY_LENGTH);
1177             }
1178             return length;
1179         } catch (final ArithmeticException exception) {
1180             throw new IllegalArgumentException("Total arrays length exceed " + SAFE_MAX_ARRAY_LENGTH);
1181         }
1182     }
1183 
1184     /**
1185      * Copies the given array and adds the given element at the beginning of the new array.
1186      * <p>
1187      * The new array contains the same elements of the input array plus the given element in the first position. The
1188      * component type of the new array is the same as that of the input array.
1189      * </p>
1190      * <p>
1191      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1192      * element.
1193      * </p>
1194      * <pre>
1195      * ArrayUtils.addFirst(null, true)          = [true]
1196      * ArrayUtils.addFirst([true], false)       = [false, true]
1197      * ArrayUtils.addFirst([true, false], true) = [true, true, false]
1198      * </pre>
1199      *
1200      * @param array the array to "add" the element to, may be {@code null}.
1201      * @param element the object to add.
1202      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1203      *         the input array (unless null), in which case it will have the same type as the element.
1204      * @since 3.10
1205      */
1206     public static boolean[] addFirst(final boolean[] array, final boolean element) {
1207         return array == null ? add(array, element) : insert(0, array, element);
1208     }
1209 
1210     /**
1211      * Copies the given array and adds the given element at the beginning of the new array.
1212      * <p>
1213      * The new array contains the same elements of the input array plus the given element in the first position. The
1214      * component type of the new array is the same as that of the input array.
1215      * </p>
1216      * <p>
1217      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1218      * element.
1219      * </p>
1220      * <pre>
1221      * ArrayUtils.addFirst(null, 1)   = [1]
1222      * ArrayUtils.addFirst([1], 0)    = [0, 1]
1223      * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1224      * </pre>
1225      *
1226      * @param array the array to "add" the element to, may be {@code null}.
1227      * @param element the object to add.
1228      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1229      *         the input array (unless null), in which case it will have the same type as the element.
1230      * @since 3.10
1231      */
1232     public static byte[] addFirst(final byte[] array, final byte element) {
1233         return array == null ? add(array, element) : insert(0, array, element);
1234     }
1235 
1236     /**
1237      * Copies the given array and adds the given element at the beginning of the new array.
1238      * <p>
1239      * The new array contains the same elements of the input array plus the given element in the first position. The
1240      * component type of the new array is the same as that of the input array.
1241      * </p>
1242      * <p>
1243      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1244      * element.
1245      * </p>
1246      * <pre>
1247      * ArrayUtils.addFirst(null, '1')       = ['1']
1248      * ArrayUtils.addFirst(['1'], '0')      = ['0', '1']
1249      * ArrayUtils.addFirst(['1', '0'], '1') = ['1', '1', '0']
1250      * </pre>
1251      *
1252      * @param array the array to "add" the element to, may be {@code null}.
1253      * @param element the object to add.
1254      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1255      *         the input array (unless null), in which case it will have the same type as the element.
1256      * @since 3.10
1257      */
1258     public static char[] addFirst(final char[] array, final char element) {
1259         return array == null ? add(array, element) : insert(0, array, element);
1260     }
1261 
1262     /**
1263      * Copies the given array and adds the given element at the beginning of the new array.
1264      * <p>
1265      * The new array contains the same elements of the input array plus the given element in the first position. The
1266      * component type of the new array is the same as that of the input array.
1267      * </p>
1268      * <p>
1269      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1270      * element.
1271      * </p>
1272      * <pre>
1273      * ArrayUtils.addFirst(null, 1)   = [1]
1274      * ArrayUtils.addFirst([1], 0)    = [0, 1]
1275      * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1276      * </pre>
1277      *
1278      * @param array the array to "add" the element to, may be {@code null}.
1279      * @param element the object to add.
1280      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1281      *         the input array (unless null), in which case it will have the same type as the element.
1282      * @since 3.10
1283      */
1284     public static double[] addFirst(final double[] array, final double element) {
1285         return array == null ? add(array, element) : insert(0, array, element);
1286     }
1287 
1288     /**
1289      * Copies the given array and adds the given element at the beginning of the new array.
1290      * <p>
1291      * The new array contains the same elements of the input array plus the given element in the first position. The
1292      * component type of the new array is the same as that of the input array.
1293      * </p>
1294      * <p>
1295      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1296      * element.
1297      * </p>
1298      * <pre>
1299      * ArrayUtils.addFirst(null, 1)   = [1]
1300      * ArrayUtils.addFirst([1], 0)    = [0, 1]
1301      * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1302      * </pre>
1303      *
1304      * @param array the array to "add" the element to, may be {@code null}.
1305      * @param element the object to add.
1306      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1307      *         the input array (unless null), in which case it will have the same type as the element.
1308      * @since 3.10
1309      */
1310     public static float[] addFirst(final float[] array, final float element) {
1311         return array == null ? add(array, element) : insert(0, array, element);
1312     }
1313 
1314     /**
1315      * Copies the given array and adds the given element at the beginning of the new array.
1316      * <p>
1317      * The new array contains the same elements of the input array plus the given element in the first position. The
1318      * component type of the new array is the same as that of the input array.
1319      * </p>
1320      * <p>
1321      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1322      * element.
1323      * </p>
1324      * <pre>
1325      * ArrayUtils.addFirst(null, 1)   = [1]
1326      * ArrayUtils.addFirst([1], 0)    = [0, 1]
1327      * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1328      * </pre>
1329      *
1330      * @param array the array to "add" the element to, may be {@code null}.
1331      * @param element the object to add.
1332      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1333      *         the input array (unless null), in which case it will have the same type as the element.
1334      * @since 3.10
1335      */
1336     public static int[] addFirst(final int[] array, final int element) {
1337         return array == null ? add(array, element) : insert(0, array, element);
1338     }
1339 
1340     /**
1341      * Copies the given array and adds the given element at the beginning of the new array.
1342      * <p>
1343      * The new array contains the same elements of the input array plus the given element in the first position. The
1344      * component type of the new array is the same as that of the input array.
1345      * </p>
1346      * <p>
1347      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1348      * element.
1349      * </p>
1350      * <pre>
1351      * ArrayUtils.addFirst(null, 1)   = [1]
1352      * ArrayUtils.addFirst([1], 0)    = [0, 1]
1353      * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1354      * </pre>
1355      *
1356      * @param array the array to "add" the element to, may be {@code null}.
1357      * @param element the object to add.
1358      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1359      *         the input array (unless null), in which case it will have the same type as the element.
1360      * @since 3.10
1361      */
1362     public static long[] addFirst(final long[] array, final long element) {
1363         return array == null ? add(array, element) : insert(0, array, element);
1364     }
1365 
1366     /**
1367      * Copies the given array and adds the given element at the beginning of the new array.
1368      * <p>
1369      * The new array contains the same elements of the input array plus the given element in the first position. The
1370      * component type of the new array is the same as that of the input array.
1371      * </p>
1372      * <p>
1373      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1374      * element.
1375      * </p>
1376      * <pre>
1377      * ArrayUtils.addFirst(null, 1)   = [1]
1378      * ArrayUtils.addFirst([1], 0)    = [0, 1]
1379      * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1380      * </pre>
1381      *
1382      * @param array the array to "add" the element to, may be {@code null}.
1383      * @param element the object to add.
1384      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1385      *         the input array (unless null), in which case it will have the same type as the element.
1386      * @since 3.10
1387      */
1388     public static short[] addFirst(final short[] array, final short element) {
1389         return array == null ? add(array, element) : insert(0, array, element);
1390     }
1391 
1392     /**
1393      * Copies the given array and adds the given element at the beginning of the new array.
1394      * <p>
1395      * The new array contains the same elements of the input array plus the given element in the first position. The
1396      * component type of the new array is the same as that of the input array.
1397      * </p>
1398      * <p>
1399      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1400      * element, unless the element itself is null, in which case the return type is Object[]
1401      * </p>
1402      * <pre>
1403      * ArrayUtils.addFirst(null, null)      = Throws {@link IllegalArgumentException}
1404      * ArrayUtils.addFirst(null, "a")       = ["a"]
1405      * ArrayUtils.addFirst(["a"], null)     = [null, "a"]
1406      * ArrayUtils.addFirst(["a"], "b")      = ["b", "a"]
1407      * ArrayUtils.addFirst(["a", "b"], "c") = ["c", "a", "b"]
1408      * </pre>
1409      *
1410      * @param <T> the component type of the array.
1411      * @param array the array to "add" the element to, may be {@code null}.
1412      * @param element the object to add, may be {@code null}.
1413      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1414      *         the input array (unless null), in which case it will have the same type as the element. If both are null,
1415      *         an IllegalArgumentException is thrown.
1416      * @throws IllegalArgumentException if both arguments are null.
1417      * @since 3.10
1418      */
1419     public static <T> T[] addFirst(final T[] array, final T element) {
1420         return array == null ? add(array, element) : insert(0, array, element);
1421     }
1422 
1423     /**
1424      * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array.
1425      *
1426      * @param <T>       the type.
1427      * @param source    the source array.
1428      * @param sourcePos starting position in the source array.
1429      * @param destPos   starting position in the destination data.
1430      * @param length    the number of array elements to be copied.
1431      * @param allocator allocates the array to populate and return.
1432      * @return dest
1433      * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds.
1434      * @throws ArrayStoreException       if an element in the {@code src} array could not be stored into the {@code dest} array because of a type
1435      *                                   mismatch.
1436      * @throws NullPointerException      if either {@code src} or {@code dest} is {@code null}.
1437      * @since 3.15.0
1438      */
1439     public static <T> T arraycopy(final T source, final int sourcePos, final int destPos, final int length, final Function<Integer, T> allocator) {
1440         return arraycopy(source, sourcePos, allocator.apply(length), destPos, length);
1441     }
1442 
1443     /**
1444      * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array.
1445      *
1446      * @param <T>       the type.
1447      * @param source    the source array.
1448      * @param sourcePos starting position in the source array.
1449      * @param destPos   starting position in the destination data.
1450      * @param length    the number of array elements to be copied.
1451      * @param allocator allocates the array to populate and return.
1452      * @return dest
1453      * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds.
1454      * @throws ArrayStoreException       if an element in the {@code src} array could not be stored into the {@code dest} array because of a type
1455      *                                   mismatch.
1456      * @throws NullPointerException      if either {@code src} or {@code dest} is {@code null}.
1457      * @since 3.15.0
1458      */
1459     public static <T> T arraycopy(final T source, final int sourcePos, final int destPos, final int length, final Supplier<T> allocator) {
1460         return arraycopy(source, sourcePos, allocator.get(), destPos, length);
1461     }
1462 
1463     /**
1464      * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array.
1465      *
1466      * @param <T>       the type.
1467      * @param source    the source array.
1468      * @param sourcePos starting position in the source array.
1469      * @param dest      the destination array.
1470      * @param destPos   starting position in the destination data.
1471      * @param length    the number of array elements to be copied.
1472      * @return dest
1473      * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds.
1474      * @throws ArrayStoreException       if an element in the {@code src} array could not be stored into the {@code dest} array because of a type
1475      *                                   mismatch.
1476      * @throws NullPointerException      if either {@code src} or {@code dest} is {@code null}.
1477      * @since 3.15.0
1478      */
1479     public static <T> T arraycopy(final T source, final int sourcePos, final T dest, final int destPos, final int length) {
1480         System.arraycopy(source, sourcePos, dest, destPos, length);
1481         return dest;
1482     }
1483 
1484     /**
1485      * Clones an array or returns {@code null}.
1486      * <p>
1487      * This method returns {@code null} for a {@code null} input array.
1488      * </p>
1489      *
1490      * @param array the array to clone, may be {@code null}.
1491      * @return the cloned array, {@code null} if {@code null} input.
1492      */
1493     public static boolean[] clone(final boolean[] array) {
1494         return array != null ? array.clone() : null;
1495     }
1496 
1497     /**
1498      * Clones an array or returns {@code null}.
1499      * <p>
1500      * This method returns {@code null} for a {@code null} input array.
1501      * </p>
1502      *
1503      * @param array the array to clone, may be {@code null}.
1504      * @return the cloned array, {@code null} if {@code null} input.
1505      */
1506     public static byte[] clone(final byte[] array) {
1507         return array != null ? array.clone() : null;
1508     }
1509 
1510     /**
1511      * Clones an array or returns {@code null}.
1512      * <p>
1513      * This method returns {@code null} for a {@code null} input array.
1514      * </p>
1515      *
1516      * @param array the array to clone, may be {@code null}.
1517      * @return the cloned array, {@code null} if {@code null} input.
1518      */
1519     public static char[] clone(final char[] array) {
1520         return array != null ? array.clone() : null;
1521     }
1522 
1523     /**
1524      * Clones an array or returns {@code null}.
1525      * <p>
1526      * This method returns {@code null} for a {@code null} input array.
1527      * </p>
1528      *
1529      * @param array the array to clone, may be {@code null}.
1530      * @return the cloned array, {@code null} if {@code null} input.
1531      */
1532     public static double[] clone(final double[] array) {
1533         return array != null ? array.clone() : null;
1534     }
1535 
1536     /**
1537      * Clones an array or returns {@code null}.
1538      * <p>
1539      * This method returns {@code null} for a {@code null} input array.
1540      * </p>
1541      *
1542      * @param array the array to clone, may be {@code null}.
1543      * @return the cloned array, {@code null} if {@code null} input.
1544      */
1545     public static float[] clone(final float[] array) {
1546         return array != null ? array.clone() : null;
1547     }
1548 
1549     /**
1550      * Clones an array or returns {@code null}.
1551      * <p>
1552      * This method returns {@code null} for a {@code null} input array.
1553      * </p>
1554      *
1555      * @param array the array to clone, may be {@code null}.
1556      * @return the cloned array, {@code null} if {@code null} input.
1557      */
1558     public static int[] clone(final int[] array) {
1559         return array != null ? array.clone() : null;
1560     }
1561 
1562     /**
1563      * Clones an array or returns {@code null}.
1564      * <p>
1565      * This method returns {@code null} for a {@code null} input array.
1566      * </p>
1567      *
1568      * @param array the array to clone, may be {@code null}.
1569      * @return the cloned array, {@code null} if {@code null} input.
1570      */
1571     public static long[] clone(final long[] array) {
1572         return array != null ? array.clone() : null;
1573     }
1574 
1575     /**
1576      * Clones an array or returns {@code null}.
1577      * <p>
1578      * This method returns {@code null} for a {@code null} input array.
1579      * </p>
1580      *
1581      * @param array the array to clone, may be {@code null}.
1582      * @return the cloned array, {@code null} if {@code null} input.
1583      */
1584     public static short[] clone(final short[] array) {
1585         return array != null ? array.clone() : null;
1586     }
1587 
1588     /**
1589      * Shallow clones an array or returns {@code null}.
1590      * <p>
1591      * The objects in the array are not cloned, thus there is no special handling for multi-dimensional arrays.
1592      * </p>
1593      * <p>
1594      * This method returns {@code null} for a {@code null} input array.
1595      * </p>
1596      *
1597      * @param <T>   the component type of the array.
1598      * @param array the array to shallow clone, may be {@code null}.
1599      * @return the cloned array, {@code null} if {@code null} input.
1600      */
1601     public static <T> T[] clone(final T[] array) {
1602         return array != null ? array.clone() : null;
1603     }
1604 
1605     /**
1606      * Concatenates multiple boolean arrays into a single array.
1607      * <p>
1608      * This method combines all input arrays in the order they are provided,
1609      * creating a new array that contains all elements from the input arrays.
1610      * The resulting array length is the sum of lengths of all non-null input arrays.
1611      * </p>
1612      *
1613      * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1614      *               or be null itself (treated as empty varargs).
1615      * @return a new boolean array containing all elements from the input arrays
1616      *         in the order they appear, or an empty array if no elements are present.
1617      * @throws NullPointerException if the input array of arrays is null.
1618      * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1619      * @since 3.21.0
1620      */
1621     public static boolean[] concat(boolean[]... arrays) {
1622         int totalLength = 0;
1623         for (boolean[] array : arrays) {
1624             totalLength = addExact(totalLength, array);
1625         }
1626         final boolean[] result = new boolean[totalLength];
1627         int currentPos = 0;
1628         for (boolean[] array : arrays) {
1629             if (array != null && array.length > 0) {
1630                 System.arraycopy(array, 0, result, currentPos, array.length);
1631                 currentPos += array.length;
1632             }
1633         }
1634         return result;
1635     }
1636 
1637     /**
1638      * Concatenates multiple byte arrays into a single array.
1639      * <p>
1640      * This method combines all input arrays in the order they are provided,
1641      * creating a new array that contains all elements from the input arrays.
1642      * The resulting array length is the sum of lengths of all non-null input arrays.
1643      * </p>
1644      *
1645      * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1646      *               or be null itself (treated as empty varargs).
1647      * @return a new byte array containing all elements from the input arrays
1648      *         in the order they appear, or an empty array if no elements are present.
1649      * @throws NullPointerException if the input array of arrays is null.
1650      * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1651      * @since 3.21.0
1652      */
1653     public static byte[] concat(byte[]... arrays) {
1654         int totalLength = 0;
1655         for (byte[] array : arrays) {
1656             totalLength = addExact(totalLength, array);
1657         }
1658         final byte[] result = new byte[totalLength];
1659         int currentPos = 0;
1660         for (byte[] array : arrays) {
1661             if (array != null && array.length > 0) {
1662                 System.arraycopy(array, 0, result, currentPos, array.length);
1663                 currentPos += array.length;
1664             }
1665         }
1666         return result;
1667     }
1668 
1669     /**
1670      * Concatenates multiple char arrays into a single array.
1671      * <p>
1672      * This method combines all input arrays in the order they are provided,
1673      * creating a new array that contains all elements from the input arrays.
1674      * The resulting array length is the sum of lengths of all non-null input arrays.
1675      * </p>
1676      *
1677      * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1678      *               or be null itself (treated as empty varargs).
1679      * @return a new char array containing all elements from the input arrays
1680      *         in the order they appear, or an empty array if no elements are present.
1681      * @throws NullPointerException if the input array of arrays is null.
1682      * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1683      * @since 3.21.0
1684      */
1685     public static char[] concat(char[]... arrays) {
1686         int totalLength = 0;
1687         for (char[] array : arrays) {
1688             totalLength = addExact(totalLength, array);
1689         }
1690         final char[] result = new char[totalLength];
1691         int currentPos = 0;
1692         for (char[] array : arrays) {
1693             if (array != null && array.length > 0) {
1694                 System.arraycopy(array, 0, result, currentPos, array.length);
1695                 currentPos += array.length;
1696             }
1697         }
1698         return result;
1699     }
1700 
1701     /**
1702      * Concatenates multiple double arrays into a single array.
1703      * <p>
1704      * This method combines all input arrays in the order they are provided,
1705      * creating a new array that contains all elements from the input arrays.
1706      * The resulting array length is the sum of lengths of all non-null input arrays.
1707      * </p>
1708      *
1709      * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1710      *               or be null itself (treated as empty varargs).
1711      * @return a new double array containing all elements from the input arrays
1712      *         in the order they appear, or an empty array if no elements are present.
1713      * @throws NullPointerException if the input array of arrays is null.
1714      * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1715      * @since 3.21.0
1716      */
1717     public static double[] concat(double[]... arrays) {
1718         int totalLength = 0;
1719         for (double[] array : arrays) {
1720             totalLength = addExact(totalLength, array);
1721         }
1722         final double[] result = new double[totalLength];
1723         int currentPos = 0;
1724         for (double[] array : arrays) {
1725             if (array != null && array.length > 0) {
1726                 System.arraycopy(array, 0, result, currentPos, array.length);
1727                 currentPos += array.length;
1728             }
1729         }
1730         return result;
1731     }
1732 
1733     /**
1734      * Concatenates multiple float arrays into a single array.
1735      * <p>
1736      * This method combines all input arrays in the order they are provided,
1737      * creating a new array that contains all elements from the input arrays.
1738      * The resulting array length is the sum of lengths of all non-null input arrays.
1739      * </p>
1740      *
1741      * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1742      *               or be null itself (treated as empty varargs).
1743      * @return a new float array containing all elements from the input arrays
1744      *         in the order they appear, or an empty array if no elements are present.
1745      * @throws NullPointerException if the input array of arrays is null.
1746      * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1747      * @since 3.21.0
1748      */
1749     public static float[] concat(float[]... arrays) {
1750         int totalLength = 0;
1751         for (float[] array : arrays) {
1752             totalLength = addExact(totalLength, array);
1753         }
1754         final float[] result = new float[totalLength];
1755         int currentPos = 0;
1756         for (float[] array : arrays) {
1757             if (array != null && array.length > 0) {
1758                 System.arraycopy(array, 0, result, currentPos, array.length);
1759                 currentPos += array.length;
1760             }
1761         }
1762         return result;
1763     }
1764 
1765     /**
1766      * Concatenates multiple int arrays into a single array.
1767      * <p>
1768      * This method combines all input arrays in the order they are provided,
1769      * creating a new array that contains all elements from the input arrays.
1770      * The resulting array length is the sum of lengths of all non-null input arrays.
1771      * </p>
1772      *
1773      * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1774      *               or be null itself (treated as empty varargs).
1775      * @return a new int array containing all elements from the input arrays
1776      *         in the order they appear, or an empty array if no elements are present.
1777      * @throws NullPointerException if the input array of arrays is null.
1778      * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1779      * @since 3.21.0
1780      */
1781     public static int[] concat(int[]... arrays) {
1782         int totalLength = 0;
1783         for (int[] array : arrays) {
1784             totalLength = addExact(totalLength, array);
1785         }
1786         final int[] result = new int[totalLength];
1787         int currentPos = 0;
1788         for (int[] array : arrays) {
1789             if (array != null && array.length > 0) {
1790                 System.arraycopy(array, 0, result, currentPos, array.length);
1791                 currentPos += array.length;
1792             }
1793         }
1794         return result;
1795     }
1796 
1797     /**
1798      * Concatenates multiple long arrays into a single array.
1799      * <p>
1800      * This method combines all input arrays in the order they are provided,
1801      * creating a new array that contains all elements from the input arrays.
1802      * The resulting array length is the sum of lengths of all non-null input arrays.
1803      * </p>
1804      *
1805      * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1806      *               or be null itself (treated as empty varargs).
1807      * @return a new long array containing all elements from the input arrays
1808      *         in the order they appear, or an empty array if no elements are present.
1809      * @throws NullPointerException if the input array of arrays is null.
1810      * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1811      * @since 3.21.0
1812      */
1813     public static long[] concat(long[]... arrays) {
1814         int totalLength = 0;
1815         for (long[] array : arrays) {
1816             totalLength = addExact(totalLength, array);
1817         }
1818         final long[] result = new long[totalLength];
1819         int currentPos = 0;
1820         for (long[] array : arrays) {
1821             if (array != null && array.length > 0) {
1822                 System.arraycopy(array, 0, result, currentPos, array.length);
1823                 currentPos += array.length;
1824             }
1825         }
1826         return result;
1827     }
1828 
1829     /**
1830      * Concatenates multiple short arrays into a single array.
1831      * <p>
1832      * This method combines all input arrays in the order they are provided,
1833      * creating a new array that contains all elements from the input arrays.
1834      * The resulting array length is the sum of lengths of all non-null input arrays.
1835      * </p>
1836      *
1837      * @param arrays the arrays to concatenate. Can be empty, contain nulls,
1838      *               or be null itself (treated as empty varargs).
1839      * @return a new short array containing all elements from the input arrays
1840      *         in the order they appear, or an empty array if no elements are present.
1841      * @throws NullPointerException if the input array of arrays is null.
1842      * @throws IllegalArgumentException if total arrays length exceed {@link ArrayUtils#SAFE_MAX_ARRAY_LENGTH}.
1843      * @since 3.21.0
1844      */
1845     public static short[] concat(short[]... arrays) {
1846         int totalLength = 0;
1847         for (short[] array : arrays) {
1848             totalLength = addExact(totalLength, array);
1849         }
1850         final short[] result = new short[totalLength];
1851         int currentPos = 0;
1852         for (short[] array : arrays) {
1853             if (array != null && array.length > 0) {
1854                 System.arraycopy(array, 0, result, currentPos, array.length);
1855                 currentPos += array.length;
1856             }
1857         }
1858         return result;
1859     }
1860 
1861     /**
1862      * Checks if the value is in the given array.
1863      * <p>
1864      * The method returns {@code false} if a {@code null} array is passed in.
1865      * </p>
1866      *
1867      * @param array  the array to search.
1868      * @param valueToFind  the value to find.
1869      * @return {@code true} if the array contains the object.
1870      */
1871     public static boolean contains(final boolean[] array, final boolean valueToFind) {
1872         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1873     }
1874 
1875     /**
1876      * Checks if the value is in the given array.
1877      * <p>
1878      * The method returns {@code false} if a {@code null} array is passed in.
1879      * </p>
1880      * <p>
1881      * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1882      * {@link Arrays#sort(byte[])} and {@link Arrays#binarySearch(byte[], byte)}.
1883      * </p>
1884      *
1885      * @param array  the array to search.
1886      * @param valueToFind  the value to find.
1887      * @return {@code true} if the array contains the object.
1888      */
1889     public static boolean contains(final byte[] array, final byte valueToFind) {
1890         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1891     }
1892 
1893     /**
1894      * Checks if the value is in the given array.
1895      * <p>
1896      * The method returns {@code false} if a {@code null} array is passed in.
1897      * </p>
1898      * <p>
1899      * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1900      * {@link Arrays#sort(char[])} and {@link Arrays#binarySearch(char[], char)}.
1901      * </p>
1902      *
1903      * @param array  the array to search.
1904      * @param valueToFind  the value to find.
1905      * @return {@code true} if the array contains the object.
1906      * @since 2.1
1907      */
1908     public static boolean contains(final char[] array, final char valueToFind) {
1909         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1910     }
1911 
1912     /**
1913      * Checks if the value is in the given array.
1914      * <p>
1915      * The method returns {@code false} if a {@code null} array is passed in.
1916      * </p>
1917      * <p>
1918      * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1919      * {@link Arrays#sort(double[])} and {@link Arrays#binarySearch(double[], double)}.
1920      * </p>
1921      *
1922      * @param array  the array to search.
1923      * @param valueToFind  the value to find.
1924      * @return {@code true} if the array contains the object.
1925      */
1926     public static boolean contains(final double[] array, final double valueToFind) {
1927         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1928     }
1929 
1930     /**
1931      * Checks if a value falling within the given tolerance is in the
1932      * given array.  If the array contains a value within the inclusive range
1933      * defined by (value - tolerance) to (value + tolerance).
1934      * <p>
1935      * The method returns {@code false} if a {@code null} array
1936      * is passed in.
1937      * </p>
1938      * <p>
1939      * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1940      * {@link Arrays#sort(double[])} and {@link Arrays#binarySearch(double[], double)}.
1941      * </p>
1942      *
1943      * @param array  the array to search.
1944      * @param valueToFind  the value to find.
1945      * @param tolerance  the array contains the tolerance of the search.
1946      * @return true if value falling within tolerance is in array.
1947      */
1948     public static boolean contains(final double[] array, final double valueToFind, final double tolerance) {
1949         return indexOf(array, valueToFind, 0, tolerance) != INDEX_NOT_FOUND;
1950     }
1951 
1952     /**
1953      * Checks if the value is in the given array.
1954      * <p>
1955      * The method returns {@code false} if a {@code null} array is passed in.
1956      * </p>
1957      * <p>
1958      * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1959      * {@link Arrays#sort(float[])} and {@link Arrays#binarySearch(float[], float)}.
1960      * </p>
1961      *
1962      * @param array  the array to search.
1963      * @param valueToFind  the value to find.
1964      * @return {@code true} if the array contains the object.
1965      */
1966     public static boolean contains(final float[] array, final float valueToFind) {
1967         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1968     }
1969 
1970     /**
1971      * Checks if the value is in the given array.
1972      * <p>
1973      * The method returns {@code false} if a {@code null} array is passed in.
1974      * </p>
1975      * <p>
1976      * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1977      * {@link Arrays#sort(int[])} and {@link Arrays#binarySearch(int[], int)}.
1978      * </p>
1979      *
1980      * @param array  the array to search.
1981      * @param valueToFind  the value to find.
1982      * @return {@code true} if the array contains the object.
1983      */
1984     public static boolean contains(final int[] array, final int valueToFind) {
1985         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1986     }
1987 
1988     /**
1989      * Checks if the value is in the given array.
1990      * <p>
1991      * The method returns {@code false} if a {@code null} array is passed in.
1992      * </p>
1993      * <p>
1994      * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
1995      * {@link Arrays#sort(long[])} and {@link Arrays#binarySearch(long[], long)}.
1996      * </p>
1997      *
1998      * @param array  the array to search.
1999      * @param valueToFind  the value to find.
2000      * @return {@code true} if the array contains the object.
2001      */
2002     public static boolean contains(final long[] array, final long valueToFind) {
2003         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2004     }
2005 
2006     /**
2007      * Checks if the object is in the given array.
2008      * <p>
2009      * The method returns {@code false} if a {@code null} array is passed in.
2010      * </p>
2011      * <p>
2012      * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
2013      * {@link Arrays#sort(Object[], Comparator)} and {@link Arrays#binarySearch(Object[], Object)}.
2014      * </p>
2015      *
2016      * @param array  the array to search, may be {@code null}.
2017      * @param objectToFind  the object to find, may be {@code null}.
2018      * @return {@code true} if the array contains the object.
2019      */
2020     public static boolean contains(final Object[] array, final Object objectToFind) {
2021         return indexOf(array, objectToFind) != INDEX_NOT_FOUND;
2022     }
2023 
2024     /**
2025      * Checks if the value is in the given array.
2026      * <p>
2027      * The method returns {@code false} if a {@code null} array is passed in.
2028      * </p>
2029      * <p>
2030      * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
2031      * {@link Arrays#sort(short[])} and {@link Arrays#binarySearch(short[], short)}.
2032      * </p>
2033      *
2034      * @param array  the array to search.
2035      * @param valueToFind  the value to find.
2036      * @return {@code true} if the array contains the object.
2037      */
2038     public static boolean contains(final short[] array, final short valueToFind) {
2039         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2040     }
2041 
2042     /**
2043      * Checks if any of the ints are in the given array.
2044      * <p>
2045      * The method returns {@code false} if a {@code null} array is passed in.
2046      * </p>
2047      * <p>
2048      * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
2049      * {@link Arrays#sort(int[])} and {@link Arrays#binarySearch(int[], int)}.
2050      * </p>
2051      *
2052      * @param array         the array to search.
2053      * @param objectsToFind any of the ints to find.
2054      * @return {@code true} if the array contains any of the ints.
2055      * @since 3.18.0
2056      */
2057     public static boolean containsAny(final int[] array, final int... objectsToFind) {
2058         return IntStreams.of(objectsToFind).anyMatch(e -> contains(array, e));
2059     }
2060 
2061     /**
2062      * Checks if any of the objects are in the given array.
2063      * <p>
2064      * The method returns {@code false} if a {@code null} array is passed in.
2065      * </p>
2066      * <p>
2067      * If the {@code array} elements you are searching implement {@link Comparator}, consider whether it is worth using
2068      * {@link Arrays#sort(Object[], Comparator)} and {@link Arrays#binarySearch(Object[], Object)}.
2069      * </p>
2070      *
2071      * @param array         the array to search, may be {@code null}.
2072      * @param objectsToFind any of the objects to find, may be {@code null}.
2073      * @return {@code true} if the array contains any of the objects.
2074      * @since 3.13.0
2075      */
2076     public static boolean containsAny(final Object[] array, final Object... objectsToFind) {
2077         return Streams.of(objectsToFind).anyMatch(e -> contains(array, e));
2078     }
2079 
2080     /**
2081      * Returns a copy of the given array of size 1 greater than the argument.
2082      * The last value of the array is left to the default value.
2083      *
2084      * @param array The array to copy, must not be {@code null}.
2085      * @param newArrayComponentType If {@code array} is {@code null}, create a
2086      * size 1 array of this type.
2087      * @return A new copy of the array of size 1 greater than the input.
2088      */
2089     private static Object copyArrayGrow1(final Object array, final Class<?> newArrayComponentType) {
2090         if (array != null) {
2091             final int arrayLength = Array.getLength(array);
2092             final Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
2093             System.arraycopy(array, 0, newArray, 0, arrayLength);
2094             return newArray;
2095         }
2096         return Array.newInstance(newArrayComponentType, 1);
2097     }
2098 
2099     /**
2100      * Gets the nTh element of an array or null if the index is out of bounds or the array is null.
2101      *
2102      * @param <T> The type of array elements.
2103      * @param array The array to index.
2104      * @param index The index.
2105      * @return the nTh element of an array or null if the index is out of bounds or the array is null.
2106      * @since 3.11
2107      */
2108     public static <T> T get(final T[] array, final int index) {
2109         return get(array, index, null);
2110     }
2111 
2112     /**
2113      * Gets the nTh element of an array or a default value if the index is out of bounds.
2114      *
2115      * @param <T> The type of array elements.
2116      * @param array The array to index.
2117      * @param index The index.
2118      * @param defaultValue The return value of the given index is out of bounds.
2119      * @return the nTh element of an array or a default value if the index is out of bounds.
2120      * @since 3.11
2121      */
2122     public static <T> T get(final T[] array, final int index, final T defaultValue) {
2123         return isArrayIndexValid(array, index) ? array[index] : defaultValue;
2124     }
2125 
2126     /**
2127      * Gets an array's component type.
2128      *
2129      * @param <T> The array type.
2130      * @param array The array.
2131      * @return The component type.
2132      * @since 3.13.0
2133      */
2134     public static <T> Class<T> getComponentType(final T[] array) {
2135         return ClassUtils.getComponentType(ObjectUtils.getClass(array));
2136     }
2137 
2138     /**
2139      * Gets the number of dimensions of an array.
2140      * <p>
2141      * The <a href="https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.3">JVM specification</a> limits the number of dimensions to 255.
2142      * </p>
2143      *
2144      * @param array the array, may be {@code null}.
2145      * @return The number of dimensions, 0 if the input is null or not an array. The JVM specification limits the number of dimensions to 255.
2146      * @since 3.21.0
2147      * @see <a href="https://docs.oracle.com/javase/specs/jvms/se25/html/jvms-4.html#jvms-4.3">JVM specification Field Descriptors</a>
2148      */
2149     public static int getDimensions(final Object array) {
2150         int dimensions = 0;
2151         if (array != null) {
2152             Class<?> arrayClass = array.getClass();
2153             while (arrayClass.isArray()) {
2154                 dimensions++;
2155                 arrayClass = arrayClass.getComponentType();
2156             }
2157         }
2158         return dimensions;
2159     }
2160 
2161     /**
2162      * Gets the length of the specified array.
2163      * This method handles {@link Object} arrays and primitive arrays.
2164      * <p>
2165      * If the input array is {@code null}, {@code 0} is returned.
2166      * </p>
2167      * <pre>
2168      * ArrayUtils.getLength(null)            = 0
2169      * ArrayUtils.getLength([])              = 0
2170      * ArrayUtils.getLength([null])          = 1
2171      * ArrayUtils.getLength([true, false])   = 2
2172      * ArrayUtils.getLength([1, 2, 3])       = 3
2173      * ArrayUtils.getLength(["a", "b", "c"]) = 3
2174      * </pre>
2175      *
2176      * @param array  the array to retrieve the length from, may be {@code null}.
2177      * @return The length of the array, or {@code 0} if the array is {@code null}.
2178      * @throws IllegalArgumentException if the object argument is not an array.
2179      * @since 2.1
2180      */
2181     public static int getLength(final Object array) {
2182         return array != null ? Array.getLength(array) : 0;
2183     }
2184 
2185     /**
2186      * Gets a hash code for an array handling multidimensional arrays correctly.
2187      * <p>
2188      * Multi-dimensional primitive arrays are also handled correctly by this method.
2189      * </p>
2190      *
2191      * @param array  the array to get a hash code for, {@code null} returns zero.
2192      * @return a hash code for the array.
2193      */
2194     public static int hashCode(final Object array) {
2195         return new HashCodeBuilder().append(array).toHashCode();
2196     }
2197 
2198     static <K> void increment(final Map<K, MutableInt> occurrences, final K boxed) {
2199         occurrences.computeIfAbsent(boxed, k -> new MutableInt()).increment();
2200     }
2201 
2202     /**
2203      * Finds the indices of the given value in the array.
2204      * <p>
2205      * This method returns an empty BitSet for a {@code null} input array.
2206      * </p>
2207      *
2208      * @param array  the array to search for the object, may be {@code null}.
2209      * @param valueToFind  the value to find.
2210      * @return a BitSet of all the indices of the value within the array,
2211      *  an empty BitSet if not found or {@code null} array input.
2212      * @since 3.10
2213      */
2214     public static BitSet indexesOf(final boolean[] array, final boolean valueToFind) {
2215         return indexesOf(array, valueToFind, 0);
2216     }
2217 
2218     /**
2219      * Finds the indices of the given value in the array starting at the given index.
2220      * <p>
2221      * This method returns an empty BitSet for a {@code null} input array.
2222      * </p>
2223      * <p>
2224      * A negative startIndex is treated as zero. A startIndex larger than the array length will return an empty BitSet ({@code -1}).
2225      * </p>
2226      *
2227      * @param array       the array to search for the object, may be {@code null}.
2228      * @param valueToFind the value to find.
2229      * @param startIndex  the index to start searching.
2230      * @return a BitSet of all the indices of the value within the array, an empty BitSet if not found or {@code null} array input.
2231      * @since 3.10
2232      */
2233     public static BitSet indexesOf(final boolean[] array, final boolean valueToFind, int startIndex) {
2234         final BitSet bitSet = new BitSet();
2235         if (array != null) {
2236             while (startIndex < array.length) {
2237                 startIndex = indexOf(array, valueToFind, startIndex);
2238                 if (startIndex == INDEX_NOT_FOUND) {
2239                     break;
2240                 }
2241                 bitSet.set(startIndex);
2242                 ++startIndex;
2243             }
2244         }
2245         return bitSet;
2246     }
2247 
2248     /**
2249      * Finds the indices of the given value in the array.
2250      *
2251      * <p>
2252      * This method returns an empty BitSet for a {@code null} input array.
2253      * </p>
2254      *
2255      * @param array       the array to search for the object, may be {@code null}.
2256      * @param valueToFind the value to find.
2257      * @return a BitSet of all the indices of the value within the array, an empty BitSet if not found or {@code null} array input.
2258      * @since 3.10
2259      */
2260     public static BitSet indexesOf(final byte[] array, final byte valueToFind) {
2261         return indexesOf(array, valueToFind, 0);
2262     }
2263 
2264     /**
2265      * Finds the indices of the given value in the array starting at the given index.
2266      *
2267      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2268      *
2269      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2270      * length will return an empty BitSet.</p>
2271      *
2272      * @param array  the array to search for the object, may be {@code null}.
2273      * @param valueToFind  the value to find.
2274      * @param startIndex  the index to start searching.
2275      * @return a BitSet of all the indices of the value within the array,
2276      *  an empty BitSet if not found or {@code null} array input.
2277      * @since 3.10
2278      */
2279     public static BitSet indexesOf(final byte[] array, final byte valueToFind, int startIndex) {
2280         final BitSet bitSet = new BitSet();
2281         if (array != null) {
2282             while (startIndex < array.length) {
2283                 startIndex = indexOf(array, valueToFind, startIndex);
2284                 if (startIndex == INDEX_NOT_FOUND) {
2285                     break;
2286                 }
2287                 bitSet.set(startIndex);
2288                 ++startIndex;
2289             }
2290         }
2291         return bitSet;
2292     }
2293 
2294     /**
2295      * Finds the indices of the given value in the array.
2296      *
2297      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2298      *
2299      * @param array  the array to search for the object, may be {@code null}.
2300      * @param valueToFind  the value to find.
2301      * @return a BitSet of all the indices of the value within the array,
2302      *  an empty BitSet if not found or {@code null} array input.
2303      * @since 3.10
2304      */
2305     public static BitSet indexesOf(final char[] array, final char valueToFind) {
2306         return indexesOf(array, valueToFind, 0);
2307     }
2308 
2309     /**
2310      * Finds the indices of the given value in the array starting at the given index.
2311      *
2312      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2313      *
2314      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2315      * length will return an empty BitSet.</p>
2316      *
2317      * @param array  the array to search for the object, may be {@code null}.
2318      * @param valueToFind  the value to find.
2319      * @param startIndex  the index to start searching.
2320      * @return a BitSet of all the indices of the value within the array,
2321      *  an empty BitSet if not found or {@code null} array input.
2322      * @since 3.10
2323      */
2324     public static BitSet indexesOf(final char[] array, final char valueToFind, int startIndex) {
2325         final BitSet bitSet = new BitSet();
2326         if (array != null) {
2327             while (startIndex < array.length) {
2328                 startIndex = indexOf(array, valueToFind, startIndex);
2329                 if (startIndex == INDEX_NOT_FOUND) {
2330                     break;
2331                 }
2332                 bitSet.set(startIndex);
2333                 ++startIndex;
2334             }
2335         }
2336         return bitSet;
2337     }
2338 
2339     /**
2340      * Finds the indices of the given value in the array.
2341      *
2342      * <p>This method returns empty BitSet for a {@code null} input array.</p>
2343      *
2344      * @param array  the array to search for the object, may be {@code null}.
2345      * @param valueToFind  the value to find.
2346      * @return a BitSet of all the indices of the value within the array,
2347      *  an empty BitSet if not found or {@code null} array input.
2348      * @since 3.10
2349      */
2350     public static BitSet indexesOf(final double[] array, final double valueToFind) {
2351         return indexesOf(array, valueToFind, 0);
2352     }
2353 
2354     /**
2355      * Finds the indices of the given value within a given tolerance in the array.
2356      *
2357      * <p>
2358      * This method will return all the indices of the value which fall between the region
2359      * defined by valueToFind - tolerance and valueToFind + tolerance, each time between the nearest integers.
2360      * </p>
2361      *
2362      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2363      *
2364      * @param array  the array to search for the object, may be {@code null}.
2365      * @param valueToFind  the value to find.
2366      * @param tolerance tolerance of the search.
2367      * @return a BitSet of all the indices of the value within the array,
2368      *  an empty BitSet if not found or {@code null} array input.
2369      * @since 3.10
2370      */
2371     public static BitSet indexesOf(final double[] array, final double valueToFind, final double tolerance) {
2372         return indexesOf(array, valueToFind, 0, tolerance);
2373     }
2374 
2375     /**
2376      * Finds the indices of the given value in the array starting at the given index.
2377      *
2378      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2379      *
2380      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2381      * length will return an empty BitSet.</p>
2382      *
2383      * @param array  the array to search for the object, may be {@code null}.
2384      * @param valueToFind  the value to find.
2385      * @param startIndex  the index to start searching.
2386      * @return a BitSet of the indices of the value within the array,
2387      *  an empty BitSet if not found or {@code null} array input.
2388      * @since 3.10
2389      */
2390     public static BitSet indexesOf(final double[] array, final double valueToFind, int startIndex) {
2391         final BitSet bitSet = new BitSet();
2392         if (array != null) {
2393             while (startIndex < array.length) {
2394                 startIndex = indexOf(array, valueToFind, startIndex);
2395                 if (startIndex == INDEX_NOT_FOUND) {
2396                     break;
2397                 }
2398                 bitSet.set(startIndex);
2399                 ++startIndex;
2400             }
2401         }
2402         return bitSet;
2403     }
2404 
2405     /**
2406      * Finds the indices of the given value in the array starting at the given index.
2407      *
2408      * <p>
2409      * This method will return the indices of the values which fall between the region
2410      * defined by valueToFind - tolerance and valueToFind + tolerance, between the nearest integers.
2411      * </p>
2412      *
2413      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2414      *
2415      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2416      * length will return an empty BitSet.</p>
2417      *
2418      * @param array  the array to search for the object, may be {@code null}.
2419      * @param valueToFind  the value to find.
2420      * @param startIndex  the index to start searching.
2421      * @param tolerance tolerance of the search.
2422      * @return a BitSet of the indices of the value within the array,
2423      *  an empty BitSet if not found or {@code null} array input.
2424      * @since 3.10
2425      */
2426     public static BitSet indexesOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
2427         final BitSet bitSet = new BitSet();
2428         if (array != null) {
2429             while (startIndex < array.length) {
2430                 startIndex = indexOf(array, valueToFind, startIndex, tolerance);
2431                 if (startIndex == INDEX_NOT_FOUND) {
2432                     break;
2433                 }
2434                 bitSet.set(startIndex);
2435                 ++startIndex;
2436             }
2437         }
2438         return bitSet;
2439     }
2440 
2441     /**
2442      * Finds the indices of the given value in the array.
2443      *
2444      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2445      *
2446      * @param array  the array to search for the object, may be {@code null}.
2447      * @param valueToFind  the value to find.
2448      * @return a BitSet of all the indices of the value within the array,
2449      *  an empty BitSet if not found or {@code null} array input.
2450      * @since 3.10
2451      */
2452     public static BitSet indexesOf(final float[] array, final float valueToFind) {
2453         return indexesOf(array, valueToFind, 0);
2454     }
2455 
2456     /**
2457      * Finds the indices of the given value in the array starting at the given index.
2458      *
2459      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2460      *
2461      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2462      * length will return empty BitSet.</p>
2463      *
2464      * @param array  the array to search for the object, may be {@code null}.
2465      * @param valueToFind  the value to find.
2466      * @param startIndex  the index to start searching.
2467      * @return a BitSet of all the indices of the value within the array,
2468      *  an empty BitSet if not found or {@code null} array input.
2469      * @since 3.10
2470      */
2471     public static BitSet indexesOf(final float[] array, final float valueToFind, int startIndex) {
2472         final BitSet bitSet = new BitSet();
2473         if (array != null) {
2474             while (startIndex < array.length) {
2475                 startIndex = indexOf(array, valueToFind, startIndex);
2476                 if (startIndex == INDEX_NOT_FOUND) {
2477                     break;
2478                 }
2479                 bitSet.set(startIndex);
2480                 ++startIndex;
2481             }
2482         }
2483         return bitSet;
2484     }
2485 
2486     /**
2487      * Finds the indices of the given value in the array.
2488      *
2489      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2490      *
2491      * @param array  the array to search for the object, may be {@code null}.
2492      * @param valueToFind  the value to find.
2493      * @return a BitSet of all the indices of the value within the array,
2494      *  an empty BitSet if not found or {@code null} array input.
2495      * @since 3.10
2496      */
2497     public static BitSet indexesOf(final int[] array, final int valueToFind) {
2498         return indexesOf(array, valueToFind, 0);
2499     }
2500 
2501     /**
2502      * Finds the indices of the given value in the array starting at the given index.
2503      *
2504      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2505      *
2506      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2507      * length will return an empty BitSet.</p>
2508      *
2509      * @param array  the array to search for the object, may be {@code null}.
2510      * @param valueToFind  the value to find.
2511      * @param startIndex  the index to start searching.
2512      * @return a BitSet of all the indices of the value within the array,
2513      *  an empty BitSet if not found or {@code null} array input.
2514      * @since 3.10
2515      */
2516     public static BitSet indexesOf(final int[] array, final int valueToFind, int startIndex) {
2517         final BitSet bitSet = new BitSet();
2518         if (array != null) {
2519             while (startIndex < array.length) {
2520                 startIndex = indexOf(array, valueToFind, startIndex);
2521                 if (startIndex == INDEX_NOT_FOUND) {
2522                     break;
2523                 }
2524                 bitSet.set(startIndex);
2525                 ++startIndex;
2526             }
2527         }
2528         return bitSet;
2529     }
2530 
2531     /**
2532      * Finds the indices of the given value in the array.
2533      *
2534      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2535      *
2536      * @param array  the array to search for the object, may be {@code null}.
2537      * @param valueToFind  the value to find.
2538      * @return a BitSet of all the indices of the value within the array,
2539      *  an empty BitSet if not found or {@code null} array input.
2540      * @since 3.10
2541      */
2542     public static BitSet indexesOf(final long[] array, final long valueToFind) {
2543         return indexesOf(array, valueToFind, 0);
2544     }
2545 
2546     /**
2547      * Finds the indices of the given value in the array starting at the given index.
2548      *
2549      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2550      *
2551      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2552      * length will return an empty BitSet.</p>
2553      *
2554      * @param array  the array to search for the object, may be {@code null}.
2555      * @param valueToFind  the value to find.
2556      * @param startIndex  the index to start searching.
2557      * @return a BitSet of all the indices of the value within the array,
2558      *  an empty BitSet if not found or {@code null} array input.
2559      * @since 3.10
2560      */
2561     public static BitSet indexesOf(final long[] array, final long valueToFind, int startIndex) {
2562         final BitSet bitSet = new BitSet();
2563         if (array != null) {
2564             while (startIndex < array.length) {
2565                 startIndex = indexOf(array, valueToFind, startIndex);
2566                 if (startIndex == INDEX_NOT_FOUND) {
2567                     break;
2568                 }
2569                 bitSet.set(startIndex);
2570                 ++startIndex;
2571             }
2572         }
2573         return bitSet;
2574     }
2575 
2576     /**
2577      * Finds the indices of the given object in the array.
2578      *
2579      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2580      *
2581      * @param array  the array to search for the object, may be {@code null}.
2582      * @param objectToFind  the object to find, may be {@code null}.
2583      * @return a BitSet of all the indices of the object within the array,
2584      *  an empty BitSet if not found or {@code null} array input.
2585      * @since 3.10
2586      */
2587     public static BitSet indexesOf(final Object[] array, final Object objectToFind) {
2588         return indexesOf(array, objectToFind, 0);
2589     }
2590 
2591     /**
2592      * Finds the indices of the given object in the array starting at the given index.
2593      *
2594      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2595      *
2596      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2597      * length will return an empty BitSet.</p>
2598      *
2599      * @param array  the array to search for the object, may be {@code null}.
2600      * @param objectToFind  the object to find, may be {@code null}.
2601      * @param startIndex  the index to start searching.
2602      * @return a BitSet of all the indices of the object within the array starting at the index,
2603      *  an empty BitSet if not found or {@code null} array input.
2604      * @since 3.10
2605      */
2606     public static BitSet indexesOf(final Object[] array, final Object objectToFind, int startIndex) {
2607         final BitSet bitSet = new BitSet();
2608         if (array != null) {
2609             while (startIndex < array.length) {
2610                 startIndex = indexOf(array, objectToFind, startIndex);
2611                 if (startIndex == INDEX_NOT_FOUND) {
2612                     break;
2613                 }
2614                 bitSet.set(startIndex);
2615                 ++startIndex;
2616             }
2617         }
2618         return bitSet;
2619     }
2620 
2621     /**
2622      * Finds the indices of the given value in the array.
2623      *
2624      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2625      *
2626      * @param array  the array to search for the object, may be {@code null}.
2627      * @param valueToFind  the value to find.
2628      * @return a BitSet of all the indices of the value within the array,
2629      *  an empty BitSet if not found or {@code null} array input.
2630      * @since 3.10
2631      */
2632     public static BitSet indexesOf(final short[] array, final short valueToFind) {
2633         return indexesOf(array, valueToFind, 0);
2634     }
2635 
2636     /**
2637      * Finds the indices of the given value in the array starting at the given index.
2638      *
2639      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2640      *
2641      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2642      * length will return an empty BitSet.</p>
2643      *
2644      * @param array  the array to search for the object, may be {@code null}.
2645      * @param valueToFind  the value to find.
2646      * @param startIndex  the index to start searching.
2647      * @return a BitSet of all the indices of the value within the array,
2648      *  an empty BitSet if not found or {@code null} array input.
2649      * @since 3.10
2650      */
2651     public static BitSet indexesOf(final short[] array, final short valueToFind, int startIndex) {
2652         final BitSet bitSet = new BitSet();
2653         if (array != null) {
2654             while (startIndex < array.length) {
2655                 startIndex = indexOf(array, valueToFind, startIndex);
2656                 if (startIndex == INDEX_NOT_FOUND) {
2657                     break;
2658                 }
2659                 bitSet.set(startIndex);
2660                 ++startIndex;
2661             }
2662         }
2663         return bitSet;
2664     }
2665 
2666     /**
2667      * Finds the index of the given value in the array.
2668      * <p>
2669      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2670      * </p>
2671      *
2672      * @param array       the array to search for the object, may be {@code null}.
2673      * @param valueToFind the value to find.
2674      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2675      */
2676     public static int indexOf(final boolean[] array, final boolean valueToFind) {
2677         return indexOf(array, valueToFind, 0);
2678     }
2679 
2680     /**
2681      * Finds the index of the given value in the array starting at the given index.
2682      * <p>
2683      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2684      * </p>
2685      * <p>
2686      * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2687      * </p>
2688      *
2689      * @param array       the array to search for the object, may be {@code null}.
2690      * @param valueToFind the value to find.
2691      * @param startIndex  the index to start searching.
2692      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2693      */
2694     public static int indexOf(final boolean[] array, final boolean valueToFind, final int startIndex) {
2695         if (isEmpty(array)) {
2696             return INDEX_NOT_FOUND;
2697         }
2698         for (int i = max0(startIndex); i < array.length; i++) {
2699             if (valueToFind == array[i]) {
2700                 return i;
2701             }
2702         }
2703         return INDEX_NOT_FOUND;
2704     }
2705 
2706     /**
2707      * Finds the index of the given value in the array.
2708      * <p>
2709      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2710      * </p>
2711      *
2712      * @param array       the array to search for the object, may be {@code null}.
2713      * @param valueToFind the value to find.
2714      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2715      */
2716     public static int indexOf(final byte[] array, final byte valueToFind) {
2717         return indexOf(array, valueToFind, 0);
2718     }
2719 
2720     /**
2721      * Finds the index of the given value in the array starting at the given index.
2722      * <p>
2723      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2724      * </p>
2725      * <p>
2726      * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2727      * </p>
2728      *
2729      * @param array       the array to search for the object, may be {@code null}.
2730      * @param valueToFind the value to find.
2731      * @param startIndex  the index to start searching.
2732      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2733      */
2734     public static int indexOf(final byte[] array, final byte valueToFind, final int startIndex) {
2735         if (isEmpty(array)) {
2736             return INDEX_NOT_FOUND;
2737         }
2738         for (int i = max0(startIndex); i < array.length; i++) {
2739             if (valueToFind == array[i]) {
2740                 return i;
2741             }
2742         }
2743         return INDEX_NOT_FOUND;
2744     }
2745 
2746     /**
2747      * Finds the index of the given value in the array.
2748      * <p>
2749      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2750      * </p>
2751      *
2752      * @param array       the array to search for the object, may be {@code null}.
2753      * @param valueToFind the value to find.
2754      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2755      * @since 2.1
2756      */
2757     public static int indexOf(final char[] array, final char valueToFind) {
2758         return indexOf(array, valueToFind, 0);
2759     }
2760 
2761     /**
2762      * Finds the index of the given value in the array starting at the given index.
2763      * <p>
2764      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2765      * </p>
2766      * <p>
2767      * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2768      * </p>
2769      *
2770      * @param array       the array to search for the object, may be {@code null}.
2771      * @param valueToFind the value to find.
2772      * @param startIndex  the index to start searching.
2773      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2774      * @since 2.1
2775      */
2776     public static int indexOf(final char[] array, final char valueToFind, final int startIndex) {
2777         if (isEmpty(array)) {
2778             return INDEX_NOT_FOUND;
2779         }
2780         for (int i = max0(startIndex); i < array.length; i++) {
2781             if (valueToFind == array[i]) {
2782                 return i;
2783             }
2784         }
2785         return INDEX_NOT_FOUND;
2786     }
2787 
2788     /**
2789      * Finds the index of the given value in the array.
2790      * <p>
2791      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2792      * </p>
2793      *
2794      * @param array       the array to search for the object, may be {@code null}.
2795      * @param valueToFind the value to find.
2796      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2797      */
2798     public static int indexOf(final double[] array, final double valueToFind) {
2799         return indexOf(array, valueToFind, 0);
2800     }
2801 
2802     /**
2803      * Finds the index of the given value within a given tolerance in the array. This method will return the index of the first value which falls between the
2804      * region defined by valueToFind - tolerance and valueToFind + tolerance.
2805      * <p>
2806      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2807      * </p>
2808      *
2809      * @param array       the array to search for the object, may be {@code null}.
2810      * @param valueToFind the value to find.
2811      * @param tolerance   tolerance of the search.
2812      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2813      */
2814     public static int indexOf(final double[] array, final double valueToFind, final double tolerance) {
2815         return indexOf(array, valueToFind, 0, tolerance);
2816     }
2817 
2818     /**
2819      * Finds the index of the given value in the array starting at the given index.
2820      * <p>
2821      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2822      * </p>
2823      * <p>
2824      * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2825      * </p>
2826      *
2827      * @param array       the array to search for the object, may be {@code null}.
2828      * @param valueToFind the value to find.
2829      * @param startIndex  the index to start searching.
2830      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2831      */
2832     public static int indexOf(final double[] array, final double valueToFind, final int startIndex) {
2833         if (Double.isNaN(valueToFind)) {
2834             return indexOfNaN(array, startIndex);
2835         }
2836         if (isEmpty(array)) {
2837             return INDEX_NOT_FOUND;
2838         }
2839         for (int i = max0(startIndex); i < array.length; i++) {
2840             if (valueToFind == array[i]) {
2841                 return i;
2842             }
2843         }
2844         return INDEX_NOT_FOUND;
2845     }
2846 
2847     /**
2848      * Finds the index of the given value in the array starting at the given index. This method will return the index of the first value which falls between the
2849      * region defined by valueToFind - tolerance and valueToFind + tolerance.
2850      * <p>
2851      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2852      * </p>
2853      * <p>
2854      * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2855      * </p>
2856      *
2857      * @param array       the array to search for the object, may be {@code null}.
2858      * @param valueToFind the value to find.
2859      * @param startIndex  the index to start searching.
2860      * @param tolerance   tolerance of the search.
2861      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2862      */
2863     public static int indexOf(final double[] array, final double valueToFind, final int startIndex, final double tolerance) {
2864         if (Double.isNaN(valueToFind)) {
2865             return indexOfNaN(array, startIndex);
2866         }
2867         if (isEmpty(array)) {
2868             return INDEX_NOT_FOUND;
2869         }
2870         final double min = valueToFind - tolerance;
2871         final double max = valueToFind + tolerance;
2872         for (int i = max0(startIndex); i < array.length; i++) {
2873             if (array[i] >= min && array[i] <= max) {
2874                 return i;
2875             }
2876         }
2877         return INDEX_NOT_FOUND;
2878     }
2879 
2880     /**
2881      * Finds the index of the given value in the array.
2882      * <p>
2883      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2884      * </p>
2885      *
2886      * @param array       the array to search for the object, may be {@code null}.
2887      * @param valueToFind the value to find.
2888      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2889      */
2890     public static int indexOf(final float[] array, final float valueToFind) {
2891         return indexOf(array, valueToFind, 0);
2892     }
2893 
2894     /**
2895      * Finds the index of the given value in the array starting at the given index.
2896      * <p>
2897      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2898      * </p>
2899      * <p>
2900      * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2901      * </p>
2902      *
2903      * @param array       the array to search for the object, may be {@code null}.
2904      * @param valueToFind the value to find.
2905      * @param startIndex  the index to start searching.
2906      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2907      */
2908     public static int indexOf(final float[] array, final float valueToFind, final int startIndex) {
2909         if (isEmpty(array)) {
2910             return INDEX_NOT_FOUND;
2911         }
2912         final boolean searchNaN = Float.isNaN(valueToFind);
2913         for (int i = max0(startIndex); i < array.length; i++) {
2914             final float element = array[i];
2915             if (valueToFind == element || searchNaN && Float.isNaN(element)) {
2916                 return i;
2917             }
2918         }
2919         return INDEX_NOT_FOUND;
2920     }
2921 
2922     /**
2923      * Finds the index of the given value in the array.
2924      * <p>
2925      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2926      * </p>
2927      *
2928      * @param array       the array to search for the object, may be {@code null}.
2929      * @param valueToFind the value to find.
2930      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2931      */
2932     public static int indexOf(final int[] array, final int valueToFind) {
2933         return indexOf(array, valueToFind, 0);
2934     }
2935 
2936     /**
2937      * Finds the index of the given value in the array starting at the given index.
2938      * <p>
2939      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2940      * </p>
2941      * <p>
2942      * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2943      * </p>
2944      *
2945      * @param array       the array to search for the object, may be {@code null}.
2946      * @param valueToFind the value to find.
2947      * @param startIndex  the index to start searching.
2948      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2949      */
2950     public static int indexOf(final int[] array, final int valueToFind, final int startIndex) {
2951         if (isEmpty(array)) {
2952             return INDEX_NOT_FOUND;
2953         }
2954         for (int i = max0(startIndex); i < array.length; i++) {
2955             if (valueToFind == array[i]) {
2956                 return i;
2957             }
2958         }
2959         return INDEX_NOT_FOUND;
2960     }
2961 
2962     /**
2963      * Finds the index of the given value in the array.
2964      * <p>
2965      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2966      * </p>
2967      *
2968      * @param array       the array to search for the object, may be {@code null}.
2969      * @param valueToFind the value to find.
2970      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2971      */
2972     public static int indexOf(final long[] array, final long valueToFind) {
2973         return indexOf(array, valueToFind, 0);
2974     }
2975 
2976     /**
2977      * Finds the index of the given value in the array starting at the given index.
2978      * <p>
2979      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2980      * </p>
2981      * <p>
2982      * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2983      * </p>
2984      *
2985      * @param array       the array to search for the object, may be {@code null}.
2986      * @param valueToFind the value to find.
2987      * @param startIndex  the index to start searching.
2988      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
2989      */
2990     public static int indexOf(final long[] array, final long valueToFind, final int startIndex) {
2991         if (isEmpty(array)) {
2992             return INDEX_NOT_FOUND;
2993         }
2994         for (int i = max0(startIndex); i < array.length; i++) {
2995             if (valueToFind == array[i]) {
2996                 return i;
2997             }
2998         }
2999         return INDEX_NOT_FOUND;
3000     }
3001 
3002     /**
3003      * Finds the index of the given object in the array.
3004      * <p>
3005      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3006      * </p>
3007      *
3008      * @param array        the array to search for the object, may be {@code null}.
3009      * @param objectToFind the object to find, may be {@code null}.
3010      * @return the index of the object within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3011      */
3012     public static int indexOf(final Object[] array, final Object objectToFind) {
3013         return indexOf(array, objectToFind, 0);
3014     }
3015 
3016     /**
3017      * Finds the index of the given object in the array starting at the given index.
3018      * <p>
3019      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3020      * </p>
3021      * <p>
3022      * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3023      * </p>
3024      *
3025      * @param array        the array to search for the object, may be {@code null}.
3026      * @param objectToFind the object to find, may be {@code null}.
3027      * @param startIndex   the index to start searching.
3028      * @return the index of the object within the array starting at the index, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3029      */
3030     public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
3031         if (isEmpty(array)) {
3032             return INDEX_NOT_FOUND;
3033         }
3034         startIndex = max0(startIndex);
3035         if (objectToFind == null) {
3036             for (int i = startIndex; i < array.length; i++) {
3037                 if (array[i] == null) {
3038                     return i;
3039                 }
3040             }
3041         } else {
3042             for (int i = startIndex; i < array.length; i++) {
3043                 if (objectToFind.equals(array[i])) {
3044                     return i;
3045                 }
3046             }
3047         }
3048         return INDEX_NOT_FOUND;
3049     }
3050 
3051     /**
3052      * Finds the index of the given value in the array.
3053      * <p>
3054      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3055      * </p>
3056      *
3057      * @param array       the array to search for the object, may be {@code null}
3058      * @param valueToFind the value to find.
3059      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3060      */
3061     public static int indexOf(final short[] array, final short valueToFind) {
3062         return indexOf(array, valueToFind, 0);
3063     }
3064 
3065     /**
3066      * Finds the index of the given value in the array starting at the given index.
3067      * <p>
3068      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3069      * </p>
3070      * <p>
3071      * A negative startIndex is treated as zero. A startIndex larger than the array length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3072      * </p>
3073      *
3074      * @param array       the array to search for the object, may be {@code null}.
3075      * @param valueToFind the value to find.
3076      * @param startIndex  the index to start searching.
3077      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3078      */
3079     public static int indexOf(final short[] array, final short valueToFind, final int startIndex) {
3080         if (isEmpty(array)) {
3081             return INDEX_NOT_FOUND;
3082         }
3083         for (int i = max0(startIndex); i < array.length; i++) {
3084             if (valueToFind == array[i]) {
3085                 return i;
3086             }
3087         }
3088         return INDEX_NOT_FOUND;
3089     }
3090 
3091     /**
3092      * Finds the index of the NaN value in a double array.
3093      * @param array the array to search for NaN, may be {@code null}.
3094      * @param startIndex the index to start searching.
3095      * @return the index of the NaN value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
3096      */
3097     private static int indexOfNaN(final double[] array, final int startIndex) {
3098         if (isEmpty(array)) {
3099             return INDEX_NOT_FOUND;
3100         }
3101         for (int i = max0(startIndex); i < array.length; i++) {
3102             if (Double.isNaN(array[i])) {
3103                 return i;
3104             }
3105         }
3106         return INDEX_NOT_FOUND;
3107     }
3108 
3109     /**
3110      * Inserts elements into an array at the given index (starting from zero).
3111      *
3112      * <p>
3113      * When an array is returned, it is always a new array.
3114      * </p>
3115      *
3116      * <pre>
3117      * ArrayUtils.insert(index, null, null)      = null
3118      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3119      * ArrayUtils.insert(index, null, values)    = null
3120      * </pre>
3121      *
3122      * @param index  the position within {@code array} to insert the new values.
3123      * @param array  the array to insert the values into, may be {@code null}.
3124      * @param values the new values to insert, may be {@code null}.
3125      * @return The new array or {@code null} if the given array is {@code null}.
3126      * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3127      * @since 3.6
3128      */
3129     public static boolean[] insert(final int index, final boolean[] array, final boolean... values) {
3130         if (array == null) {
3131             return null;
3132         }
3133         if (isEmpty(values)) {
3134             return clone(array);
3135         }
3136         if (index < 0 || index > array.length) {
3137             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3138         }
3139         final boolean[] result = new boolean[array.length + values.length];
3140         System.arraycopy(values, 0, result, index, values.length);
3141         if (index > 0) {
3142             System.arraycopy(array, 0, result, 0, index);
3143         }
3144         if (index < array.length) {
3145             System.arraycopy(array, index, result, index + values.length, array.length - index);
3146         }
3147         return result;
3148     }
3149 
3150     /**
3151      * Inserts elements into an array at the given index (starting from zero).
3152      *
3153      * <p>
3154      * When an array is returned, it is always a new array.
3155      * </p>
3156      *
3157      * <pre>
3158      * ArrayUtils.insert(index, null, null)      = null
3159      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3160      * ArrayUtils.insert(index, null, values)    = null
3161      * </pre>
3162      *
3163      * @param index  the position within {@code array} to insert the new values.
3164      * @param array  the array to insert the values into, may be {@code null}.
3165      * @param values the new values to insert, may be {@code null}.
3166      * @return The new array or {@code null} if the given array is {@code null}.
3167      * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3168      * @since 3.6
3169      */
3170     public static byte[] insert(final int index, final byte[] array, final byte... values) {
3171         if (array == null) {
3172             return null;
3173         }
3174         if (isEmpty(values)) {
3175             return clone(array);
3176         }
3177         if (index < 0 || index > array.length) {
3178             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3179         }
3180         final byte[] result = new byte[array.length + values.length];
3181         System.arraycopy(values, 0, result, index, values.length);
3182         if (index > 0) {
3183             System.arraycopy(array, 0, result, 0, index);
3184         }
3185         if (index < array.length) {
3186             System.arraycopy(array, index, result, index + values.length, array.length - index);
3187         }
3188         return result;
3189     }
3190 
3191     /**
3192      * Inserts elements into an array at the given index (starting from zero).
3193      *
3194      * <p>
3195      * When an array is returned, it is always a new array.
3196      * </p>
3197      *
3198      * <pre>
3199      * ArrayUtils.insert(index, null, null)      = null
3200      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3201      * ArrayUtils.insert(index, null, values)    = null
3202      * </pre>
3203      *
3204      * @param index  the position within {@code array} to insert the new values.
3205      * @param array  the array to insert the values into, may be {@code null}.
3206      * @param values the new values to insert, may be {@code null}.
3207      * @return The new array or {@code null} if the given array is {@code null}.
3208      * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3209      * @since 3.6
3210      */
3211     public static char[] insert(final int index, final char[] array, final char... values) {
3212         if (array == null) {
3213             return null;
3214         }
3215         if (isEmpty(values)) {
3216             return clone(array);
3217         }
3218         if (index < 0 || index > array.length) {
3219             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3220         }
3221         final char[] result = new char[array.length + values.length];
3222         System.arraycopy(values, 0, result, index, values.length);
3223         if (index > 0) {
3224             System.arraycopy(array, 0, result, 0, index);
3225         }
3226         if (index < array.length) {
3227             System.arraycopy(array, index, result, index + values.length, array.length - index);
3228         }
3229         return result;
3230     }
3231 
3232     /**
3233      * Inserts elements into an array at the given index (starting from zero).
3234      *
3235      * <p>
3236      * When an array is returned, it is always a new array.
3237      * </p>
3238      *
3239      * <pre>
3240      * ArrayUtils.insert(index, null, null)      = null
3241      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3242      * ArrayUtils.insert(index, null, values)    = null
3243      * </pre>
3244      *
3245      * @param index  the position within {@code array} to insert the new values.
3246      * @param array  the array to insert the values into, may be {@code null}.
3247      * @param values the new values to insert, may be {@code null}.
3248      * @return The new array or {@code null} if the given array is {@code null}.
3249      * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3250      * @since 3.6
3251      */
3252     public static double[] insert(final int index, final double[] array, final double... values) {
3253         if (array == null) {
3254             return null;
3255         }
3256         if (isEmpty(values)) {
3257             return clone(array);
3258         }
3259         if (index < 0 || index > array.length) {
3260             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3261         }
3262         final double[] result = new double[array.length + values.length];
3263         System.arraycopy(values, 0, result, index, values.length);
3264         if (index > 0) {
3265             System.arraycopy(array, 0, result, 0, index);
3266         }
3267         if (index < array.length) {
3268             System.arraycopy(array, index, result, index + values.length, array.length - index);
3269         }
3270         return result;
3271     }
3272 
3273     /**
3274      * Inserts elements into an array at the given index (starting from zero).
3275      *
3276      * <p>
3277      * When an array is returned, it is always a new array.
3278      * </p>
3279      *
3280      * <pre>
3281      * ArrayUtils.insert(index, null, null)      = null
3282      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3283      * ArrayUtils.insert(index, null, values)    = null
3284      * </pre>
3285      *
3286      * @param index  the position within {@code array} to insert the new values.
3287      * @param array  the array to insert the values into, may be {@code null}.
3288      * @param values the new values to insert, may be {@code null}.
3289      * @return The new array or {@code null} if the given array is {@code null}.
3290      * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3291      * @since 3.6
3292      */
3293     public static float[] insert(final int index, final float[] array, final float... values) {
3294         if (array == null) {
3295             return null;
3296         }
3297         if (isEmpty(values)) {
3298             return clone(array);
3299         }
3300         if (index < 0 || index > array.length) {
3301             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3302         }
3303         final float[] result = new float[array.length + values.length];
3304         System.arraycopy(values, 0, result, index, values.length);
3305         if (index > 0) {
3306             System.arraycopy(array, 0, result, 0, index);
3307         }
3308         if (index < array.length) {
3309             System.arraycopy(array, index, result, index + values.length, array.length - index);
3310         }
3311         return result;
3312     }
3313 
3314     /**
3315      * Inserts elements into an array at the given index (starting from zero).
3316      *
3317      * <p>
3318      * When an array is returned, it is always a new array.
3319      * </p>
3320      *
3321      * <pre>
3322      * ArrayUtils.insert(index, null, null)      = null
3323      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3324      * ArrayUtils.insert(index, null, values)    = null
3325      * </pre>
3326      *
3327      * @param index  the position within {@code array} to insert the new values.
3328      * @param array  the array to insert the values into, may be {@code null}.
3329      * @param values the new values to insert, may be {@code null}.
3330      * @return The new array or {@code null} if the given array is {@code null}.
3331      * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3332      * @since 3.6
3333      */
3334     public static int[] insert(final int index, final int[] array, final int... values) {
3335         if (array == null) {
3336             return null;
3337         }
3338         if (isEmpty(values)) {
3339             return clone(array);
3340         }
3341         if (index < 0 || index > array.length) {
3342             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3343         }
3344         final int[] result = new int[array.length + values.length];
3345         System.arraycopy(values, 0, result, index, values.length);
3346         if (index > 0) {
3347             System.arraycopy(array, 0, result, 0, index);
3348         }
3349         if (index < array.length) {
3350             System.arraycopy(array, index, result, index + values.length, array.length - index);
3351         }
3352         return result;
3353     }
3354 
3355     /**
3356      * Inserts elements into an array at the given index (starting from zero).
3357      *
3358      * <p>
3359      * When an array is returned, it is always a new array.
3360      * </p>
3361      *
3362      * <pre>
3363      * ArrayUtils.insert(index, null, null)      = null
3364      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3365      * ArrayUtils.insert(index, null, values)    = null
3366      * </pre>
3367      *
3368      * @param index  the position within {@code array} to insert the new values.
3369      * @param array  the array to insert the values into, may be {@code null}.
3370      * @param values the new values to insert, may be {@code null}.
3371      * @return The new array or {@code null} if the given array is {@code null}.
3372      * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3373      * @since 3.6
3374      */
3375     public static long[] insert(final int index, final long[] array, final long... values) {
3376         if (array == null) {
3377             return null;
3378         }
3379         if (isEmpty(values)) {
3380             return clone(array);
3381         }
3382         if (index < 0 || index > array.length) {
3383             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3384         }
3385         final long[] result = new long[array.length + values.length];
3386         System.arraycopy(values, 0, result, index, values.length);
3387         if (index > 0) {
3388             System.arraycopy(array, 0, result, 0, index);
3389         }
3390         if (index < array.length) {
3391             System.arraycopy(array, index, result, index + values.length, array.length - index);
3392         }
3393         return result;
3394     }
3395 
3396     /**
3397      * Inserts elements into an array at the given index (starting from zero).
3398      *
3399      * <p>
3400      * When an array is returned, it is always a new array.
3401      * </p>
3402      *
3403      * <pre>
3404      * ArrayUtils.insert(index, null, null)      = null
3405      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3406      * ArrayUtils.insert(index, null, values)    = null
3407      * </pre>
3408      *
3409      * @param index  the position within {@code array} to insert the new values.
3410      * @param array  the array to insert the values into, may be {@code null}.
3411      * @param values the new values to insert, may be {@code null}.
3412      * @return The new array or {@code null} if the given array is {@code null}.
3413      * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3414      * @since 3.6
3415      */
3416     public static short[] insert(final int index, final short[] array, final short... values) {
3417         if (array == null) {
3418             return null;
3419         }
3420         if (isEmpty(values)) {
3421             return clone(array);
3422         }
3423         if (index < 0 || index > array.length) {
3424             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3425         }
3426         final short[] result = new short[array.length + values.length];
3427         System.arraycopy(values, 0, result, index, values.length);
3428         if (index > 0) {
3429             System.arraycopy(array, 0, result, 0, index);
3430         }
3431         if (index < array.length) {
3432             System.arraycopy(array, index, result, index + values.length, array.length - index);
3433         }
3434         return result;
3435     }
3436 
3437     /**
3438      * Inserts elements into an array at the given index (starting from zero).
3439      *
3440      * <p>
3441      * When an array is returned, it is always a new array.
3442      * </p>
3443      *
3444      * <pre>
3445      * ArrayUtils.insert(index, null, null)      = null
3446      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3447      * ArrayUtils.insert(index, null, values)    = null
3448      * </pre>
3449      *
3450      * @param <T>    The type of elements in {@code array} and {@code values}.
3451      * @param index  the position within {@code array} to insert the new values.
3452      * @param array  the array to insert the values into, may be {@code null}.
3453      * @param values the new values to insert, may be {@code null}.
3454      * @return The new array or {@code null} if the given array is {@code null}.
3455      * @throws IndexOutOfBoundsException if {@code array} is provided and either {@code index < 0} or {@code index > array.length}.
3456      * @since 3.6
3457      */
3458     @SafeVarargs
3459     public static <T> T[] insert(final int index, final T[] array, final T... values) {
3460         /*
3461          * Note on use of @SafeVarargs:
3462          *
3463          * By returning null when 'array' is null, we avoid returning the vararg
3464          * array to the caller. We also avoid relying on the type of the vararg
3465          * array, by inspecting the component type of 'array'.
3466          */
3467         if (array == null) {
3468             return null;
3469         }
3470         if (isEmpty(values)) {
3471             return clone(array);
3472         }
3473         if (index < 0 || index > array.length) {
3474             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3475         }
3476         final Class<T> type = getComponentType(array);
3477         final int length = array.length + values.length;
3478         final T[] result = newInstance(type, length);
3479         System.arraycopy(values, 0, result, index, values.length);
3480         if (index > 0) {
3481             System.arraycopy(array, 0, result, 0, index);
3482         }
3483         if (index < array.length) {
3484             System.arraycopy(array, index, result, index + values.length, array.length - index);
3485         }
3486         return result;
3487     }
3488 
3489     /**
3490      * Checks if an array is empty or {@code null}.
3491      *
3492      * @param array the array to test.
3493      * @return {@code true} if the array is empty or {@code null}.
3494      */
3495     private static boolean isArrayEmpty(final Object array) {
3496         return getLength(array) == 0;
3497     }
3498 
3499     /**
3500      * Tests whether a given array can safely be accessed at the given index.
3501      *
3502      * <pre>
3503      * ArrayUtils.isArrayIndexValid(null, 0)       = false
3504      * ArrayUtils.isArrayIndexValid([], 0)         = false
3505      * ArrayUtils.isArrayIndexValid(["a"], 0)      = true
3506      * </pre>
3507      *
3508      * @param <T> the component type of the array.
3509      * @param array the array to inspect, may be {@code null}.
3510      * @param index the index of the array to be inspected.
3511      * @return Whether the given index is safely-accessible in the given array.
3512      * @since 3.8
3513      */
3514     public static <T> boolean isArrayIndexValid(final T[] array, final int index) {
3515         return index >= 0 && getLength(array) > index;
3516     }
3517 
3518     /**
3519      * Tests whether an array of primitive booleans is empty or {@code null}.
3520      *
3521      * @param array  the array to test.
3522      * @return {@code true} if the array is empty or {@code null}.
3523      * @since 2.1
3524      */
3525     public static boolean isEmpty(final boolean[] array) {
3526         return isArrayEmpty(array);
3527     }
3528 
3529     /**
3530      * Tests whether an array of primitive bytes is empty or {@code null}.
3531      *
3532      * @param array  the array to test.
3533      * @return {@code true} if the array is empty or {@code null}.
3534      * @since 2.1
3535      */
3536     public static boolean isEmpty(final byte[] array) {
3537         return isArrayEmpty(array);
3538     }
3539 
3540     /**
3541      * Tests whether an array of primitive chars is empty or {@code null}.
3542      *
3543      * @param array  the array to test.
3544      * @return {@code true} if the array is empty or {@code null}.
3545      * @since 2.1
3546      */
3547     public static boolean isEmpty(final char[] array) {
3548         return isArrayEmpty(array);
3549     }
3550 
3551     /**
3552      * Tests whether an array of primitive doubles is empty or {@code null}.
3553      *
3554      * @param array  the array to test.
3555      * @return {@code true} if the array is empty or {@code null}.
3556      * @since 2.1
3557      */
3558     public static boolean isEmpty(final double[] array) {
3559         return isArrayEmpty(array);
3560     }
3561 
3562     /**
3563      * Tests whether an array of primitive floats is empty or {@code null}.
3564      *
3565      * @param array  the array to test.
3566      * @return {@code true} if the array is empty or {@code null}.
3567      * @since 2.1
3568      */
3569     public static boolean isEmpty(final float[] array) {
3570         return isArrayEmpty(array);
3571     }
3572 
3573     /**
3574      * Tests whether an array of primitive ints is empty or {@code null}.
3575      *
3576      * @param array  the array to test.
3577      * @return {@code true} if the array is empty or {@code null}.
3578      * @since 2.1
3579      */
3580     public static boolean isEmpty(final int[] array) {
3581         return isArrayEmpty(array);
3582     }
3583 
3584     /**
3585      * Tests whether an array of primitive longs is empty or {@code null}.
3586      *
3587      * @param array  the array to test.
3588      * @return {@code true} if the array is empty or {@code null}.
3589      * @since 2.1
3590      */
3591     public static boolean isEmpty(final long[] array) {
3592         return isArrayEmpty(array);
3593     }
3594 
3595     /**
3596      * Tests whether an array of Objects is empty or {@code null}.
3597      *
3598      * @param array  the array to test.
3599      * @return {@code true} if the array is empty or {@code null}.
3600      * @since 2.1
3601      */
3602     public static boolean isEmpty(final Object[] array) {
3603         return isArrayEmpty(array);
3604     }
3605 
3606     /**
3607      * Tests whether an array of primitive shorts is empty or {@code null}.
3608      *
3609      * @param array  the array to test.
3610      * @return {@code true} if the array is empty or {@code null}.
3611      * @since 2.1
3612      */
3613     public static boolean isEmpty(final short[] array) {
3614         return isArrayEmpty(array);
3615     }
3616 
3617      /**
3618      * Tests whether two arrays have equal content, using equals(), handling multidimensional arrays
3619      * correctly.
3620      * <p>
3621      * Multi-dimensional primitive arrays are also handled correctly by this method.
3622      * </p>
3623      *
3624      * @param array1  the left-hand side array to compare, may be {@code null}.
3625      * @param array2  the right-hand side array to compare, may be {@code null}.
3626      * @return {@code true} if the arrays are equal.
3627      * @deprecated Replaced by {@code java.util.Objects.deepEquals(Object, Object)} and will be
3628      * removed from future releases.
3629      */
3630     @Deprecated
3631     public static boolean isEquals(final Object array1, final Object array2) {
3632         return new EqualsBuilder().append(array1, array2).isEquals();
3633     }
3634 
3635     /**
3636      * Tests whether an array of primitive booleans is not empty and not {@code null}.
3637      *
3638      * @param array  the array to test.
3639      * @return {@code true} if the array is not empty and not {@code null}.
3640      * @since 2.5
3641      */
3642     public static boolean isNotEmpty(final boolean[] array) {
3643         return !isEmpty(array);
3644     }
3645 
3646     /**
3647      * Tests whether an array of primitive bytes is not empty and not {@code null}.
3648      *
3649      * @param array  the array to test.
3650      * @return {@code true} if the array is not empty and not {@code null}.
3651      * @since 2.5
3652      */
3653     public static boolean isNotEmpty(final byte[] array) {
3654         return !isEmpty(array);
3655     }
3656 
3657     /**
3658      * Tests whether an array of primitive chars is not empty and not {@code null}.
3659      *
3660      * @param array  the array to test.
3661      * @return {@code true} if the array is not empty and not {@code null}.
3662      * @since 2.5
3663      */
3664     public static boolean isNotEmpty(final char[] array) {
3665         return !isEmpty(array);
3666     }
3667 
3668     /**
3669      * Tests whether an array of primitive doubles is not empty and not {@code null}.
3670      *
3671      * @param array  the array to test.
3672      * @return {@code true} if the array is not empty and not {@code null}.
3673      * @since 2.5
3674      */
3675     public static boolean isNotEmpty(final double[] array) {
3676         return !isEmpty(array);
3677     }
3678 
3679     /**
3680      * Tests whether an array of primitive floats is not empty and not {@code null}.
3681      *
3682      * @param array  the array to test.
3683      * @return {@code true} if the array is not empty and not {@code null}.
3684      * @since 2.5
3685      */
3686     public static boolean isNotEmpty(final float[] array) {
3687         return !isEmpty(array);
3688     }
3689 
3690     /**
3691      * Tests whether an array of primitive ints is not empty and not {@code null}.
3692      *
3693      * @param array  the array to test.
3694      * @return {@code true} if the array is not empty and not {@code null}.
3695      * @since 2.5
3696      */
3697     public static boolean isNotEmpty(final int[] array) {
3698         return !isEmpty(array);
3699     }
3700 
3701     /**
3702      * Tests whether an array of primitive longs is not empty and not {@code null}.
3703      *
3704      * @param array  the array to test.
3705      * @return {@code true} if the array is not empty and not {@code null}.
3706      * @since 2.5
3707      */
3708     public static boolean isNotEmpty(final long[] array) {
3709         return !isEmpty(array);
3710     }
3711 
3712     /**
3713      * Tests whether an array of primitive shorts is not empty and not {@code null}.
3714      *
3715      * @param array  the array to test.
3716      * @return {@code true} if the array is not empty and not {@code null}.
3717      * @since 2.5
3718      */
3719     public static boolean isNotEmpty(final short[] array) {
3720         return !isEmpty(array);
3721     }
3722 
3723     /**
3724      * Tests whether an array of Objects is not empty and not {@code null}.
3725      *
3726      * @param <T> the component type of the array
3727      * @param array  the array to test.
3728      * @return {@code true} if the array is not empty and not {@code null}.
3729      * @since 2.5
3730      */
3731      public static <T> boolean isNotEmpty(final T[] array) {
3732          return !isEmpty(array);
3733      }
3734 
3735     /**
3736       * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3737       *
3738       * @param array1 the first array, may be {@code null}.
3739       * @param array2 the second array, may be {@code null}.
3740       * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3741       */
3742      public static boolean isSameLength(final boolean[] array1, final boolean[] array2) {
3743         return getLength(array1) == getLength(array2);
3744     }
3745 
3746     /**
3747      * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3748      *
3749      * @param array1 the first array, may be {@code null}.
3750      * @param array2 the second array, may be {@code null}.
3751      * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3752      */
3753     public static boolean isSameLength(final byte[] array1, final byte[] array2) {
3754         return getLength(array1) == getLength(array2);
3755     }
3756 
3757     /**
3758      * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3759      *
3760      * @param array1 the first array, may be {@code null}.
3761      * @param array2 the second array, may be {@code null}.
3762      * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3763      */
3764     public static boolean isSameLength(final char[] array1, final char[] array2) {
3765         return getLength(array1) == getLength(array2);
3766     }
3767 
3768     /**
3769      * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3770      *
3771      * @param array1 the first array, may be {@code null}.
3772      * @param array2 the second array, may be {@code null}.
3773      * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3774      */
3775     public static boolean isSameLength(final double[] array1, final double[] array2) {
3776         return getLength(array1) == getLength(array2);
3777     }
3778 
3779     /**
3780      * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3781      *
3782      * @param array1 the first array, may be {@code null}.
3783      * @param array2 the second array, may be {@code null}.
3784      * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3785      */
3786     public static boolean isSameLength(final float[] array1, final float[] array2) {
3787         return getLength(array1) == getLength(array2);
3788     }
3789 
3790     /**
3791      * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3792      *
3793      * @param array1 the first array, may be {@code null}.
3794      * @param array2 the second array, may be {@code null}.
3795      * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3796      */
3797     public static boolean isSameLength(final int[] array1, final int[] array2) {
3798         return getLength(array1) == getLength(array2);
3799     }
3800 
3801     /**
3802      * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3803      *
3804      * @param array1 the first array, may be {@code null}.
3805      * @param array2 the second array, may be {@code null}.
3806      * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3807      */
3808     public static boolean isSameLength(final long[] array1, final long[] array2) {
3809         return getLength(array1) == getLength(array2);
3810     }
3811 
3812     /**
3813      * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3814      * <p>
3815      * Any multi-dimensional aspects of the arrays are ignored.
3816      * </p>
3817      *
3818      * @param array1 the first array, may be {@code null}.
3819      * @param array2 the second array, may be {@code null}.
3820      * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3821      * @since 3.11
3822      */
3823     public static boolean isSameLength(final Object array1, final Object array2) {
3824         return getLength(array1) == getLength(array2);
3825     }
3826 
3827     /**
3828      * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3829      * <p>
3830      * Any multi-dimensional aspects of the arrays are ignored.
3831      * </p>
3832      *
3833      * @param array1 the first array, may be {@code null}.
3834      * @param array2 the second array, may be {@code null}.
3835      * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3836      */
3837     public static boolean isSameLength(final Object[] array1, final Object[] array2) {
3838         return getLength(array1) == getLength(array2);
3839     }
3840 
3841     /**
3842      * Tests whether two arrays are the same length, treating {@code null} arrays as length {@code 0}.
3843      *
3844      * @param array1 the first array, may be {@code null}.
3845      * @param array2 the second array, may be {@code null}.
3846      * @return {@code true} if length of arrays matches, treating {@code null} as an empty array.
3847      */
3848     public static boolean isSameLength(final short[] array1, final short[] array2) {
3849         return getLength(array1) == getLength(array2);
3850     }
3851 
3852     /**
3853      * Tests whether two arrays are the same type taking into account multidimensional arrays.
3854      *
3855      * @param array1 the first array, must not be {@code null}.
3856      * @param array2 the second array, must not be {@code null}.
3857      * @return {@code true} if type of arrays matches.
3858      * @throws IllegalArgumentException if either array is {@code null}.
3859      */
3860     public static boolean isSameType(final Object array1, final Object array2) {
3861         if (array1 == null || array2 == null) {
3862             throw new IllegalArgumentException("The Array must not be null");
3863         }
3864         return array1.getClass().getName().equals(array2.getClass().getName());
3865     }
3866 
3867     /**
3868      * Tests whether whether the provided array is sorted according to natural ordering ({@code false} before {@code true}).
3869      *
3870      * @param array the array to check.
3871      * @return whether the array is sorted according to natural ordering.
3872      * @since 3.4
3873      */
3874     public static boolean isSorted(final boolean[] array) {
3875         if (getLength(array) < 2) {
3876             return true;
3877         }
3878         boolean previous = array[0];
3879         final int n = array.length;
3880         for (int i = 1; i < n; i++) {
3881             final boolean current = array[i];
3882             if (BooleanUtils.compare(previous, current) > 0) {
3883                 return false;
3884             }
3885             previous = current;
3886         }
3887         return true;
3888     }
3889 
3890     /**
3891      * Tests whether the provided array is sorted according to natural ordering.
3892      *
3893      * @param array the array to check.
3894      * @return whether the array is sorted according to natural ordering.
3895      * @since 3.4
3896      */
3897     public static boolean isSorted(final byte[] array) {
3898         if (getLength(array) < 2) {
3899             return true;
3900         }
3901         byte previous = array[0];
3902         final int n = array.length;
3903         for (int i = 1; i < n; i++) {
3904             final byte current = array[i];
3905             if (Byte.compare(previous, current) > 0) {
3906                 return false;
3907             }
3908             previous = current;
3909         }
3910         return true;
3911     }
3912 
3913     /**
3914      * Tests whether the provided array is sorted according to natural ordering.
3915      *
3916      * @param array the array to check.
3917      * @return whether the array is sorted according to natural ordering.
3918      * @since 3.4
3919      */
3920     public static boolean isSorted(final char[] array) {
3921         if (getLength(array) < 2) {
3922             return true;
3923         }
3924         char previous = array[0];
3925         final int n = array.length;
3926         for (int i = 1; i < n; i++) {
3927             final char current = array[i];
3928             if (CharUtils.compare(previous, current) > 0) {
3929                 return false;
3930             }
3931             previous = current;
3932         }
3933         return true;
3934     }
3935 
3936     /**
3937      * Tests whether the provided array is sorted according to natural ordering.
3938      *
3939      * @param array the array to check.
3940      * @return whether the array is sorted according to natural ordering.
3941      * @since 3.4
3942      */
3943     public static boolean isSorted(final double[] array) {
3944         if (getLength(array) < 2) {
3945             return true;
3946         }
3947         double previous = array[0];
3948         final int n = array.length;
3949         for (int i = 1; i < n; i++) {
3950             final double current = array[i];
3951             if (Double.compare(previous, current) > 0) {
3952                 return false;
3953             }
3954             previous = current;
3955         }
3956         return true;
3957     }
3958 
3959     /**
3960      * Tests whether the provided array is sorted according to natural ordering.
3961      *
3962      * @param array the array to check.
3963      * @return whether the array is sorted according to natural ordering.
3964      * @since 3.4
3965      */
3966     public static boolean isSorted(final float[] array) {
3967         if (getLength(array) < 2) {
3968             return true;
3969         }
3970         float previous = array[0];
3971         final int n = array.length;
3972         for (int i = 1; i < n; i++) {
3973             final float current = array[i];
3974             if (Float.compare(previous, current) > 0) {
3975                 return false;
3976             }
3977             previous = current;
3978         }
3979         return true;
3980     }
3981 
3982     /**
3983      * Tests whether the provided array is sorted according to natural ordering.
3984      *
3985      * @param array the array to check.
3986      * @return whether the array is sorted according to natural ordering.
3987      * @since 3.4
3988      */
3989     public static boolean isSorted(final int[] array) {
3990         if (getLength(array) < 2) {
3991             return true;
3992         }
3993         int previous = array[0];
3994         final int n = array.length;
3995         for (int i = 1; i < n; i++) {
3996             final int current = array[i];
3997             if (Integer.compare(previous, current) > 0) {
3998                 return false;
3999             }
4000             previous = current;
4001         }
4002         return true;
4003     }
4004 
4005     /**
4006      * Tests whether the provided array is sorted according to natural ordering.
4007      *
4008      * @param array the array to check.
4009      * @return whether the array is sorted according to natural ordering.
4010      * @since 3.4
4011      */
4012     public static boolean isSorted(final long[] array) {
4013         if (getLength(array) < 2) {
4014             return true;
4015         }
4016         long previous = array[0];
4017         final int n = array.length;
4018         for (int i = 1; i < n; i++) {
4019             final long current = array[i];
4020             if (Long.compare(previous, current) > 0) {
4021                 return false;
4022             }
4023             previous = current;
4024         }
4025         return true;
4026     }
4027 
4028     /**
4029      * Tests whether the provided array is sorted according to natural ordering.
4030      *
4031      * @param array the array to check.
4032      * @return whether the array is sorted according to natural ordering.
4033      * @since 3.4
4034      */
4035     public static boolean isSorted(final short[] array) {
4036         if (getLength(array) < 2) {
4037             return true;
4038         }
4039         short previous = array[0];
4040         final int n = array.length;
4041         for (int i = 1; i < n; i++) {
4042             final short current = array[i];
4043             if (Short.compare(previous, current) > 0) {
4044                 return false;
4045             }
4046             previous = current;
4047         }
4048         return true;
4049     }
4050 
4051     /**
4052      * Tests whether the provided array is sorted according to the class's
4053      * {@code compareTo} method.
4054      *
4055      * @param array the array to check.
4056      * @param <T> the datatype of the array to check, it must implement {@link Comparable}.
4057      * @return whether the array is sorted.
4058      * @since 3.4
4059      */
4060     public static <T extends Comparable<? super T>> boolean isSorted(final T[] array) {
4061         return isSorted(array, Comparable::compareTo);
4062     }
4063 
4064     /**
4065      * Tests whether the provided array is sorted according to the provided {@link Comparator}.
4066      *
4067      * @param array the array to check.
4068      * @param comparator the {@link Comparator} to compare over.
4069      * @param <T> the datatype of the array.
4070      * @return whether the array is sorted.
4071      * @throws NullPointerException if {@code comparator} is {@code null}.
4072      * @since 3.4
4073      */
4074     public static <T> boolean isSorted(final T[] array, final Comparator<T> comparator) {
4075         Objects.requireNonNull(comparator, "comparator");
4076         if (getLength(array) < 2) {
4077             return true;
4078         }
4079         T previous = array[0];
4080         final int n = array.length;
4081         for (int i = 1; i < n; i++) {
4082             final T current = array[i];
4083             if (comparator.compare(previous, current) > 0) {
4084                 return false;
4085             }
4086             previous = current;
4087         }
4088         return true;
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}) if {@code null} array input.
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, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4100      */
4101     public static int lastIndexOf(final boolean[] array, final boolean valueToFind) {
4102         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4103     }
4104 
4105     /**
4106      * Finds the last index of the given value in the array starting at the given index.
4107      * <p>
4108      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4109      * </p>
4110      * <p>
4111      * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4112      * </p>
4113      *
4114      * @param array       the array to traverse for looking for the object, may be {@code null}.
4115      * @param valueToFind the value to find.
4116      * @param startIndex  the start index to traverse backwards from.
4117      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4118      */
4119     public static int lastIndexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
4120         if (isEmpty(array) || startIndex < 0) {
4121             return INDEX_NOT_FOUND;
4122         }
4123         if (startIndex >= array.length) {
4124             startIndex = array.length - 1;
4125         }
4126         for (int i = startIndex; i >= 0; i--) {
4127             if (valueToFind == array[i]) {
4128                 return i;
4129             }
4130         }
4131         return INDEX_NOT_FOUND;
4132     }
4133 
4134     /**
4135      * Finds the last index of the given value within the array.
4136      * <p>
4137      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4138      * </p>
4139      *
4140      * @param array       the array to traverse backwards looking for the object, may be {@code null}.
4141      * @param valueToFind the object to find.
4142      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4143      */
4144     public static int lastIndexOf(final byte[] array, final byte valueToFind) {
4145         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4146     }
4147 
4148     /**
4149      * Finds the last index of the given value in the array starting at the given index.
4150      * <p>
4151      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4152      * </p>
4153      * <p>
4154      * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4155      * </p>
4156      *
4157      * @param array       the array to traverse for looking for the object, may be {@code null}.
4158      * @param valueToFind the value to find.
4159      * @param startIndex  the start index to traverse backwards from.
4160      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4161      */
4162     public static int lastIndexOf(final byte[] array, final byte valueToFind, int startIndex) {
4163         if (array == null || startIndex < 0) {
4164             return INDEX_NOT_FOUND;
4165         }
4166         if (startIndex >= array.length) {
4167             startIndex = array.length - 1;
4168         }
4169         for (int i = startIndex; i >= 0; i--) {
4170             if (valueToFind == array[i]) {
4171                 return i;
4172             }
4173         }
4174         return INDEX_NOT_FOUND;
4175     }
4176 
4177     /**
4178      * Finds the last index of the given value within the array.
4179      * <p>
4180      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4181      * </p>
4182      *
4183      * @param array       the array to traverse backwards looking for the object, may be {@code null}.
4184      * @param valueToFind the object to find.
4185      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4186      * @since 2.1
4187      */
4188     public static int lastIndexOf(final char[] array, final char valueToFind) {
4189         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4190     }
4191 
4192     /**
4193      * Finds the last index of the given value in the array starting at the given index.
4194      * <p>
4195      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4196      * </p>
4197      * <p>
4198      * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4199      * </p>
4200      *
4201      * @param array       the array to traverse for looking for the object, may be {@code null}.
4202      * @param valueToFind the value to find.
4203      * @param startIndex  the start index to traverse backwards from.
4204      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4205      * @since 2.1
4206      */
4207     public static int lastIndexOf(final char[] array, final char valueToFind, int startIndex) {
4208         if (array == null || startIndex < 0) {
4209             return INDEX_NOT_FOUND;
4210         }
4211         if (startIndex >= array.length) {
4212             startIndex = array.length - 1;
4213         }
4214         for (int i = startIndex; i >= 0; i--) {
4215             if (valueToFind == array[i]) {
4216                 return i;
4217             }
4218         }
4219         return INDEX_NOT_FOUND;
4220     }
4221 
4222     /**
4223      * Finds the last index of the given value within the array.
4224      * <p>
4225      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4226      * </p>
4227      *
4228      * @param array       the array to traverse backwards looking for the object, may be {@code null}.
4229      * @param valueToFind the object to find.
4230      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4231      */
4232     public static int lastIndexOf(final double[] array, final double valueToFind) {
4233         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4234     }
4235 
4236     /**
4237      * Finds the last index of the given value within a given tolerance in the array. This method will return the index of the last value which falls between
4238      * the region defined by valueToFind - tolerance and valueToFind + tolerance.
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 search for the object, may be {@code null}.
4244      * @param valueToFind the value to find.
4245      * @param tolerance   tolerance of the search.
4246      * @return the index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4247      */
4248     public static int lastIndexOf(final double[] array, final double valueToFind, final double tolerance) {
4249         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance);
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 array length will search from the end of the array.
4259      * </p>
4260      *
4261      * @param array       the array to traverse for looking for the object, may be {@code null}.
4262      * @param valueToFind the value to find.
4263      * @param startIndex  the start index to traverse backwards from.
4264      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4265      */
4266     public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex) {
4267         if (isEmpty(array) || startIndex < 0) {
4268             return INDEX_NOT_FOUND;
4269         }
4270         if (startIndex >= array.length) {
4271             startIndex = array.length - 1;
4272         }
4273         for (int i = startIndex; i >= 0; i--) {
4274             if (valueToFind == array[i]) {
4275                 return i;
4276             }
4277         }
4278         return INDEX_NOT_FOUND;
4279     }
4280 
4281     /**
4282      * Finds the last index of the given value in the array starting at the given index. This method will return the index of the last value which falls between
4283      * the region defined by valueToFind - tolerance and valueToFind + tolerance.
4284      * <p>
4285      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4286      * </p>
4287      * <p>
4288      * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4289      * </p>
4290      *
4291      * @param array       the array to traverse for looking for the object, may be {@code null}.
4292      * @param valueToFind the value to find.
4293      * @param startIndex  the start index to traverse backwards from.
4294      * @param tolerance   search for value within plus/minus this amount.
4295      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4296      */
4297     public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
4298         if (isEmpty(array) || startIndex < 0) {
4299             return INDEX_NOT_FOUND;
4300         }
4301         if (startIndex >= array.length) {
4302             startIndex = array.length - 1;
4303         }
4304         final double min = valueToFind - tolerance;
4305         final double max = valueToFind + tolerance;
4306         for (int i = startIndex; i >= 0; i--) {
4307             if (array[i] >= min && array[i] <= max) {
4308                 return i;
4309             }
4310         }
4311         return INDEX_NOT_FOUND;
4312     }
4313 
4314     /**
4315      * Finds the last index of the given value within the array.
4316      * <p>
4317      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4318      * </p>
4319      *
4320      * @param array       the array to traverse backwards looking for the object, may be {@code null}.
4321      * @param valueToFind the object to find.
4322      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4323      */
4324     public static int lastIndexOf(final float[] array, final float valueToFind) {
4325         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4326     }
4327 
4328     /**
4329      * Finds the last index of the given value in the array starting at the given index.
4330      * <p>
4331      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4332      * </p>
4333      * <p>
4334      * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4335      * </p>
4336      *
4337      * @param array       the array to traverse for looking for the object, may be {@code null}.
4338      * @param valueToFind the value to find.
4339      * @param startIndex  the start index to traverse backwards from.
4340      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4341      */
4342     public static int lastIndexOf(final float[] array, final float valueToFind, int startIndex) {
4343         if (isEmpty(array) || startIndex < 0) {
4344             return INDEX_NOT_FOUND;
4345         }
4346         if (startIndex >= array.length) {
4347             startIndex = array.length - 1;
4348         }
4349         for (int i = startIndex; i >= 0; i--) {
4350             if (valueToFind == array[i]) {
4351                 return i;
4352             }
4353         }
4354         return INDEX_NOT_FOUND;
4355     }
4356 
4357     /**
4358      * Finds the last index of the given value within the array.
4359      * <p>
4360      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4361      * </p>
4362      *
4363      * @param array       the array to traverse backwards looking for the object, may be {@code null}.
4364      * @param valueToFind the object to find.
4365      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4366      */
4367     public static int lastIndexOf(final int[] array, final int valueToFind) {
4368         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4369     }
4370 
4371     /**
4372      * Finds the last index of the given value in the array starting at the given index.
4373      * <p>
4374      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4375      * </p>
4376      * <p>
4377      * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4378      * </p>
4379      *
4380      * @param array       the array to traverse for looking for the object, may be {@code null}.
4381      * @param valueToFind the value to find.
4382      * @param startIndex  the start index to traverse backwards from.
4383      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4384      */
4385     public static int lastIndexOf(final int[] array, final int valueToFind, int startIndex) {
4386         if (array == null || startIndex < 0) {
4387             return INDEX_NOT_FOUND;
4388         }
4389         if (startIndex >= array.length) {
4390             startIndex = array.length - 1;
4391         }
4392         for (int i = startIndex; i >= 0; i--) {
4393             if (valueToFind == array[i]) {
4394                 return i;
4395             }
4396         }
4397         return INDEX_NOT_FOUND;
4398     }
4399 
4400     /**
4401      * Finds the last index of the given value within the array.
4402      * <p>
4403      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4404      * </p>
4405      *
4406      * @param array       the array to traverse backwards looking for the object, may be {@code null}.
4407      * @param valueToFind the object to find.
4408      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4409      */
4410     public static int lastIndexOf(final long[] array, final long valueToFind) {
4411         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4412     }
4413 
4414     /**
4415      * Finds the last index of the given value in the array starting at the given index.
4416      * <p>
4417      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4418      * </p>
4419      * <p>
4420      * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4421      * </p>
4422      *
4423      * @param array       the array to traverse for looking for the object, may be {@code null}.
4424      * @param valueToFind the value to find.
4425      * @param startIndex  the start index to traverse backwards from.
4426      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4427      */
4428     public static int lastIndexOf(final long[] array, final long valueToFind, int startIndex) {
4429         if (array == null || startIndex < 0) {
4430             return INDEX_NOT_FOUND;
4431         }
4432         if (startIndex >= array.length) {
4433             startIndex = array.length - 1;
4434         }
4435         for (int i = startIndex; i >= 0; i--) {
4436             if (valueToFind == array[i]) {
4437                 return i;
4438             }
4439         }
4440         return INDEX_NOT_FOUND;
4441     }
4442 
4443     /**
4444      * Finds the last index of the given object within the array.
4445      * <p>
4446      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4447      * </p>
4448      *
4449      * @param array        the array to traverse backwards looking for the object, may be {@code null}.
4450      * @param objectToFind the object to find, may be {@code null}.
4451      * @return the last index of the object within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4452      */
4453     public static int lastIndexOf(final Object[] array, final Object objectToFind) {
4454         return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
4455     }
4456 
4457     /**
4458      * Finds the last index of the given object in the array starting at the given index.
4459      * <p>
4460      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4461      * </p>
4462      * <p>
4463      * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4464      * </p>
4465      *
4466      * @param array        the array to traverse for looking for the object, may be {@code null}.
4467      * @param objectToFind the object to find, may be {@code null}.
4468      * @param startIndex   the start index to traverse backwards from.
4469      * @return the last index of the object within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4470      */
4471     public static int lastIndexOf(final Object[] array, final Object objectToFind, int startIndex) {
4472         if (array == null || startIndex < 0) {
4473             return INDEX_NOT_FOUND;
4474         }
4475         if (startIndex >= array.length) {
4476             startIndex = array.length - 1;
4477         }
4478         if (objectToFind == null) {
4479             for (int i = startIndex; i >= 0; i--) {
4480                 if (array[i] == null) {
4481                     return i;
4482                 }
4483             }
4484         } else if (array.getClass().getComponentType().isInstance(objectToFind)) {
4485             for (int i = startIndex; i >= 0; i--) {
4486                 if (objectToFind.equals(array[i])) {
4487                     return i;
4488                 }
4489             }
4490         }
4491         return INDEX_NOT_FOUND;
4492     }
4493 
4494     /**
4495      * Finds the last index of the given value within the array.
4496      * <p>
4497      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4498      * </p>
4499      *
4500      * @param array       the array to traverse backwards looking for the object, may be {@code null}.
4501      * @param valueToFind the object to find.
4502      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4503      */
4504     public static int lastIndexOf(final short[] array, final short valueToFind) {
4505         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4506     }
4507 
4508     /**
4509      * Finds the last index of the given value in the array starting at the given index.
4510      * <p>
4511      * This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4512      * </p>
4513      * <p>
4514      * A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the array length will search from the end of the array.
4515      * </p>
4516      *
4517      * @param array       the array to traverse for looking for the object, may be {@code null}.
4518      * @param valueToFind the value to find.
4519      * @param startIndex  the start index to traverse backwards from.
4520      * @return the last index of the value within the array, {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input.
4521      */
4522     public static int lastIndexOf(final short[] array, final short valueToFind, int startIndex) {
4523         if (array == null || startIndex < 0) {
4524             return INDEX_NOT_FOUND;
4525         }
4526         if (startIndex >= array.length) {
4527             startIndex = array.length - 1;
4528         }
4529         for (int i = startIndex; i >= 0; i--) {
4530             if (valueToFind == array[i]) {
4531                 return i;
4532             }
4533         }
4534         return INDEX_NOT_FOUND;
4535     }
4536 
4537     /**
4538      * Maps elements from an array into elements of a new array of a given type, while mapping old elements to new elements.
4539      *
4540      * @param <T>           The input array type.
4541      * @param <R>           The output array type.
4542      * @param <E>           The type of exceptions thrown when the mapper function fails.
4543      * @param array         The input array.
4544      * @param componentType the component type of the result array.
4545      * @param mapper        a non-interfering, stateless function to apply to each element.
4546      * @return a new array.
4547      * @throws E Thrown when the mapper function fails.
4548      */
4549     private static <T, R, E extends Throwable> R[] map(final T[] array, final Class<R> componentType, final FailableFunction<? super T, ? extends R, E> mapper)
4550             throws E {
4551         return ArrayFill.fill(newInstance(componentType, array.length), i -> mapper.apply(array[i]));
4552     }
4553 
4554     private static int max0(final int other) {
4555         return Math.max(0, other);
4556     }
4557 
4558     /**
4559      * Delegates to {@link Array#newInstance(Class,int)} using generics.
4560      *
4561      * @param <T> The array type.
4562      * @param componentType The array class.
4563      * @param length the array length
4564      * @return The new array.
4565      * @throws NullPointerException if the specified {@code componentType} parameter is null.
4566      * @since 3.13.0
4567      */
4568     @SuppressWarnings("unchecked") // OK, because array and values are of type T
4569     public static <T> T[] newInstance(final Class<T> componentType, final int length) {
4570         return (T[]) Array.newInstance(componentType, length);
4571     }
4572 
4573     /**
4574      * Defensive programming technique to change a {@code null}
4575      * reference to an empty one.
4576      * <p>
4577      * This method returns a default array for a {@code null} input array.
4578      * </p>
4579      * <p>
4580      * As a memory optimizing technique an empty array passed in will be overridden with
4581      * the empty {@code public static} references in this class.
4582      * </p>
4583      *
4584      * @param <T> The array type.
4585      * @param array  the array to check for {@code null} or empty
4586      * @param defaultArray A default array, usually empty.
4587      * @return the same array, or defaultArray if {@code null} or empty input.
4588      * @since 3.15.0
4589      */
4590     public static <T> T[] nullTo(final T[] array, final T[] defaultArray) {
4591         return isEmpty(array) ? defaultArray : array;
4592     }
4593 
4594     /**
4595      * Defensive programming technique to change a {@code null}
4596      * reference to an empty one.
4597      * <p>
4598      * This method returns an empty array for a {@code null} input array.
4599      * </p>
4600      * <p>
4601      * As a memory optimizing technique an empty array passed in will be overridden with
4602      * the empty {@code public static} references in this class.
4603      * </p>
4604      *
4605      * @param array  the array to check for {@code null} or empty.
4606      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4607      * @since 2.5
4608      */
4609     public static boolean[] nullToEmpty(final boolean[] array) {
4610         return isEmpty(array) ? EMPTY_BOOLEAN_ARRAY : array;
4611     }
4612 
4613     /**
4614      * Defensive programming technique to change a {@code null}
4615      * reference to an empty one.
4616      * <p>
4617      * This method returns an empty array for a {@code null} input array.
4618      * </p>
4619      * <p>
4620      * As a memory optimizing technique an empty array passed in will be overridden with
4621      * the empty {@code public static} references in this class.
4622      * </p>
4623      *
4624      * @param array  the array to check for {@code null} or empty.
4625      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4626      * @since 2.5
4627      */
4628     public static Boolean[] nullToEmpty(final Boolean[] array) {
4629         return nullTo(array, EMPTY_BOOLEAN_OBJECT_ARRAY);
4630     }
4631 
4632     /**
4633      * Defensive programming technique to change a {@code null}
4634      * reference to an empty one.
4635      * <p>
4636      * This method returns an empty array for a {@code null} input array.
4637      * </p>
4638      * <p>
4639      * As a memory optimizing technique an empty array passed in will be overridden with
4640      * the empty {@code public static} references in this class.
4641      * </p>
4642      *
4643      * @param array  the array to check for {@code null} or empty.
4644      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4645      * @since 2.5
4646      */
4647     public static byte[] nullToEmpty(final byte[] array) {
4648         return isEmpty(array) ? EMPTY_BYTE_ARRAY : array;
4649     }
4650 
4651     /**
4652      * Defensive programming technique to change a {@code null}
4653      * reference to an empty one.
4654      * <p>
4655      * This method returns an empty array for a {@code null} input array.
4656      * </p>
4657      * <p>
4658      * As a memory optimizing technique an empty array passed in will be overridden with
4659      * the empty {@code public static} references in this class.
4660      * </p>
4661      *
4662      * @param array  the array to check for {@code null} or empty.
4663      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4664      * @since 2.5
4665      */
4666     public static Byte[] nullToEmpty(final Byte[] array) {
4667         return nullTo(array, EMPTY_BYTE_OBJECT_ARRAY);
4668     }
4669 
4670     /**
4671      * Defensive programming technique to change a {@code null}
4672      * reference to an empty one.
4673      * <p>
4674      * This method returns an empty array for a {@code null} input array.
4675      * </p>
4676      * <p>
4677      * As a memory optimizing technique an empty array passed in will be overridden with
4678      * the empty {@code public static} references in this class.
4679      * </p>
4680      *
4681      * @param array  the array to check for {@code null} or empty.
4682      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4683      * @since 2.5
4684      */
4685     public static char[] nullToEmpty(final char[] array) {
4686         return isEmpty(array) ? EMPTY_CHAR_ARRAY : array;
4687     }
4688 
4689     /**
4690      * Defensive programming technique to change a {@code null}
4691      * reference to an empty one.
4692      * <p>
4693      * This method returns an empty array for a {@code null} input array.
4694      * </p>
4695      * <p>
4696      * As a memory optimizing technique an empty array passed in will be overridden with
4697      * the empty {@code public static} references in this class.
4698      * </p>
4699      *
4700      * @param array  the array to check for {@code null} or empty.
4701      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4702      * @since 2.5
4703      */
4704     public static Character[] nullToEmpty(final Character[] array) {
4705         return nullTo(array, EMPTY_CHARACTER_OBJECT_ARRAY);
4706     }
4707 
4708     /**
4709      * Defensive programming technique to change a {@code null}
4710      * reference to an empty one.
4711      * <p>
4712      * This method returns an empty array for a {@code null} input array.
4713      * </p>
4714      * <p>
4715      * As a memory optimizing technique an empty array passed in will be overridden with
4716      * the empty {@code public static} references in this class.
4717      * </p>
4718      *
4719      * @param array  the array to check for {@code null} or empty.
4720      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4721      * @since 3.2
4722      */
4723     public static Class<?>[] nullToEmpty(final Class<?>[] array) {
4724         return nullTo(array, EMPTY_CLASS_ARRAY);
4725     }
4726 
4727     /**
4728      * Defensive programming technique to change a {@code null}
4729      * reference to an empty one.
4730      * <p>
4731      * This method returns an empty array for a {@code null} input array.
4732      * </p>
4733      * <p>
4734      * As a memory optimizing technique an empty array passed in will be overridden with
4735      * the empty {@code public static} references in this class.
4736      * </p>
4737      *
4738      * @param array  the array to check for {@code null} or empty.
4739      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4740      * @since 2.5
4741      */
4742     public static double[] nullToEmpty(final double[] array) {
4743         return isEmpty(array) ? EMPTY_DOUBLE_ARRAY : array;
4744     }
4745 
4746     /**
4747      * Defensive programming technique to change a {@code null}
4748      * reference to an empty one.
4749      * <p>
4750      * This method returns an empty array for a {@code null} input array.
4751      * </p>
4752      * <p>
4753      * As a memory optimizing technique an empty array passed in will be overridden with
4754      * the empty {@code public static} references in this class.
4755      * </p>
4756      *
4757      * @param array  the array to check for {@code null} or empty.
4758      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4759      * @since 2.5
4760      */
4761     public static Double[] nullToEmpty(final Double[] array) {
4762         return nullTo(array, EMPTY_DOUBLE_OBJECT_ARRAY);
4763     }
4764 
4765     /**
4766      * Defensive programming technique to change a {@code null}
4767      * reference to an empty one.
4768      * <p>
4769      * This method returns an empty array for a {@code null} input array.
4770      * </p>
4771      * <p>
4772      * As a memory optimizing technique an empty array passed in will be overridden with
4773      * the empty {@code public static} references in this class.
4774      * </p>
4775      *
4776      * @param array  the array to check for {@code null} or empty.
4777      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4778      * @since 2.5
4779      */
4780     public static float[] nullToEmpty(final float[] array) {
4781         return isEmpty(array) ? EMPTY_FLOAT_ARRAY : array;
4782     }
4783 
4784     /**
4785      * Defensive programming technique to change a {@code null}
4786      * reference to an empty one.
4787      * <p>
4788      * This method returns an empty array for a {@code null} input array.
4789      * </p>
4790      * <p>
4791      * As a memory optimizing technique an empty array passed in will be overridden with
4792      * the empty {@code public static} references in this class.
4793      * </p>
4794      *
4795      * @param array  the array to check for {@code null} or empty.
4796      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4797      * @since 2.5
4798      */
4799     public static Float[] nullToEmpty(final Float[] array) {
4800         return nullTo(array, EMPTY_FLOAT_OBJECT_ARRAY);
4801     }
4802 
4803     /**
4804      * Defensive programming technique to change a {@code null}
4805      * reference to an empty one.
4806      * <p>
4807      * This method returns an empty array for a {@code null} input array.
4808      * </p>
4809      * <p>
4810      * As a memory optimizing technique an empty array passed in will be overridden with
4811      * the empty {@code public static} references in this class.
4812      * </p>
4813      *
4814      * @param array  the array to check for {@code null} or empty.
4815      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4816      * @since 2.5
4817      */
4818     public static int[] nullToEmpty(final int[] array) {
4819         return isEmpty(array) ? EMPTY_INT_ARRAY : array;
4820     }
4821 
4822     /**
4823      * Defensive programming technique to change a {@code null}
4824      * reference to an empty one.
4825      * <p>
4826      * This method returns an empty array for a {@code null} input array.
4827      * </p>
4828      * <p>
4829      * As a memory optimizing technique an empty array passed in will be overridden with
4830      * the empty {@code public static} references in this class.
4831      * </p>
4832      *
4833      * @param array  the array to check for {@code null} or empty.
4834      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4835      * @since 2.5
4836      */
4837     public static Integer[] nullToEmpty(final Integer[] array) {
4838         return nullTo(array, EMPTY_INTEGER_OBJECT_ARRAY);
4839     }
4840 
4841     /**
4842      * Defensive programming technique to change a {@code null}
4843      * reference to an empty one.
4844      * <p>
4845      * This method returns an empty array for a {@code null} input array.
4846      * </p>
4847      * <p>
4848      * As a memory optimizing technique an empty array passed in will be overridden with
4849      * the empty {@code public static} references in this class.
4850      * </p>
4851      *
4852      * @param array  the array to check for {@code null} or empty.
4853      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4854      * @since 2.5
4855      */
4856     public static long[] nullToEmpty(final long[] array) {
4857         return isEmpty(array) ? EMPTY_LONG_ARRAY : array;
4858     }
4859 
4860     /**
4861      * Defensive programming technique to change a {@code null}
4862      * reference to an empty one.
4863      * <p>
4864      * This method returns an empty array for a {@code null} input array.
4865      * </p>
4866      * <p>
4867      * As a memory optimizing technique an empty array passed in will be overridden with
4868      * the empty {@code public static} references in this class.
4869      * </p>
4870      *
4871      * @param array  the array to check for {@code null} or empty.
4872      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4873      * @since 2.5
4874      */
4875     public static Long[] nullToEmpty(final Long[] array) {
4876         return nullTo(array, EMPTY_LONG_OBJECT_ARRAY);
4877     }
4878 
4879     /**
4880      * Defensive programming technique to change a {@code null}
4881      * reference to an empty one.
4882      * <p>
4883      * This method returns an empty array for a {@code null} input array.
4884      * </p>
4885      * <p>
4886      * As a memory optimizing technique an empty array passed in will be overridden with
4887      * the empty {@code public static} references in this class.
4888      * </p>
4889      *
4890      * @param array  the array to check for {@code null} or empty.
4891      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4892      * @since 2.5
4893      */
4894     public static Object[] nullToEmpty(final Object[] array) {
4895         return nullTo(array, EMPTY_OBJECT_ARRAY);
4896     }
4897 
4898     /**
4899      * Defensive programming technique to change a {@code null}
4900      * reference to an empty one.
4901      * <p>
4902      * This method returns an empty array for a {@code null} input array.
4903      * </p>
4904      * <p>
4905      * As a memory optimizing technique an empty array passed in will be overridden with
4906      * the empty {@code public static} references in this class.
4907      * </p>
4908      *
4909      * @param array  the array to check for {@code null} or empty.
4910      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4911      * @since 2.5
4912      */
4913     public static short[] nullToEmpty(final short[] array) {
4914         return isEmpty(array) ? EMPTY_SHORT_ARRAY : array;
4915     }
4916 
4917     /**
4918      * Defensive programming technique to change a {@code null}
4919      * reference to an empty one.
4920      * <p>
4921      * This method returns an empty array for a {@code null} input array.
4922      * </p>
4923      * <p>
4924      * As a memory optimizing technique an empty array passed in will be overridden with
4925      * the empty {@code public static} references in this class.
4926      * </p>
4927      *
4928      * @param array  the array to check for {@code null} or empty.
4929      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4930      * @since 2.5
4931      */
4932     public static Short[] nullToEmpty(final Short[] array) {
4933         return nullTo(array, EMPTY_SHORT_OBJECT_ARRAY);
4934     }
4935 
4936     /**
4937      * Defensive programming technique to change a {@code null}
4938      * reference to an empty one.
4939      * <p>
4940      * This method returns an empty array for a {@code null} input array.
4941      * </p>
4942      * <p>
4943      * As a memory optimizing technique an empty array passed in will be overridden with
4944      * the empty {@code public static} references in this class.
4945      * </p>
4946      *
4947      * @param array  the array to check for {@code null} or empty.
4948      * @return the same array, {@code public static} empty array if {@code null} or empty input.
4949      * @since 2.5
4950      */
4951     public static String[] nullToEmpty(final String[] array) {
4952         return nullTo(array, EMPTY_STRING_ARRAY);
4953     }
4954 
4955     /**
4956      * Defensive programming technique to change a {@code null}
4957      * reference to an empty one.
4958      * <p>
4959      * This method returns an empty array for a {@code null} input array.
4960      * </p>
4961      *
4962      * @param array  the array to check for {@code null} or empty.
4963      * @param type   the class representation of the desired array.
4964      * @param <T>  the class type.
4965      * @return the same array, {@code public static} empty array if {@code null}.
4966      * @throws IllegalArgumentException if the type argument is null.
4967      * @since 3.5
4968      */
4969     public static <T> T[] nullToEmpty(final T[] array, final Class<T[]> type) {
4970         if (type == null) {
4971             throw new IllegalArgumentException("The type must not be null");
4972         }
4973         if (array == null) {
4974             return type.cast(Array.newInstance(type.getComponentType(), 0));
4975         }
4976         return array;
4977     }
4978 
4979     /**
4980      * Gets the {@link ThreadLocalRandom} for {@code shuffle} methods that don't take a {@link Random} argument.
4981      *
4982      * @return the current ThreadLocalRandom.
4983      */
4984     private static ThreadLocalRandom random() {
4985         return ThreadLocalRandom.current();
4986     }
4987 
4988     /**
4989      * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
4990      * indices).
4991      * <p>
4992      * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
4993      * returned array is always the same as that of the input array.
4994      * </p>
4995      * <p>
4996      * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
4997      * </p>
4998      *
4999      * <pre>
5000      * ArrayUtils.remove([true], 0)              = []
5001      * ArrayUtils.remove([true, false], 0)       = [false]
5002      * ArrayUtils.remove([true, false], 1)       = [true]
5003      * ArrayUtils.remove([true, true, false], 1) = [true, false]
5004      * </pre>
5005      *
5006      * @param array the array to remove the element from, may not be {@code null}.
5007      * @param index the position of the element to be removed.
5008      * @return A new array containing the existing elements except the element at the specified position.
5009      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5010      * @since 2.1
5011      */
5012     public static boolean[] remove(final boolean[] array, final int index) {
5013         return (boolean[]) remove((Object) array, index);
5014     }
5015 
5016     /**
5017      * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5018      * indices).
5019      * <p>
5020      * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5021      * returned array is always the same as that of the input array.
5022      * </p>
5023      * <p>
5024      * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5025      * </p>
5026      *
5027      * <pre>
5028      * ArrayUtils.remove([1], 0)          = []
5029      * ArrayUtils.remove([1, 0], 0)       = [0]
5030      * ArrayUtils.remove([1, 0], 1)       = [1]
5031      * ArrayUtils.remove([1, 0, 1], 1)    = [1, 1]
5032      * </pre>
5033      *
5034      * @param array the array to remove the element from, may not be {@code null}.
5035      * @param index the position of the element to be removed.
5036      * @return A new array containing the existing elements except the element at the specified position.
5037      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5038      * @since 2.1
5039      */
5040     public static byte[] remove(final byte[] array, final int index) {
5041         return (byte[]) remove((Object) array, index);
5042     }
5043 
5044     /**
5045      * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5046      * indices).
5047      * <p>
5048      * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5049      * returned array is always the same as that of the input array.
5050      * </p>
5051      * <p>
5052      * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5053      * </p>
5054      *
5055      * <pre>
5056      * ArrayUtils.remove(['a'], 0)           = []
5057      * ArrayUtils.remove(['a', 'b'], 0)      = ['b']
5058      * ArrayUtils.remove(['a', 'b'], 1)      = ['a']
5059      * ArrayUtils.remove(['a', 'b', 'c'], 1) = ['a', 'c']
5060      * </pre>
5061      *
5062      * @param array the array to remove the element from, may not be {@code null}.
5063      * @param index the position of the element to be removed.
5064      * @return A new array containing the existing elements except the element at the specified position.
5065      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5066      * @since 2.1
5067      */
5068     public static char[] remove(final char[] array, final int index) {
5069         return (char[]) remove((Object) array, index);
5070     }
5071 
5072     /**
5073      * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5074      * indices).
5075      * <p>
5076      * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5077      * returned array is always the same as that of the input array.
5078      * </p>
5079      * <p>
5080      * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5081      * </p>
5082      *
5083      * <pre>
5084      * ArrayUtils.remove([1.1], 0)           = []
5085      * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
5086      * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
5087      * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
5088      * </pre>
5089      *
5090      * @param array the array to remove the element from, may not be {@code null}.
5091      * @param index the position of the element to be removed.
5092      * @return A new array containing the existing elements except the element at the specified position.
5093      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5094      * @since 2.1
5095      */
5096     public static double[] remove(final double[] array, final int index) {
5097         return (double[]) remove((Object) array, index);
5098     }
5099 
5100     /**
5101      * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5102      * indices).
5103      * <p>
5104      * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5105      * returned array is always the same as that of the input array.
5106      * </p>
5107      * <p>
5108      * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5109      * </p>
5110      *
5111      * <pre>
5112      * ArrayUtils.remove([1.1], 0)           = []
5113      * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
5114      * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
5115      * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
5116      * </pre>
5117      *
5118      * @param array the array to remove the element from, may not be {@code null}.
5119      * @param index the position of the element to be removed.
5120      * @return A new array containing the existing elements except the element at the specified position.
5121      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5122      * @since 2.1
5123      */
5124     public static float[] remove(final float[] array, final int index) {
5125         return (float[]) remove((Object) array, index);
5126     }
5127 
5128     /**
5129      * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5130      * indices).
5131      * <p>
5132      * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5133      * returned array is always the same as that of the input array.
5134      * </p>
5135      * <p>
5136      * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5137      * </p>
5138      *
5139      * <pre>
5140      * ArrayUtils.remove([1], 0)         = []
5141      * ArrayUtils.remove([2, 6], 0)      = [6]
5142      * ArrayUtils.remove([2, 6], 1)      = [2]
5143      * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
5144      * </pre>
5145      *
5146      * @param array the array to remove the element from, may not be {@code null}.
5147      * @param index the position of the element to be removed.
5148      * @return A new array containing the existing elements except the element at the specified position.
5149      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5150      * @since 2.1
5151      */
5152     public static int[] remove(final int[] array, final int index) {
5153         return (int[]) remove((Object) array, index);
5154     }
5155 
5156     /**
5157      * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5158      * indices).
5159      * <p>
5160      * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5161      * returned array is always the same as that of the input array.
5162      * </p>
5163      * <p>
5164      * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5165      * </p>
5166      *
5167      * <pre>
5168      * ArrayUtils.remove([1], 0)         = []
5169      * ArrayUtils.remove([2, 6], 0)      = [6]
5170      * ArrayUtils.remove([2, 6], 1)      = [2]
5171      * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
5172      * </pre>
5173      *
5174      * @param array the array to remove the element from, may not be {@code null}.
5175      * @param index the position of the element to be removed.
5176      * @return A new array containing the existing elements except the element at the specified position.
5177      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5178      * @since 2.1
5179      */
5180     public static long[] remove(final long[] array, final int index) {
5181         return (long[]) remove((Object) array, index);
5182     }
5183 
5184     /**
5185      * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5186      * indices).
5187      * <p>
5188      * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5189      * returned array is always the same as that of the input array.
5190      * </p>
5191      * <p>
5192      * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5193      * </p>
5194      *
5195      * @param array the array to remove the element from, may not be {@code null}.
5196      * @param index the position of the element to be removed.
5197      * @return A new array containing the existing elements except the element at the specified position.
5198      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5199      * @since 2.1
5200      */
5201     private static Object remove(final Object array, final int index) {
5202         final int length = getLength(array);
5203         if (index < 0 || index >= length) {
5204             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
5205         }
5206         final Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
5207         System.arraycopy(array, 0, result, 0, index);
5208         if (index < length - 1) {
5209             System.arraycopy(array, index + 1, result, index, length - index - 1);
5210         }
5211         return result;
5212     }
5213 
5214     /**
5215      * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5216      * indices).
5217      * <p>
5218      * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5219      * returned array is always the same as that of the input array.
5220      * </p>
5221      * <p>
5222      * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5223      * </p>
5224      *
5225      * <pre>
5226      * ArrayUtils.remove([1], 0)         = []
5227      * ArrayUtils.remove([2, 6], 0)      = [6]
5228      * ArrayUtils.remove([2, 6], 1)      = [2]
5229      * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
5230      * </pre>
5231      *
5232      * @param array the array to remove the element from, may not be {@code null}.
5233      * @param index the position of the element to be removed.
5234      * @return A new array containing the existing elements except the element at the specified position.
5235      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5236      * @since 2.1
5237      */
5238     public static short[] remove(final short[] array, final int index) {
5239         return (short[]) remove((Object) array, index);
5240     }
5241 
5242     /**
5243      * Removes the element at the specified position from the specified array. All subsequent elements are shifted to the left (subtracts one from their
5244      * indices).
5245      * <p>
5246      * This method returns a new array with the same elements of the input array except the element on the specified position. The component type of the
5247      * returned array is always the same as that of the input array.
5248      * </p>
5249      * <p>
5250      * If the input array is {@code null}, an IndexOutOfBoundsException will be thrown, because in that case no valid index can be specified.
5251      * </p>
5252      *
5253      * <pre>
5254      * ArrayUtils.remove(["a"], 0)           = []
5255      * ArrayUtils.remove(["a", "b"], 0)      = ["b"]
5256      * ArrayUtils.remove(["a", "b"], 1)      = ["a"]
5257      * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"]
5258      * </pre>
5259      *
5260      * @param <T>   the component type of the array.
5261      * @param array the array to remove the element from, may not be {@code null}.
5262      * @param index the position of the element to be removed.
5263      * @return A new array containing the existing elements except the element at the specified position.
5264      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5265      * @since 2.1
5266      */
5267     @SuppressWarnings("unchecked") // remove() always creates an array of the same type as its input
5268     public static <T> T[] remove(final T[] array, final int index) {
5269         return (T[]) remove((Object) array, index);
5270     }
5271 
5272     /**
5273      * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5274      * <p>
5275      * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5276      * array is always the same as that of the input array.
5277      * </p>
5278      * <p>
5279      * If the input array is {@code null}, then return {@code null}.
5280      * </p>
5281      *
5282      * <pre>
5283      * ArrayUtils.removeAll([true, false, true], 0, 2) = [false]
5284      * ArrayUtils.removeAll([true, false, true], 1, 2) = [true]
5285      * </pre>
5286      *
5287      * @param array   the array to remove the element from, may not be {@code null}.
5288      * @param indices the positions of the elements to be removed.
5289      * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5290      * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5291      * @since 3.0.1
5292      */
5293     public static boolean[] removeAll(final boolean[] array, final int... indices) {
5294         return (boolean[]) removeAll((Object) array, indices);
5295     }
5296 
5297     /**
5298      * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5299      * <p>
5300      * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5301      * array is always the same as that of the input array.
5302      * </p>
5303      * <p>
5304      * If the input array is {@code null}, then return {@code null}.
5305      * </p>
5306      *
5307      * <pre>
5308      * ArrayUtils.removeAll([1], 0)             = []
5309      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5310      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5311      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5312      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5313      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5314      * </pre>
5315      *
5316      * @param array   the array to remove the element from, may not be {@code null}.
5317      * @param indices the positions of the elements to be removed.
5318      * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5319      * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5320      * @since 3.0.1
5321      */
5322     public static byte[] removeAll(final byte[] array, final int... indices) {
5323         return (byte[]) removeAll((Object) array, indices);
5324     }
5325 
5326     /**
5327      * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5328      * <p>
5329      * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5330      * array is always the same as that of the input array.
5331      * </p>
5332      * <p>
5333      * If the input array is {@code null}, then return {@code null}.
5334      * </p>
5335      *
5336      * <pre>
5337      * ArrayUtils.removeAll([1], 0)             = []
5338      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5339      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5340      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5341      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5342      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5343      * </pre>
5344      *
5345      * @param array   the array to remove the element from, may not be {@code null}.
5346      * @param indices the positions of the elements to be removed.
5347      * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5348      * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5349      * @since 3.0.1
5350      */
5351     public static char[] removeAll(final char[] array, final int... indices) {
5352         return (char[]) removeAll((Object) array, indices);
5353     }
5354 
5355     /**
5356      * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5357      * <p>
5358      * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5359      * array is always the same as that of the input array.
5360      * </p>
5361      * <p>
5362      * If the input array is {@code null}, then return {@code null}.
5363      * </p>
5364      *
5365      * <pre>
5366      * ArrayUtils.removeAll([1], 0)             = []
5367      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5368      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5369      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5370      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5371      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5372      * </pre>
5373      *
5374      * @param array   the array to remove the element from, may not be {@code null}.
5375      * @param indices the positions of the elements to be removed.
5376      * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5377      * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5378      * @since 3.0.1
5379      */
5380     public static double[] removeAll(final double[] array, final int... indices) {
5381         return (double[]) removeAll((Object) array, indices);
5382     }
5383 
5384     /**
5385      * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5386      * <p>
5387      * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5388      * array is always the same as that of the input array.
5389      * </p>
5390      * <p>
5391      * If the input array is {@code null}, then return {@code null}.
5392      * </p>
5393      *
5394      * <pre>
5395      * ArrayUtils.removeAll([1], 0)             = []
5396      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5397      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5398      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5399      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5400      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5401      * </pre>
5402      *
5403      * @param array   the array to remove the element from, may not be {@code null}.
5404      * @param indices the positions of the elements to be removed.
5405      * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5406      * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5407      * @since 3.0.1
5408      */
5409     public static float[] removeAll(final float[] array, final int... indices) {
5410         return (float[]) removeAll((Object) array, indices);
5411     }
5412 
5413     /**
5414      * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5415      * <p>
5416      * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5417      * array is always the same as that of the input array.
5418      * </p>
5419      * <p>
5420      * If the input array is {@code null}, then return {@code null}.
5421      * </p>
5422      *
5423      * <pre>
5424      * ArrayUtils.removeAll([1], 0)             = []
5425      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5426      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5427      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5428      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5429      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5430      * </pre>
5431      *
5432      * @param array   the array to remove the element from, may not be {@code null}.
5433      * @param indices the positions of the elements to be removed.
5434      * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5435      * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5436      * @since 3.0.1
5437      */
5438     public static int[] removeAll(final int[] array, final int... indices) {
5439         return (int[]) removeAll((Object) array, indices);
5440     }
5441 
5442     /**
5443      * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5444      * <p>
5445      * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5446      * array is always the same as that of the input array.
5447      * </p>
5448      * <p>
5449      * If the input array is {@code null}, then return {@code null}.
5450      * </p>
5451      *
5452      * <pre>
5453      * ArrayUtils.removeAll([1], 0)             = []
5454      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5455      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5456      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5457      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5458      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5459      * </pre>
5460      *
5461      * @param array   the array to remove the element from, may not be {@code null}.
5462      * @param indices the positions of the elements to be removed.
5463      * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5464      * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5465      * @since 3.0.1
5466      */
5467     public static long[] removeAll(final long[] array, final int... indices) {
5468         return (long[]) removeAll((Object) array, indices);
5469     }
5470 
5471     /**
5472      * Removes multiple array elements specified by index.
5473      *
5474      * @param array   source
5475      * @param indices to remove
5476      * @return new array of same type minus elements specified by unique values of {@code indices}
5477      */
5478     // package protected for access by unit tests
5479     static Object removeAll(final Object array, final int... indices) {
5480         if (array == null) {
5481             return null;
5482         }
5483         final int length = getLength(array);
5484         int diff = 0; // number of distinct indexes, i.e. number of entries that will be removed
5485         final int[] clonedIndices = ArraySorter.sort(clone(indices));
5486         // identify length of result array
5487         if (isNotEmpty(clonedIndices)) {
5488             int i = clonedIndices.length;
5489             int prevIndex = length;
5490             while (--i >= 0) {
5491                 final int index = clonedIndices[i];
5492                 if (index < 0 || index >= length) {
5493                     throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
5494                 }
5495                 if (index >= prevIndex) {
5496                     continue;
5497                 }
5498                 diff++;
5499                 prevIndex = index;
5500             }
5501         }
5502         // create result array
5503         final Object result = Array.newInstance(array.getClass().getComponentType(), length - diff);
5504         if (diff < length && clonedIndices != null) {
5505             int end = length; // index just after last copy
5506             int dest = length - diff; // number of entries so far not copied
5507             for (int i = clonedIndices.length - 1; i >= 0; i--) {
5508                 final int index = clonedIndices[i];
5509                 if (end - index > 1) { // same as (cp > 0)
5510                     final int cp = end - index - 1;
5511                     dest -= cp;
5512                     System.arraycopy(array, index + 1, result, dest, cp);
5513                     // After this copy, we still have room for dest items.
5514                 }
5515                 end = index;
5516             }
5517             if (end > 0) {
5518                 System.arraycopy(array, 0, result, 0, end);
5519             }
5520         }
5521         return result;
5522     }
5523 
5524     /**
5525      * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5526      * <p>
5527      * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5528      * array is always the same as that of the input array.
5529      * </p>
5530      * <p>
5531      * If the input array is {@code null}, then return {@code null}.
5532      * </p>
5533      *
5534      * <pre>
5535      * ArrayUtils.removeAll([1], 0)             = []
5536      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5537      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5538      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5539      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5540      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5541      * </pre>
5542      *
5543      * @param array   the array to remove the element from, may not be {@code null}.
5544      * @param indices the positions of the elements to be removed.
5545      * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5546      * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5547      * @since 3.0.1
5548      */
5549     public static short[] removeAll(final short[] array, final int... indices) {
5550         return (short[]) removeAll((Object) array, indices);
5551     }
5552 
5553     /**
5554      * Removes the elements at the specified positions from the specified array. All remaining elements are shifted to the left.
5555      * <p>
5556      * This method returns a new array with the same elements of the input array except those at the specified positions. The component type of the returned
5557      * array is always the same as that of the input array.
5558      * </p>
5559      * <p>
5560      * If the input array is {@code null}, then return {@code null}.
5561      * </p>
5562      *
5563      * <pre>
5564      * ArrayUtils.removeAll(["a", "b", "c"], 0, 2) = ["b"]
5565      * ArrayUtils.removeAll(["a", "b", "c"], 1, 2) = ["a"]
5566      * </pre>
5567      *
5568      * @param <T>     the component type of the array.
5569      * @param array   the array to remove the element from, may not be {@code null}.
5570      * @param indices the positions of the elements to be removed.
5571      * @return A new array containing the existing elements except those at the specified positions or {@code null} if the input array is {@code null}.
5572      * @throws IndexOutOfBoundsException if any index is out of range (index &lt; 0 || index &gt;= array.length).
5573      * @since 3.0.1
5574      */
5575     @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
5576     public static <T> T[] removeAll(final T[] array, final int... indices) {
5577         return (T[]) removeAll((Object) array, indices);
5578     }
5579 
5580     /**
5581      * Removes the occurrences of the specified element from the specified boolean array.
5582      * <p>
5583      * All subsequent elements are shifted to the left (subtracts one from their indices).
5584      * If the array doesn't contain such an element, no elements are removed from the array.
5585      * {@code null} will be returned if the input array is {@code null}.
5586      * </p>
5587      *
5588      * @param array the input array, will not be modified, and may be {@code null}.
5589      * @param element the element to remove.
5590      * @return A new array containing the existing elements except the occurrences of the specified element.
5591      * @since 3.5
5592      * @deprecated Use {@link #removeAllOccurrences(boolean[], boolean)}.
5593      */
5594     @Deprecated
5595     public static boolean[] removeAllOccurences(final boolean[] array, final boolean element) {
5596         return (boolean[]) removeAt(array, indexesOf(array, element));
5597     }
5598 
5599     /**
5600      * Removes the occurrences of the specified element from the specified byte array.
5601      * <p>
5602      * All subsequent elements are shifted to the left (subtracts one from their indices).
5603      * If the array doesn't contain such an element, no elements are removed from the array.
5604      * {@code null} will be returned if the input array is {@code null}.
5605      * </p>
5606      *
5607      * @param array the input array, will not be modified, and may be {@code null}.
5608      * @param element the element to remove.
5609      * @return A new array containing the existing elements except the occurrences of the specified element.
5610      * @since 3.5
5611      * @deprecated Use {@link #removeAllOccurrences(byte[], byte)}.
5612      */
5613     @Deprecated
5614     public static byte[] removeAllOccurences(final byte[] array, final byte element) {
5615         return (byte[]) removeAt(array, indexesOf(array, element));
5616     }
5617 
5618     /**
5619      * Removes the occurrences of the specified element from the specified char array.
5620      * <p>
5621      * All subsequent elements are shifted to the left (subtracts one from their indices).
5622      * If the array doesn't contain such an element, no elements are removed from the array.
5623      * {@code null} will be returned if the input array is {@code null}.
5624      * </p>
5625      *
5626      * @param array the input array, will not be modified, and may be {@code null}.
5627      * @param element the element to remove.
5628      * @return A new array containing the existing elements except the occurrences of the specified element.
5629      * @since 3.5
5630      * @deprecated Use {@link #removeAllOccurrences(char[], char)}.
5631      */
5632     @Deprecated
5633     public static char[] removeAllOccurences(final char[] array, final char element) {
5634         return (char[]) removeAt(array, indexesOf(array, element));
5635     }
5636 
5637     /**
5638      * Removes the occurrences of the specified element from the specified double array.
5639      * <p>
5640      * All subsequent elements are shifted to the left (subtracts one from their indices).
5641      * If the array doesn't contain such an element, no elements are removed from the array.
5642      * {@code null} will be returned if the input array is {@code null}.
5643      * </p>
5644      *
5645      * @param array the input array, will not be modified, and may be {@code null}.
5646      * @param element the element to remove.
5647      * @return A new array containing the existing elements except the occurrences of the specified element.
5648      * @since 3.5
5649      * @deprecated Use {@link #removeAllOccurrences(double[], double)}.
5650      */
5651     @Deprecated
5652     public static double[] removeAllOccurences(final double[] array, final double element) {
5653         return (double[]) removeAt(array, indexesOf(array, element));
5654     }
5655 
5656     /**
5657      * Removes the occurrences of the specified element from the specified float array.
5658      * <p>
5659      * All subsequent elements are shifted to the left (subtracts one from their indices).
5660      * If the array doesn't contain such an element, no elements are removed from the array.
5661      * {@code null} will be returned if the input array is {@code null}.
5662      * </p>
5663      *
5664      * @param array the input array, will not be modified, and may be {@code null}.
5665      * @param element the element to remove.
5666      * @return A new array containing the existing elements except the occurrences of the specified element.
5667      * @since 3.5
5668      * @deprecated Use {@link #removeAllOccurrences(float[], float)}.
5669      */
5670     @Deprecated
5671     public static float[] removeAllOccurences(final float[] array, final float element) {
5672         return (float[]) removeAt(array, indexesOf(array, element));
5673     }
5674 
5675     /**
5676      * Removes the occurrences of the specified element from the specified int array.
5677      * <p>
5678      * All subsequent elements are shifted to the left (subtracts one from their indices).
5679      * If the array doesn't contain such an element, no elements are removed from the array.
5680      * {@code null} will be returned if the input array is {@code null}.
5681      * </p>
5682      *
5683      * @param array the input array, will not be modified, and may be {@code null}.
5684      * @param element the element to remove.
5685      * @return A new array containing the existing elements except the occurrences of the specified element.
5686      * @since 3.5
5687      * @deprecated Use {@link #removeAllOccurrences(int[], int)}.
5688      */
5689     @Deprecated
5690     public static int[] removeAllOccurences(final int[] array, final int element) {
5691         return (int[]) removeAt(array, indexesOf(array, element));
5692     }
5693 
5694     /**
5695      * Removes the occurrences of the specified element from the specified long array.
5696      * <p>
5697      * All subsequent elements are shifted to the left (subtracts one from their indices).
5698      * If the array doesn't contain such an element, no elements are removed from the array.
5699      * {@code null} will be returned if the input array is {@code null}.
5700      * </p>
5701      *
5702      * @param array the input array, will not be modified, and may be {@code null}.
5703      * @param element the element to remove.
5704      * @return A new array containing the existing elements except the occurrences of the specified element.
5705      * @since 3.5
5706      * @deprecated Use {@link #removeAllOccurrences(long[], long)}.
5707      */
5708     @Deprecated
5709     public static long[] removeAllOccurences(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.5
5725      * @deprecated Use {@link #removeAllOccurrences(short[], short)}.
5726      */
5727     @Deprecated
5728     public static short[] removeAllOccurences(final short[] array, final short element) {
5729         return (short[]) removeAt(array, indexesOf(array, element));
5730     }
5731 
5732     /**
5733      * Removes the occurrences of the specified element from the specified array.
5734      * <p>
5735      * All subsequent elements are shifted to the left (subtracts one from their indices).
5736      * If the array doesn't contain such an element, no elements are removed from the array.
5737      * {@code null} will be returned if the input array is {@code null}.
5738      * </p>
5739      *
5740      * @param <T> the type of object in the array, may be {@code null}.
5741      * @param array the input array, will not be modified, and may be {@code null}.
5742      * @param element the element to remove, may be {@code null}.
5743      * @return A new array containing the existing elements except the occurrences of the specified element.
5744      * @since 3.5
5745      * @deprecated Use {@link #removeAllOccurrences(Object[], Object)}.
5746      */
5747     @Deprecated
5748     public static <T> T[] removeAllOccurences(final T[] array, final T element) {
5749         return (T[]) removeAt(array, indexesOf(array, element));
5750     }
5751 
5752     /**
5753      * Removes the occurrences of the specified element from the specified boolean array.
5754      * <p>
5755      * All subsequent elements are shifted to the left (subtracts one from their indices).
5756      * If the array doesn't contain such an element, no elements are removed from the array.
5757      * {@code null} will be returned if the input array is {@code null}.
5758      * </p>
5759      *
5760      * @param array the input array, will not be modified, and may be {@code null}.
5761      * @param element the element to remove.
5762      * @return A new array containing the existing elements except the occurrences of the specified element.
5763      * @since 3.10
5764      */
5765     public static boolean[] removeAllOccurrences(final boolean[] array, final boolean element) {
5766         return (boolean[]) removeAt(array, indexesOf(array, element));
5767     }
5768 
5769     /**
5770      * Removes the occurrences of the specified element from the specified byte array.
5771      * <p>
5772      * All subsequent elements are shifted to the left (subtracts one from their indices).
5773      * If the array doesn't contain such an element, no elements are removed from the array.
5774      * {@code null} will be returned if the input array is {@code null}.
5775      * </p>
5776      *
5777      * @param array the input array, will not be modified, and may be {@code null}.
5778      * @param element the element to remove.
5779      * @return A new array containing the existing elements except the occurrences of the specified element.
5780      * @since 3.10
5781      */
5782     public static byte[] removeAllOccurrences(final byte[] array, final byte element) {
5783         return (byte[]) removeAt(array, indexesOf(array, element));
5784     }
5785 
5786     /**
5787      * Removes the occurrences of the specified element from the specified char array.
5788      * <p>
5789      * All subsequent elements are shifted to the left (subtracts one from their indices).
5790      * If the array doesn't contain such an element, no elements are removed from the array.
5791      * {@code null} will be returned if the input array is {@code null}.
5792      * </p>
5793      *
5794      * @param array the input array, will not be modified, and may be {@code null}.
5795      * @param element the element to remove.
5796      * @return A new array containing the existing elements except the occurrences of the specified element.
5797      * @since 3.10
5798      */
5799     public static char[] removeAllOccurrences(final char[] array, final char element) {
5800         return (char[]) removeAt(array, indexesOf(array, element));
5801     }
5802 
5803     /**
5804      * Removes the occurrences of the specified element from the specified double array.
5805      * <p>
5806      * All subsequent elements are shifted to the left (subtracts one from their indices).
5807      * If the array doesn't contain such an element, no elements are removed from the array.
5808      * {@code null} will be returned if the input array is {@code null}.
5809      * </p>
5810      *
5811      * @param array the input array, will not be modified, and may be {@code null}.
5812      * @param element the element to remove.
5813      * @return A new array containing the existing elements except the occurrences of the specified element.
5814      * @since 3.10
5815      */
5816     public static double[] removeAllOccurrences(final double[] array, final double element) {
5817         return (double[]) removeAt(array, indexesOf(array, element));
5818     }
5819 
5820     /**
5821      * Removes the occurrences of the specified element from the specified float array.
5822      * <p>
5823      * All subsequent elements are shifted to the left (subtracts one from their indices).
5824      * If the array doesn't contain such an element, no elements are removed from the array.
5825      * {@code null} will be returned if the input array is {@code null}.
5826      * </p>
5827      *
5828      * @param array the input array, will not be modified, and may be {@code null}.
5829      * @param element the element to remove.
5830      * @return A new array containing the existing elements except the occurrences of the specified element.
5831      * @since 3.10
5832      */
5833     public static float[] removeAllOccurrences(final float[] array, final float element) {
5834         return (float[]) removeAt(array, indexesOf(array, element));
5835     }
5836 
5837     /**
5838      * Removes the occurrences of the specified element from the specified int array.
5839      * <p>
5840      * All subsequent elements are shifted to the left (subtracts one from their indices).
5841      * If the array doesn't contain such an element, no elements are removed from the array.
5842      * {@code null} will be returned if the input array is {@code null}.
5843      * </p>
5844      *
5845      * @param array the input array, will not be modified, and may be {@code null}.
5846      * @param element the element to remove.
5847      * @return A new array containing the existing elements except the occurrences of the specified element.
5848      * @since 3.10
5849      */
5850     public static int[] removeAllOccurrences(final int[] array, final int element) {
5851         return (int[]) removeAt(array, indexesOf(array, element));
5852     }
5853 
5854     /**
5855      * Removes the occurrences of the specified element from the specified long array.
5856      * <p>
5857      * All subsequent elements are shifted to the left (subtracts one from their indices).
5858      * If the array doesn't contain such an element, no elements are removed from the array.
5859      * {@code null} will be returned if the input array is {@code null}.
5860      * </p>
5861      *
5862      * @param array the input array, will not be modified, and may be {@code null}.
5863      * @param element the element to remove.
5864      * @return A new array containing the existing elements except the occurrences of the specified element.
5865      * @since 3.10
5866      */
5867     public static long[] removeAllOccurrences(final long[] array, final long element) {
5868         return (long[]) removeAt(array, indexesOf(array, element));
5869     }
5870 
5871     /**
5872      * Removes the occurrences of the specified element from the specified short array.
5873      * <p>
5874      * All subsequent elements are shifted to the left (subtracts one from their indices).
5875      * If the array doesn't contain such an element, no elements are removed from the array.
5876      * {@code null} will be returned if the input array is {@code null}.
5877      * </p>
5878      *
5879      * @param array the input array, will not be modified, and may be {@code null}.
5880      * @param element the element to remove.
5881      * @return A new array containing the existing elements except the occurrences of the specified element.
5882      * @since 3.10
5883      */
5884     public static short[] removeAllOccurrences(final short[] array, final short element) {
5885         return (short[]) removeAt(array, indexesOf(array, element));
5886     }
5887 
5888     /**
5889      * Removes the occurrences of the specified element from the specified array.
5890      * <p>
5891      * All subsequent elements are shifted to the left (subtracts one from their indices).
5892      * If the array doesn't contain such an element, no elements are removed from the array.
5893      * {@code null} will be returned if the input array is {@code null}.
5894      * </p>
5895      *
5896      * @param <T> the type of object in the array, may be {@code null}.
5897      * @param array the input array, will not be modified, and may be {@code null}.
5898      * @param element the element to remove, may be {@code null}.
5899      * @return A new array containing the existing elements except the occurrences of the specified element.
5900      * @since 3.10
5901      */
5902     public static <T> T[] removeAllOccurrences(final T[] array, final T element) {
5903         return (T[]) removeAt(array, indexesOf(array, element));
5904     }
5905 
5906     /**
5907      * Removes multiple array elements specified by indices.
5908      *
5909      * @param array the input array, will not be modified, and may be {@code null}.
5910      * @param indices to remove.
5911      * @return new array of same type minus elements specified by the set bits in {@code indices}.
5912      */
5913     // package protected for access by unit tests
5914     static Object removeAt(final Object array, final BitSet indices) {
5915         if (array == null) {
5916             return null;
5917         }
5918         final int srcLength = getLength(array);
5919         // No need to check maxIndex here, because method only currently called from removeElements()
5920         // which guarantee to generate only valid bit entries.
5921 //        final int maxIndex = indices.length();
5922 //        if (maxIndex > srcLength) {
5923 //            throw new IndexOutOfBoundsException("Index: " + (maxIndex-1) + ", Length: " + srcLength);
5924 //        }
5925         final int removals = indices.cardinality(); // true bits are items to remove
5926         final Object result = Array.newInstance(array.getClass().getComponentType(), srcLength - removals);
5927         int srcIndex = 0;
5928         int destIndex = 0;
5929         int count;
5930         int set;
5931         while ((set = indices.nextSetBit(srcIndex)) != -1) {
5932             count = set - srcIndex;
5933             if (count > 0) {
5934                 System.arraycopy(array, srcIndex, result, destIndex, count);
5935                 destIndex += count;
5936             }
5937             srcIndex = indices.nextClearBit(set);
5938         }
5939         count = srcLength - srcIndex;
5940         if (count > 0) {
5941             System.arraycopy(array, srcIndex, result, destIndex, count);
5942         }
5943         return result;
5944     }
5945 
5946     /**
5947      * Removes the first occurrence of the specified element from the
5948      * specified array. All subsequent elements are shifted to the left
5949      * (subtracts one from their indices). If the array doesn't contain
5950      * such an element, no elements are removed from the array.
5951      * <p>
5952      * This method returns a new array with the same elements of the input
5953      * array except the first occurrence of the specified element. The component
5954      * type of the returned array is always the same as that of the input
5955      * array.
5956      * </p>
5957      * <pre>
5958      * ArrayUtils.removeElement(null, true)                = null
5959      * ArrayUtils.removeElement([], true)                  = []
5960      * ArrayUtils.removeElement([true], false)             = [true]
5961      * ArrayUtils.removeElement([true, false], false)      = [true]
5962      * ArrayUtils.removeElement([true, false, true], true) = [false, true]
5963      * </pre>
5964      *
5965      * @param array the input array, may be {@code null}.
5966      * @param element  the element to be removed.
5967      * @return A new array containing the existing elements except the first
5968      *         occurrence of the specified element.
5969      * @since 2.1
5970      */
5971     public static boolean[] removeElement(final boolean[] array, final boolean element) {
5972         final int index = indexOf(array, element);
5973         return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
5974     }
5975 
5976     /**
5977      * Removes the first occurrence of the specified element from the
5978      * specified array. All subsequent elements are shifted to the left
5979      * (subtracts one from their indices). If the array doesn't contain
5980      * such an element, no elements are removed from the array.
5981      * <p>
5982      * This method returns a new array with the same elements of the input
5983      * array except the first occurrence of the specified element. The component
5984      * type of the returned array is always the same as that of the input
5985      * array.
5986      * </p>
5987      * <pre>
5988      * ArrayUtils.removeElement(null, 1)        = null
5989      * ArrayUtils.removeElement([], 1)          = []
5990      * ArrayUtils.removeElement([1], 0)         = [1]
5991      * ArrayUtils.removeElement([1, 0], 0)      = [1]
5992      * ArrayUtils.removeElement([1, 0, 1], 1)   = [0, 1]
5993      * </pre>
5994      *
5995      * @param array the input array, may be {@code null}.
5996      * @param element  the element to be removed.
5997      * @return A new array containing the existing elements except the first
5998      *         occurrence of the specified element.
5999      * @since 2.1
6000      */
6001     public static byte[] removeElement(final byte[] array, final byte element) {
6002         final int index = indexOf(array, element);
6003         return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6004     }
6005 
6006     /**
6007      * Removes the first occurrence of the specified element from the
6008      * specified array. All subsequent elements are shifted to the left
6009      * (subtracts one from their indices). If the array doesn't contain
6010      * such an element, no elements are removed from the array.
6011      * <p>
6012      * This method returns a new array with the same elements of the input
6013      * array except the first occurrence of the specified element. The component
6014      * type of the returned array is always the same as that of the input
6015      * array.
6016      * </p>
6017      * <pre>
6018      * ArrayUtils.removeElement(null, 'a')            = null
6019      * ArrayUtils.removeElement([], 'a')              = []
6020      * ArrayUtils.removeElement(['a'], 'b')           = ['a']
6021      * ArrayUtils.removeElement(['a', 'b'], 'a')      = ['b']
6022      * ArrayUtils.removeElement(['a', 'b', 'a'], 'a') = ['b', 'a']
6023      * </pre>
6024      *
6025      * @param array the input array, may be {@code null}.
6026      * @param element  the element to be removed.
6027      * @return A new array containing the existing elements except the first
6028      *         occurrence of the specified element.
6029      * @since 2.1
6030      */
6031     public static char[] removeElement(final char[] array, final char element) {
6032         final int index = indexOf(array, element);
6033         return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6034     }
6035 
6036     /**
6037      * Removes the first occurrence of the specified element from the
6038      * specified array. All subsequent elements are shifted to the left
6039      * (subtracts one from their indices). If the array doesn't contain
6040      * such an element, no elements are removed from the array.
6041      * <p>
6042      * This method returns a new array with the same elements of the input
6043      * array except the first occurrence of the specified element. The component
6044      * type of the returned array is always the same as that of the input
6045      * array.
6046      * </p>
6047      * <pre>
6048      * ArrayUtils.removeElement(null, 1.1)            = null
6049      * ArrayUtils.removeElement([], 1.1)              = []
6050      * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
6051      * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
6052      * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
6053      * </pre>
6054      *
6055      * @param array the input array, may be {@code null}.
6056      * @param element  the element to be removed.
6057      * @return A new array containing the existing elements except the first
6058      *         occurrence of the specified element.
6059      * @since 2.1
6060      */
6061     public static double[] removeElement(final double[] array, final double element) {
6062         final int index = indexOf(array, element);
6063         return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6064     }
6065 
6066     /**
6067      * Removes the first occurrence of the specified element from the
6068      * specified array. All subsequent elements are shifted to the left
6069      * (subtracts one from their indices). If the array doesn't contain
6070      * such an element, no elements are removed from the array.
6071      * <p>
6072      * This method returns a new array with the same elements of the input
6073      * array except the first occurrence of the specified element. The component
6074      * type of the returned array is always the same as that of the input
6075      * array.
6076      * </p>
6077      * <pre>
6078      * ArrayUtils.removeElement(null, 1.1)            = null
6079      * ArrayUtils.removeElement([], 1.1)              = []
6080      * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
6081      * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
6082      * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
6083      * </pre>
6084      *
6085      * @param array the input array, may be {@code null}.
6086      * @param element  the element to be removed.
6087      * @return A new array containing the existing elements except the first
6088      *         occurrence of the specified element.
6089      * @since 2.1
6090      */
6091     public static float[] removeElement(final float[] array, final float element) {
6092         final int index = indexOf(array, element);
6093         return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6094     }
6095 
6096     /**
6097      * Removes the first occurrence of the specified element from the
6098      * specified array. All subsequent elements are shifted to the left
6099      * (subtracts one from their indices). If the array doesn't contain
6100      * such an element, no elements are removed from the array.
6101      * <p>
6102      * This method returns a new array with the same elements of the input
6103      * array except the first occurrence of the specified element. The component
6104      * type of the returned array is always the same as that of the input
6105      * array.
6106      * </p>
6107      * <pre>
6108      * ArrayUtils.removeElement(null, 1)      = null
6109      * ArrayUtils.removeElement([], 1)        = []
6110      * ArrayUtils.removeElement([1], 2)       = [1]
6111      * ArrayUtils.removeElement([1, 3], 1)    = [3]
6112      * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
6113      * </pre>
6114      *
6115      * @param array the input array, may be {@code null}.
6116      * @param element  the element to be removed.
6117      * @return A new array containing the existing elements except the first
6118      *         occurrence of the specified element.
6119      * @since 2.1
6120      */
6121     public static int[] removeElement(final int[] array, final int element) {
6122         final int index = indexOf(array, element);
6123         return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6124     }
6125 
6126     /**
6127      * Removes the first occurrence of the specified element from the
6128      * specified array. All subsequent elements are shifted to the left
6129      * (subtracts one from their indices). If the array doesn't contain
6130      * such an element, no elements are removed from the array.
6131      * <p>
6132      * This method returns a new array with the same elements of the input
6133      * array except the first occurrence of the specified element. The component
6134      * type of the returned array is always the same as that of the input
6135      * array.
6136      * </p>
6137      * <pre>
6138      * ArrayUtils.removeElement(null, 1)      = null
6139      * ArrayUtils.removeElement([], 1)        = []
6140      * ArrayUtils.removeElement([1], 2)       = [1]
6141      * ArrayUtils.removeElement([1, 3], 1)    = [3]
6142      * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
6143      * </pre>
6144      *
6145      * @param array the input array, may be {@code null}.
6146      * @param element  the element to be removed.
6147      * @return A new array containing the existing elements except the first
6148      *         occurrence of the specified element.
6149      * @since 2.1
6150      */
6151     public static long[] removeElement(final long[] array, final long element) {
6152         final int index = indexOf(array, element);
6153         return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6154     }
6155 
6156     /**
6157      * Removes the first occurrence of the specified element from the
6158      * specified array. All subsequent elements are shifted to the left
6159      * (subtracts one from their indices). If the array doesn't contain
6160      * such an element, no elements are removed from the array.
6161      * <p>
6162      * This method returns a new array with the same elements of the input
6163      * array except the first occurrence of the specified element. The component
6164      * type of the returned array is always the same as that of the input
6165      * array.
6166      * </p>
6167      * <pre>
6168      * ArrayUtils.removeElement(null, 1)      = null
6169      * ArrayUtils.removeElement([], 1)        = []
6170      * ArrayUtils.removeElement([1], 2)       = [1]
6171      * ArrayUtils.removeElement([1, 3], 1)    = [3]
6172      * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
6173      * </pre>
6174      *
6175      * @param array the input array, may be {@code null}.
6176      * @param element  the element to be removed.
6177      * @return A new array containing the existing elements except the first
6178      *         occurrence of the specified element.
6179      * @since 2.1
6180      */
6181     public static short[] removeElement(final short[] array, final short element) {
6182         final int index = indexOf(array, element);
6183         return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6184     }
6185 
6186     /**
6187      * Removes the first occurrence of the specified element from the
6188      * specified array. All subsequent elements are shifted to the left
6189      * (subtracts one from their indices). If the array doesn't contain
6190      * such an element, no elements are removed from the array.
6191      * <p>
6192      * This method returns a new array with the same elements of the input
6193      * array except the first occurrence of the specified element. The component
6194      * type of the returned array is always the same as that of the input
6195      * array.
6196      * </p>
6197      * <pre>
6198      * ArrayUtils.removeElement(null, "a")            = null
6199      * ArrayUtils.removeElement([], "a")              = []
6200      * ArrayUtils.removeElement(["a"], "b")           = ["a"]
6201      * ArrayUtils.removeElement(["a", "b"], "a")      = ["b"]
6202      * ArrayUtils.removeElement(["a", "b", "a"], "a") = ["b", "a"]
6203      * </pre>
6204      *
6205      * @param <T> the component type of the array
6206      * @param array the input array, may be {@code null}.
6207      * @param element  the element to be removed, may be {@code null}.
6208      * @return A new array containing the existing elements except the first
6209      *         occurrence of the specified element.
6210      * @since 2.1
6211      */
6212     public static <T> T[] removeElement(final T[] array, final Object element) {
6213         final int index = indexOf(array, element);
6214         return index == INDEX_NOT_FOUND ? clone(array) : remove(array, index);
6215     }
6216 
6217     /**
6218      * Removes occurrences of specified elements, in specified quantities,
6219      * from the specified array. All subsequent elements are shifted left.
6220      * For any element-to-be-removed specified in greater quantities than
6221      * contained in the original array, no change occurs beyond the
6222      * removal of the existing matching items.
6223      * <p>
6224      * This method returns a new array with the same elements of the input
6225      * array except for the earliest-encountered occurrences of the specified
6226      * elements. The component type of the returned array is always the same
6227      * as that of the input array.
6228      * </p>
6229      * <pre>
6230      * ArrayUtils.removeElements(null, true, false)               = null
6231      * ArrayUtils.removeElements([], true, false)                 = []
6232      * ArrayUtils.removeElements([true], false, false)            = [true]
6233      * ArrayUtils.removeElements([true, false], true, true)       = [false]
6234      * ArrayUtils.removeElements([true, false, true], true)       = [false, true]
6235      * ArrayUtils.removeElements([true, false, true], true, true) = [false]
6236      * </pre>
6237      *
6238      * @param array the input array, will not be modified, and may be {@code null}.
6239      * @param values  the values to be removed.
6240      * @return A new array containing the existing elements except the
6241      *         earliest-encountered occurrences of the specified elements.
6242      * @since 3.0.1
6243      */
6244     public static boolean[] removeElements(final boolean[] array, final boolean... values) {
6245         if (isEmpty(array) || isEmpty(values)) {
6246             return clone(array);
6247         }
6248         final HashMap<Boolean, MutableInt> occurrences = new HashMap<>(2); // only two possible values here
6249         for (final boolean v : values) {
6250             increment(occurrences, Boolean.valueOf(v));
6251         }
6252         final BitSet toRemove = new BitSet();
6253         for (int i = 0; i < array.length; i++) {
6254             final boolean key = array[i];
6255             final MutableInt count = occurrences.get(key);
6256             if (count != null) {
6257                 if (count.decrementAndGet() == 0) {
6258                     occurrences.remove(key);
6259                 }
6260                 toRemove.set(i);
6261             }
6262         }
6263         return (boolean[]) removeAt(array, toRemove);
6264     }
6265 
6266     /**
6267      * Removes occurrences of specified elements, in specified quantities,
6268      * from the specified array. All subsequent elements are shifted left.
6269      * For any element-to-be-removed specified in greater quantities than
6270      * contained in the original array, no change occurs beyond the
6271      * removal of the existing matching items.
6272      * <p>
6273      * This method returns a new array with the same elements of the input
6274      * array except for the earliest-encountered occurrences of the specified
6275      * elements. The component type of the returned array is always the same
6276      * as that of the input array.
6277      * </p>
6278      * <pre>
6279      * ArrayUtils.removeElements(null, 1, 2)      = null
6280      * ArrayUtils.removeElements([], 1, 2)        = []
6281      * ArrayUtils.removeElements([1], 2, 3)       = [1]
6282      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6283      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6284      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6285      * </pre>
6286      *
6287      * @param array the input array, will not be modified, and may be {@code null}.
6288      * @param values  the values to be removed.
6289      * @return A new array containing the existing elements except the
6290      *         earliest-encountered occurrences of the specified elements.
6291      * @since 3.0.1
6292      */
6293     public static byte[] removeElements(final byte[] array, final byte... values) {
6294         if (isEmpty(array) || isEmpty(values)) {
6295             return clone(array);
6296         }
6297         final HashMap<Byte, MutableInt> occurrences = new HashMap<>(values.length);
6298         for (final byte v : values) {
6299             increment(occurrences, Byte.valueOf(v));
6300         }
6301         final BitSet toRemove = new BitSet();
6302         for (int i = 0; i < array.length; i++) {
6303             final byte key = array[i];
6304             final MutableInt count = occurrences.get(key);
6305             if (count != null) {
6306                 if (count.decrementAndGet() == 0) {
6307                     occurrences.remove(key);
6308                 }
6309                 toRemove.set(i);
6310             }
6311         }
6312         return (byte[]) removeAt(array, toRemove);
6313     }
6314 
6315     /**
6316      * Removes occurrences of specified elements, in specified quantities,
6317      * from the specified array. All subsequent elements are shifted left.
6318      * For any element-to-be-removed specified in greater quantities than
6319      * contained in the original array, no change occurs beyond the
6320      * removal of the existing matching items.
6321      * <p>
6322      * This method returns a new array with the same elements of the input
6323      * array except for the earliest-encountered occurrences of the specified
6324      * elements. The component type of the returned array is always the same
6325      * as that of the input array.
6326      * </p>
6327      * <pre>
6328      * ArrayUtils.removeElements(null, 1, 2)      = null
6329      * ArrayUtils.removeElements([], 1, 2)        = []
6330      * ArrayUtils.removeElements([1], 2, 3)       = [1]
6331      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6332      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6333      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6334      * </pre>
6335      *
6336      * @param array the input array, will not be modified, and may be {@code null}.
6337      * @param values  the values to be removed.
6338      * @return A new array containing the existing elements except the
6339      *         earliest-encountered occurrences of the specified elements.
6340      * @since 3.0.1
6341      */
6342     public static char[] removeElements(final char[] array, final char... values) {
6343         if (isEmpty(array) || isEmpty(values)) {
6344             return clone(array);
6345         }
6346         final HashMap<Character, MutableInt> occurrences = new HashMap<>(values.length);
6347         for (final char v : values) {
6348             increment(occurrences, Character.valueOf(v));
6349         }
6350         final BitSet toRemove = new BitSet();
6351         for (int i = 0; i < array.length; i++) {
6352             final char key = array[i];
6353             final MutableInt count = occurrences.get(key);
6354             if (count != null) {
6355                 if (count.decrementAndGet() == 0) {
6356                     occurrences.remove(key);
6357                 }
6358                 toRemove.set(i);
6359             }
6360         }
6361         return (char[]) removeAt(array, toRemove);
6362     }
6363 
6364     /**
6365      * Removes occurrences of specified elements, in specified quantities,
6366      * from the specified array. All subsequent elements are shifted left.
6367      * For any element-to-be-removed specified in greater quantities than
6368      * contained in the original array, no change occurs beyond the
6369      * removal of the existing matching items.
6370      * <p>
6371      * This method returns a new array with the same elements of the input
6372      * array except for the earliest-encountered occurrences of the specified
6373      * elements. The component type of the returned array is always the same
6374      * as that of the input array.
6375      * </p>
6376      * <pre>
6377      * ArrayUtils.removeElements(null, 1, 2)      = null
6378      * ArrayUtils.removeElements([], 1, 2)        = []
6379      * ArrayUtils.removeElements([1], 2, 3)       = [1]
6380      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6381      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6382      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6383      * </pre>
6384      *
6385      * @param array the input array, will not be modified, and may be {@code null}.
6386      * @param values  the values to be removed.
6387      * @return A new array containing the existing elements except the
6388      *         earliest-encountered occurrences of the specified elements.
6389      * @since 3.0.1
6390      */
6391     public static double[] removeElements(final double[] array, final double... values) {
6392         if (isEmpty(array) || isEmpty(values)) {
6393             return clone(array);
6394         }
6395         final HashMap<Double, MutableInt> occurrences = new HashMap<>(values.length);
6396         for (final double v : values) {
6397             increment(occurrences, Double.valueOf(v));
6398         }
6399         final BitSet toRemove = new BitSet();
6400         for (int i = 0; i < array.length; i++) {
6401             final double key = array[i];
6402             final MutableInt count = occurrences.get(key);
6403             if (count != null) {
6404                 if (count.decrementAndGet() == 0) {
6405                     occurrences.remove(key);
6406                 }
6407                 toRemove.set(i);
6408             }
6409         }
6410         return (double[]) removeAt(array, toRemove);
6411     }
6412 
6413     /**
6414      * Removes occurrences of specified elements, in specified quantities,
6415      * from the specified array. All subsequent elements are shifted left.
6416      * For any element-to-be-removed specified in greater quantities than
6417      * contained in the original array, no change occurs beyond the
6418      * removal of the existing matching items.
6419      * <p>
6420      * This method returns a new array with the same elements of the input
6421      * array except for the earliest-encountered occurrences of the specified
6422      * elements. The component type of the returned array is always the same
6423      * as that of the input array.
6424      * </p>
6425      * <pre>
6426      * ArrayUtils.removeElements(null, 1, 2)      = null
6427      * ArrayUtils.removeElements([], 1, 2)        = []
6428      * ArrayUtils.removeElements([1], 2, 3)       = [1]
6429      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6430      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6431      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6432      * </pre>
6433      *
6434      * @param array the input array, will not be modified, and may be {@code null}.
6435      * @param values  the values to be removed.
6436      * @return A new array containing the existing elements except the
6437      *         earliest-encountered occurrences of the specified elements.
6438      * @since 3.0.1
6439      */
6440     public static float[] removeElements(final float[] array, final float... values) {
6441         if (isEmpty(array) || isEmpty(values)) {
6442             return clone(array);
6443         }
6444         final HashMap<Float, MutableInt> occurrences = new HashMap<>(values.length);
6445         for (final float v : values) {
6446             increment(occurrences, Float.valueOf(v));
6447         }
6448         final BitSet toRemove = new BitSet();
6449         for (int i = 0; i < array.length; i++) {
6450             final float key = array[i];
6451             final MutableInt count = occurrences.get(key);
6452             if (count != null) {
6453                 if (count.decrementAndGet() == 0) {
6454                     occurrences.remove(key);
6455                 }
6456                 toRemove.set(i);
6457             }
6458         }
6459         return (float[]) removeAt(array, toRemove);
6460     }
6461 
6462     /**
6463      * Removes occurrences of specified elements, in specified quantities,
6464      * from the specified array. All subsequent elements are shifted left.
6465      * For any element-to-be-removed specified in greater quantities than
6466      * contained in the original array, no change occurs beyond the
6467      * removal of the existing matching items.
6468      * <p>
6469      * This method returns a new array with the same elements of the input
6470      * array except for the earliest-encountered occurrences of the specified
6471      * elements. The component type of the returned array is always the same
6472      * as that of the input array.
6473      * </p>
6474      * <pre>
6475      * ArrayUtils.removeElements(null, 1, 2)      = null
6476      * ArrayUtils.removeElements([], 1, 2)        = []
6477      * ArrayUtils.removeElements([1], 2, 3)       = [1]
6478      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6479      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6480      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6481      * </pre>
6482      *
6483      * @param array the input array, will not be modified, and may be {@code null}.
6484      * @param values  the values to be removed.
6485      * @return A new array containing the existing elements except the
6486      *         earliest-encountered occurrences of the specified elements.
6487      * @since 3.0.1
6488      */
6489     public static int[] removeElements(final int[] array, final int... values) {
6490         if (isEmpty(array) || isEmpty(values)) {
6491             return clone(array);
6492         }
6493         final HashMap<Integer, MutableInt> occurrences = new HashMap<>(values.length);
6494         for (final int v : values) {
6495             increment(occurrences, Integer.valueOf(v));
6496         }
6497         final BitSet toRemove = new BitSet();
6498         for (int i = 0; i < array.length; i++) {
6499             final int key = array[i];
6500             final MutableInt count = occurrences.get(key);
6501             if (count != null) {
6502                 if (count.decrementAndGet() == 0) {
6503                     occurrences.remove(key);
6504                 }
6505                 toRemove.set(i);
6506             }
6507         }
6508         return (int[]) removeAt(array, toRemove);
6509     }
6510 
6511     /**
6512      * Removes occurrences of specified elements, in specified quantities,
6513      * from the specified array. All subsequent elements are shifted left.
6514      * For any element-to-be-removed specified in greater quantities than
6515      * contained in the original array, no change occurs beyond the
6516      * removal of the existing matching items.
6517      * <p>
6518      * This method returns a new array with the same elements of the input
6519      * array except for the earliest-encountered occurrences of the specified
6520      * elements. The component type of the returned array is always the same
6521      * as that of the input array.
6522      * </p>
6523      * <pre>
6524      * ArrayUtils.removeElements(null, 1, 2)      = null
6525      * ArrayUtils.removeElements([], 1, 2)        = []
6526      * ArrayUtils.removeElements([1], 2, 3)       = [1]
6527      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6528      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6529      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6530      * </pre>
6531      *
6532      * @param array the input array, will not be modified, and may be {@code null}.
6533      * @param values  the values to be removed.
6534      * @return A new array containing the existing elements except the
6535      *         earliest-encountered occurrences of the specified elements.
6536      * @since 3.0.1
6537      */
6538     public static long[] removeElements(final long[] array, final long... values) {
6539         if (isEmpty(array) || isEmpty(values)) {
6540             return clone(array);
6541         }
6542         final HashMap<Long, MutableInt> occurrences = new HashMap<>(values.length);
6543         for (final long v : values) {
6544             increment(occurrences, Long.valueOf(v));
6545         }
6546         final BitSet toRemove = new BitSet();
6547         for (int i = 0; i < array.length; i++) {
6548             final long key = array[i];
6549             final MutableInt count = occurrences.get(key);
6550             if (count != null) {
6551                 if (count.decrementAndGet() == 0) {
6552                     occurrences.remove(key);
6553                 }
6554                 toRemove.set(i);
6555             }
6556         }
6557         return (long[]) removeAt(array, toRemove);
6558     }
6559 
6560     /**
6561      * Removes occurrences of specified elements, in specified quantities,
6562      * from the specified array. All subsequent elements are shifted left.
6563      * For any element-to-be-removed specified in greater quantities than
6564      * contained in the original array, no change occurs beyond the
6565      * removal of the existing matching items.
6566      * <p>
6567      * This method returns a new array with the same elements of the input
6568      * array except for the earliest-encountered occurrences of the specified
6569      * elements. The component type of the returned array is always the same
6570      * as that of the input array.
6571      * </p>
6572      * <pre>
6573      * ArrayUtils.removeElements(null, 1, 2)      = null
6574      * ArrayUtils.removeElements([], 1, 2)        = []
6575      * ArrayUtils.removeElements([1], 2, 3)       = [1]
6576      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6577      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6578      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6579      * </pre>
6580      *
6581      * @param array the input array, will not be modified, and may be {@code null}.
6582      * @param values  the values to be removed.
6583      * @return A new array containing the existing elements except the
6584      *         earliest-encountered occurrences of the specified elements.
6585      * @since 3.0.1
6586      */
6587     public static short[] removeElements(final short[] array, final short... values) {
6588         if (isEmpty(array) || isEmpty(values)) {
6589             return clone(array);
6590         }
6591         final HashMap<Short, MutableInt> occurrences = new HashMap<>(values.length);
6592         for (final short v : values) {
6593             increment(occurrences, Short.valueOf(v));
6594         }
6595         final BitSet toRemove = new BitSet();
6596         for (int i = 0; i < array.length; i++) {
6597             final short key = array[i];
6598             final MutableInt count = occurrences.get(key);
6599             if (count != null) {
6600                 if (count.decrementAndGet() == 0) {
6601                     occurrences.remove(key);
6602                 }
6603                 toRemove.set(i);
6604             }
6605         }
6606         return (short[]) removeAt(array, toRemove);
6607     }
6608 
6609     /**
6610      * Removes occurrences of specified elements, in specified quantities,
6611      * from the specified array. All subsequent elements are shifted left.
6612      * For any element-to-be-removed specified in greater quantities than
6613      * contained in the original array, no change occurs beyond the
6614      * removal of the existing matching items.
6615      * <p>
6616      * This method returns a new array with the same elements of the input
6617      * array except for the earliest-encountered occurrences of the specified
6618      * elements. The component type of the returned array is always the same
6619      * as that of the input array.
6620      * </p>
6621      * <pre>
6622      * ArrayUtils.removeElements(null, "a", "b")            = null
6623      * ArrayUtils.removeElements([], "a", "b")              = []
6624      * ArrayUtils.removeElements(["a"], "b", "c")           = ["a"]
6625      * ArrayUtils.removeElements(["a", "b"], "a", "c")      = ["b"]
6626      * ArrayUtils.removeElements(["a", "b", "a"], "a")      = ["b", "a"]
6627      * ArrayUtils.removeElements(["a", "b", "a"], "a", "a") = ["b"]
6628      * </pre>
6629      *
6630      * @param <T> the component type of the array
6631      * @param array the input array, will not be modified, and may be {@code null}.
6632      * @param values  the values to be removed.
6633      * @return A new array containing the existing elements except the
6634      *         earliest-encountered occurrences of the specified elements.
6635      * @since 3.0.1
6636      */
6637     @SafeVarargs
6638     public static <T> T[] removeElements(final T[] array, final T... values) {
6639         if (isEmpty(array) || isEmpty(values)) {
6640             return clone(array);
6641         }
6642         final HashMap<T, MutableInt> occurrences = new HashMap<>(values.length);
6643         for (final T v : values) {
6644             increment(occurrences, v);
6645         }
6646         final BitSet toRemove = new BitSet();
6647         for (int i = 0; i < array.length; i++) {
6648             final T key = array[i];
6649             final MutableInt count = occurrences.get(key);
6650             if (count != null) {
6651                 if (count.decrementAndGet() == 0) {
6652                     occurrences.remove(key);
6653                 }
6654                 toRemove.set(i);
6655             }
6656         }
6657         @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
6658         final T[] result = (T[]) removeAt(array, toRemove);
6659         return result;
6660     }
6661 
6662     /**
6663      * Reverses the order of the given array.
6664      * <p>
6665      * This method does nothing for a {@code null} input array.
6666      * </p>
6667      *
6668      * @param array  the array to reverse, may be {@code null}.
6669      */
6670     public static void reverse(final boolean[] array) {
6671         if (array != null) {
6672             reverse(array, 0, array.length);
6673         }
6674     }
6675 
6676     /**
6677      * Reverses the order of the given array in the given range.
6678      * <p>
6679      * This method does nothing for a {@code null} input array.
6680      * </p>
6681      *
6682      * @param array
6683      *            the array to reverse, may be {@code null}.
6684      * @param startIndexInclusive
6685      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6686      *            change.
6687      * @param endIndexExclusive
6688      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6689      *            change. Overvalue (&gt;array.length) is demoted to array length.
6690      * @since 3.2
6691      */
6692     public static void reverse(final boolean[] array, final int startIndexInclusive, final int endIndexExclusive) {
6693         if (array == null) {
6694             return;
6695         }
6696         int i = Math.max(startIndexInclusive, 0);
6697         int j = Math.min(array.length, endIndexExclusive) - 1;
6698         boolean tmp;
6699         while (j > i) {
6700             tmp = array[j];
6701             array[j] = array[i];
6702             array[i] = tmp;
6703             j--;
6704             i++;
6705         }
6706     }
6707 
6708     /**
6709      * Reverses the order of the given array.
6710      * <p>
6711      * This method does nothing for a {@code null} input array.
6712      * </p>
6713      *
6714      * @param array  the array to reverse, may be {@code null}.
6715      */
6716     public static void reverse(final byte[] array) {
6717         if (array != null) {
6718             reverse(array, 0, array.length);
6719         }
6720     }
6721 
6722     /**
6723      * Reverses the order of the given array in the given range.
6724      * <p>
6725      * This method does nothing for a {@code null} input array.
6726      * </p>
6727      *
6728      * @param array               the array to reverse, may be {@code null}.
6729      * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no change.
6730      * @param endIndexExclusive   elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no change. Overvalue
6731      *                            (&gt;array.length) is demoted to array length.
6732      * @since 3.2
6733      */
6734     public static void reverse(final byte[] array, final int startIndexInclusive, final int endIndexExclusive) {
6735         if (array == null) {
6736             return;
6737         }
6738         int i = Math.max(startIndexInclusive, 0);
6739         int j = Math.min(array.length, endIndexExclusive) - 1;
6740         byte tmp;
6741         while (j > i) {
6742             tmp = array[j];
6743             array[j] = array[i];
6744             array[i] = tmp;
6745             j--;
6746             i++;
6747         }
6748     }
6749 
6750     /**
6751      * Reverses the order of the given array.
6752      * <p>
6753      * This method does nothing for a {@code null} input array.
6754      * </p>
6755      *
6756      * @param array  the array to reverse, may be {@code null}.
6757      */
6758     public static void reverse(final char[] array) {
6759         if (array != null) {
6760             reverse(array, 0, array.length);
6761         }
6762     }
6763 
6764     /**
6765      * Reverses the order of the given array in the given range.
6766      * <p>
6767      * This method does nothing for a {@code null} input array.
6768      * </p>
6769      *
6770      * @param array               the array to reverse, may be {@code null}.
6771      * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no change.
6772      * @param endIndexExclusive   elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no change. Overvalue
6773      *                            (&gt;array.length) is demoted to array length.
6774      * @since 3.2
6775      */
6776     public static void reverse(final char[] array, final int startIndexInclusive, final int endIndexExclusive) {
6777         if (array == null) {
6778             return;
6779         }
6780         int i = Math.max(startIndexInclusive, 0);
6781         int j = Math.min(array.length, endIndexExclusive) - 1;
6782         char tmp;
6783         while (j > i) {
6784             tmp = array[j];
6785             array[j] = array[i];
6786             array[i] = tmp;
6787             j--;
6788             i++;
6789         }
6790     }
6791 
6792     /**
6793      * Reverses the order of the given array.
6794      * <p>
6795      * This method does nothing for a {@code null} input array.
6796      * </p>
6797      *
6798      * @param array  the array to reverse, may be {@code null}
6799      */
6800     public static void reverse(final double[] array) {
6801         if (array != null) {
6802             reverse(array, 0, array.length);
6803         }
6804     }
6805 
6806     /**
6807      * Reverses the order of the given array in the given range.
6808      * <p>
6809      * This method does nothing for a {@code null} input array.
6810      * </p>
6811      *
6812      * @param array               the array to reverse, may be {@code null}.
6813      * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no change.
6814      * @param endIndexExclusive   elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no change. Overvalue
6815      *                            (&gt;array.length) is demoted to array length.
6816      * @since 3.2
6817      */
6818     public static void reverse(final double[] array, final int startIndexInclusive, final int endIndexExclusive) {
6819         if (array == null) {
6820             return;
6821         }
6822         int i = Math.max(startIndexInclusive, 0);
6823         int j = Math.min(array.length, endIndexExclusive) - 1;
6824         double tmp;
6825         while (j > i) {
6826             tmp = array[j];
6827             array[j] = array[i];
6828             array[i] = tmp;
6829             j--;
6830             i++;
6831         }
6832     }
6833 
6834     /**
6835      * Reverses the order of the given array.
6836      * <p>
6837      * This method does nothing for a {@code null} input array.
6838      * </p>
6839      *
6840      * @param array  the array to reverse, may be {@code null}.
6841      */
6842     public static void reverse(final float[] array) {
6843         if (array != null) {
6844             reverse(array, 0, array.length);
6845         }
6846     }
6847 
6848     /**
6849      * Reverses the order of the given array in the given range.
6850      * <p>
6851      * This method does nothing for a {@code null} input array.
6852      * </p>
6853      *
6854      * @param array               the array to reverse, may be {@code null}.
6855      * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no change.
6856      * @param endIndexExclusive   elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no change. Overvalue
6857      *                            (&gt;array.length) is demoted to array length.
6858      * @since 3.2
6859      */
6860     public static void reverse(final float[] 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         float 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 int[] 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 int[] 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         int 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      * Reverses the order of the given array.
6924      * <p>
6925      * This method does nothing for a {@code null} input array.
6926      * </p>
6927      *
6928      * @param array  the array to reverse, may be {@code null}.
6929      */
6930     public static void reverse(final long[] array) {
6931         if (array != null) {
6932             reverse(array, 0, array.length);
6933         }
6934     }
6935 
6936     /**
6937      * Reverses the order of the given array in the given range.
6938      * <p>
6939      * This method does nothing for a {@code null} input array.
6940      * </p>
6941      *
6942      * @param array
6943      *            the array to reverse, may be {@code null}.
6944      * @param startIndexInclusive
6945      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6946      *            change.
6947      * @param endIndexExclusive
6948      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6949      *            change. Overvalue (&gt;array.length) is demoted to array length.
6950      * @since 3.2
6951      */
6952     public static void reverse(final long[] array, final int startIndexInclusive, final int endIndexExclusive) {
6953         if (array == null) {
6954             return;
6955         }
6956         int i = Math.max(startIndexInclusive, 0);
6957         int j = Math.min(array.length, endIndexExclusive) - 1;
6958         long tmp;
6959         while (j > i) {
6960             tmp = array[j];
6961             array[j] = array[i];
6962             array[i] = tmp;
6963             j--;
6964             i++;
6965         }
6966     }
6967 
6968     /**
6969      * Reverses the order of the given array.
6970      * <p>
6971      * There is no special handling for multi-dimensional arrays.
6972      * </p>
6973      * <p>
6974      * This method does nothing for a {@code null} input array.
6975      * </p>
6976      *
6977      * @param array  the array to reverse, may be {@code null}.
6978      */
6979     public static void reverse(final Object[] array) {
6980         if (array != null) {
6981             reverse(array, 0, array.length);
6982         }
6983     }
6984 
6985     /**
6986      * Reverses the order of the given array in the given range.
6987      * <p>
6988      * This method does nothing for a {@code null} input array.
6989      * </p>
6990      *
6991      * @param array
6992      *            the array to reverse, may be {@code null}.
6993      * @param startIndexInclusive
6994      *            the starting index. Under value (&lt;0) is promoted to 0, over value (&gt;array.length) results in no
6995      *            change.
6996      * @param endIndexExclusive
6997      *            elements up to endIndex-1 are reversed in the array. Under value (&lt; start index) results in no
6998      *            change. Over value (&gt;array.length) is demoted to array length.
6999      * @since 3.2
7000      */
7001     public static void reverse(final Object[] array, final int startIndexInclusive, final int endIndexExclusive) {
7002         if (array == null) {
7003             return;
7004         }
7005         int i = Math.max(startIndexInclusive, 0);
7006         int j = Math.min(array.length, endIndexExclusive) - 1;
7007         Object tmp;
7008         while (j > i) {
7009             tmp = array[j];
7010             array[j] = array[i];
7011             array[i] = tmp;
7012             j--;
7013             i++;
7014         }
7015     }
7016 
7017     /**
7018      * Reverses the order of the given array.
7019      * <p>
7020      * This method does nothing for a {@code null} input array.
7021      * </p>
7022      *
7023      * @param array  the array to reverse, may be {@code null}.
7024      */
7025     public static void reverse(final short[] array) {
7026         if (array != null) {
7027             reverse(array, 0, array.length);
7028         }
7029     }
7030 
7031     /**
7032      * Reverses the order of the given array in the given range.
7033      * <p>
7034      * This method does nothing for a {@code null} input array.
7035      * </p>
7036      *
7037      * @param array
7038      *            the array to reverse, may be {@code null}.
7039      * @param startIndexInclusive
7040      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7041      *            change.
7042      * @param endIndexExclusive
7043      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
7044      *            change. Overvalue (&gt;array.length) is demoted to array length.
7045      * @since 3.2
7046      */
7047     public static void reverse(final short[] array, final int startIndexInclusive, final int endIndexExclusive) {
7048         if (array == null) {
7049             return;
7050         }
7051         int i = Math.max(startIndexInclusive, 0);
7052         int j = Math.min(array.length, endIndexExclusive) - 1;
7053         short tmp;
7054         while (j > i) {
7055             tmp = array[j];
7056             array[j] = array[i];
7057             array[i] = tmp;
7058             j--;
7059             i++;
7060         }
7061     }
7062 
7063     /**
7064      * Sets all elements of the specified array, using the provided generator supplier to compute each element.
7065      * <p>
7066      * If the generator supplier throws an exception, it is relayed to the caller and the array is left in an indeterminate
7067      * state.
7068      * </p>
7069      *
7070      * @param <T> type of elements of the array, may be {@code null}.
7071      * @param array array to be initialized, may be {@code null}.
7072      * @param generator a function accepting an index and producing the desired value for that position.
7073      * @return the input array
7074      * @since 3.13.0
7075      */
7076     public static <T> T[] setAll(final T[] array, final IntFunction<? extends T> generator) {
7077         if (array != null && generator != null) {
7078             Arrays.setAll(array, generator);
7079         }
7080         return array;
7081     }
7082 
7083     /**
7084      * Sets all elements of the specified array, using the provided generator supplier to compute each element.
7085      * <p>
7086      * If the generator supplier throws an exception, it is relayed to the caller and the array is left in an indeterminate
7087      * state.
7088      * </p>
7089      *
7090      * @param <T> type of elements of the array, may be {@code null}.
7091      * @param array array to be initialized, may be {@code null}.
7092      * @param generator a function accepting an index and producing the desired value for that position.
7093      * @return the input array
7094      * @since 3.13.0
7095      */
7096     public static <T> T[] setAll(final T[] array, final Supplier<? extends T> generator) {
7097         if (array != null && generator != null) {
7098             for (int i = 0; i < array.length; i++) {
7099                 array[i] = generator.get();
7100             }
7101         }
7102         return array;
7103     }
7104 
7105     /**
7106      * Shifts the order of the given boolean array.
7107      *
7108      * <p>There is no special handling for multi-dimensional arrays. This method
7109      * does nothing for {@code null} or empty input arrays.</p>
7110      *
7111      * @param array  the array to shift, may be {@code null}.
7112      * @param offset
7113      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7114      *          rotate, than the effective offset is modulo the number of elements to rotate.
7115      * @since 3.5
7116      */
7117     public static void shift(final boolean[] array, final int offset) {
7118         if (array != null) {
7119             shift(array, 0, array.length, offset);
7120         }
7121     }
7122 
7123     /**
7124      * Shifts the order of a series of elements in the given boolean array.
7125      *
7126      * <p>There is no special handling for multi-dimensional arrays. This method
7127      * does nothing for {@code null} or empty input arrays.</p>
7128      *
7129      * @param array
7130      *            the array to shift, may be {@code null}.
7131      * @param startIndexInclusive
7132      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7133      *            change.
7134      * @param endIndexExclusive
7135      *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7136      *            change. Overvalue (&gt;array.length) is demoted to array length.
7137      * @param offset
7138      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7139      *          rotate, than the effective offset is modulo the number of elements to rotate.
7140      * @since 3.5
7141      */
7142     public static void shift(final boolean[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7143         if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7144             return;
7145         }
7146         startIndexInclusive = max0(startIndexInclusive);
7147         endIndexExclusive = Math.min(endIndexExclusive, array.length);
7148         int n = endIndexExclusive - startIndexInclusive;
7149         if (n <= 1) {
7150             return;
7151         }
7152         offset %= n;
7153         if (offset < 0) {
7154             offset += n;
7155         }
7156         // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7157         // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7158         while (n > 1 && offset > 0) {
7159             final int nOffset = n - offset;
7160             if (offset > nOffset) {
7161                 swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7162                 n = offset;
7163                 offset -= nOffset;
7164             } else if (offset < nOffset) {
7165                 swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7166                 startIndexInclusive += offset;
7167                 n = nOffset;
7168             } else {
7169                 swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7170                 break;
7171             }
7172         }
7173     }
7174 
7175     /**
7176      * Shifts the order of the given byte array.
7177      *
7178      * <p>There is no special handling for multi-dimensional arrays. This method
7179      * does nothing for {@code null} or empty input arrays.</p>
7180      *
7181      * @param array  the array to shift, may be {@code null}.
7182      * @param offset
7183      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7184      *          rotate, than the effective offset is modulo the number of elements to rotate.
7185      * @since 3.5
7186      */
7187     public static void shift(final byte[] array, final int offset) {
7188         if (array != null) {
7189             shift(array, 0, array.length, offset);
7190         }
7191     }
7192 
7193     /**
7194      * Shifts the order of a series of elements in the given byte array.
7195      *
7196      * <p>There is no special handling for multi-dimensional arrays. This method
7197      * does nothing for {@code null} or empty input arrays.</p>
7198      *
7199      * @param array
7200      *            the array to shift, may be {@code null}.
7201      * @param startIndexInclusive
7202      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7203      *            change.
7204      * @param endIndexExclusive
7205      *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7206      *            change. Overvalue (&gt;array.length) is demoted to array length.
7207      * @param offset
7208      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7209      *          rotate, than the effective offset is modulo the number of elements to rotate.
7210      * @since 3.5
7211      */
7212     public static void shift(final byte[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7213         if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7214             return;
7215         }
7216         startIndexInclusive = max0(startIndexInclusive);
7217         endIndexExclusive = Math.min(endIndexExclusive, array.length);
7218         int n = endIndexExclusive - startIndexInclusive;
7219         if (n <= 1) {
7220             return;
7221         }
7222         offset %= n;
7223         if (offset < 0) {
7224             offset += n;
7225         }
7226         // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7227         // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7228         while (n > 1 && offset > 0) {
7229             final int nOffset = n - offset;
7230             if (offset > nOffset) {
7231                 swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7232                 n = offset;
7233                 offset -= nOffset;
7234             } else if (offset < nOffset) {
7235                 swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7236                 startIndexInclusive += offset;
7237                 n = nOffset;
7238             } else {
7239                 swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7240                 break;
7241             }
7242         }
7243     }
7244 
7245     /**
7246      * Shifts the order of the given char array.
7247      *
7248      * <p>There is no special handling for multi-dimensional arrays. This method
7249      * does nothing for {@code null} or empty input arrays.</p>
7250      *
7251      * @param array  the array to shift, may be {@code null}.
7252      * @param offset
7253      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7254      *          rotate, than the effective offset is modulo the number of elements to rotate.
7255      * @since 3.5
7256      */
7257     public static void shift(final char[] array, final int offset) {
7258         if (array != null) {
7259             shift(array, 0, array.length, offset);
7260         }
7261     }
7262 
7263     /**
7264      * Shifts the order of a series of elements in the given char array.
7265      *
7266      * <p>There is no special handling for multi-dimensional arrays. This method
7267      * does nothing for {@code null} or empty input arrays.</p>
7268      *
7269      * @param array
7270      *            the array to shift, may be {@code null}.
7271      * @param startIndexInclusive
7272      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7273      *            change.
7274      * @param endIndexExclusive
7275      *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7276      *            change. Overvalue (&gt;array.length) is demoted to array length.
7277      * @param offset
7278      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7279      *          rotate, than the effective offset is modulo the number of elements to rotate.
7280      * @since 3.5
7281      */
7282     public static void shift(final char[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7283         if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7284             return;
7285         }
7286         startIndexInclusive = max0(startIndexInclusive);
7287         endIndexExclusive = Math.min(endIndexExclusive, array.length);
7288         int n = endIndexExclusive - startIndexInclusive;
7289         if (n <= 1) {
7290             return;
7291         }
7292         offset %= n;
7293         if (offset < 0) {
7294             offset += n;
7295         }
7296         // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7297         // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7298         while (n > 1 && offset > 0) {
7299             final int nOffset = n - offset;
7300             if (offset > nOffset) {
7301                 swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7302                 n = offset;
7303                 offset -= nOffset;
7304             } else if (offset < nOffset) {
7305                 swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7306                 startIndexInclusive += offset;
7307                 n = nOffset;
7308             } else {
7309                 swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7310                 break;
7311             }
7312         }
7313     }
7314 
7315     /**
7316      * Shifts the order of the given double array.
7317      *
7318      * <p>There is no special handling for multi-dimensional arrays. This method
7319      * does nothing for {@code null} or empty input arrays.</p>
7320      *
7321      * @param array  the array to shift, may be {@code null}.
7322      * @param offset
7323      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7324      *          rotate, than the effective offset is modulo the number of elements to rotate.
7325      * @since 3.5
7326      */
7327     public static void shift(final double[] array, final int offset) {
7328         if (array != null) {
7329             shift(array, 0, array.length, offset);
7330         }
7331     }
7332 
7333     /**
7334      * Shifts the order of a series of elements in the given double array.
7335      *
7336      * <p>There is no special handling for multi-dimensional arrays. This method
7337      * does nothing for {@code null} or empty input arrays.</p>
7338      *
7339      * @param array
7340      *            the array to shift, may be {@code null}.
7341      * @param startIndexInclusive
7342      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7343      *            change.
7344      * @param endIndexExclusive
7345      *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7346      *            change. Overvalue (&gt;array.length) is demoted to array length.
7347      * @param offset
7348      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7349      *          rotate, than the effective offset is modulo the number of elements to rotate.
7350      * @since 3.5
7351      */
7352     public static void shift(final double[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7353         if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7354             return;
7355         }
7356         startIndexInclusive = max0(startIndexInclusive);
7357         endIndexExclusive = Math.min(endIndexExclusive, array.length);
7358         int n = endIndexExclusive - startIndexInclusive;
7359         if (n <= 1) {
7360             return;
7361         }
7362         offset %= n;
7363         if (offset < 0) {
7364             offset += n;
7365         }
7366         // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7367         // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7368         while (n > 1 && offset > 0) {
7369             final int nOffset = n - offset;
7370             if (offset > nOffset) {
7371                 swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7372                 n = offset;
7373                 offset -= nOffset;
7374             } else if (offset < nOffset) {
7375                 swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7376                 startIndexInclusive += offset;
7377                 n = nOffset;
7378             } else {
7379                 swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7380                 break;
7381             }
7382         }
7383     }
7384 
7385     /**
7386      * Shifts the order of the given float array.
7387      *
7388      * <p>There is no special handling for multi-dimensional arrays. This method
7389      * does nothing for {@code null} or empty input arrays.</p>
7390      *
7391      * @param array  the array to shift, may be {@code null}.
7392      * @param offset
7393      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7394      *          rotate, than the effective offset is modulo the number of elements to rotate.
7395      * @since 3.5
7396      */
7397     public static void shift(final float[] array, final int offset) {
7398         if (array != null) {
7399             shift(array, 0, array.length, offset);
7400         }
7401     }
7402 
7403     /**
7404      * Shifts the order of a series of elements in the given float array.
7405      *
7406      * <p>There is no special handling for multi-dimensional arrays. This method
7407      * does nothing for {@code null} or empty input arrays.</p>
7408      *
7409      * @param array
7410      *            the array to shift, may be {@code null}.
7411      * @param startIndexInclusive
7412      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7413      *            change.
7414      * @param endIndexExclusive
7415      *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7416      *            change. Overvalue (&gt;array.length) is demoted to array length.
7417      * @param offset
7418      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7419      *          rotate, than the effective offset is modulo the number of elements to rotate.
7420      * @since 3.5
7421      */
7422     public static void shift(final float[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7423         if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7424             return;
7425         }
7426         startIndexInclusive = max0(startIndexInclusive);
7427         endIndexExclusive = Math.min(endIndexExclusive, array.length);
7428         int n = endIndexExclusive - startIndexInclusive;
7429         if (n <= 1) {
7430             return;
7431         }
7432         offset %= n;
7433         if (offset < 0) {
7434             offset += n;
7435         }
7436         // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7437         // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7438         while (n > 1 && offset > 0) {
7439             final int nOffset = n - offset;
7440             if (offset > nOffset) {
7441                 swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7442                 n = offset;
7443                 offset -= nOffset;
7444             } else if (offset < nOffset) {
7445                 swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7446                 startIndexInclusive += offset;
7447                 n = nOffset;
7448             } else {
7449                 swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7450                 break;
7451             }
7452         }
7453     }
7454 
7455     /**
7456      * Shifts the order of the given int array.
7457      *
7458      * <p>There is no special handling for multi-dimensional arrays. This method
7459      * does nothing for {@code null} or empty input arrays.</p>
7460      *
7461      * @param array  the array to shift, may be {@code null}.
7462      * @param offset
7463      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7464      *          rotate, than the effective offset is modulo the number of elements to rotate.
7465      * @since 3.5
7466      */
7467     public static void shift(final int[] array, final int offset) {
7468         if (array != null) {
7469             shift(array, 0, array.length, offset);
7470         }
7471     }
7472 
7473     /**
7474      * Shifts the order of a series of elements in the given int array.
7475      *
7476      * <p>There is no special handling for multi-dimensional arrays. This method
7477      * does nothing for {@code null} or empty input arrays.</p>
7478      *
7479      * @param array
7480      *            the array to shift, may be {@code null}.
7481      * @param startIndexInclusive
7482      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7483      *            change.
7484      * @param endIndexExclusive
7485      *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7486      *            change. Overvalue (&gt;array.length) is demoted to array length.
7487      * @param offset
7488      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7489      *          rotate, than the effective offset is modulo the number of elements to rotate.
7490      * @since 3.5
7491      */
7492     public static void shift(final int[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7493         if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7494             return;
7495         }
7496         startIndexInclusive = max0(startIndexInclusive);
7497         endIndexExclusive = Math.min(endIndexExclusive, array.length);
7498         int n = endIndexExclusive - startIndexInclusive;
7499         if (n <= 1) {
7500             return;
7501         }
7502         offset %= n;
7503         if (offset < 0) {
7504             offset += n;
7505         }
7506         // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7507         // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7508         while (n > 1 && offset > 0) {
7509             final int nOffset = n - offset;
7510             if (offset > nOffset) {
7511                 swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7512                 n = offset;
7513                 offset -= nOffset;
7514             } else if (offset < nOffset) {
7515                 swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7516                 startIndexInclusive += offset;
7517                 n = nOffset;
7518             } else {
7519                 swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7520                 break;
7521             }
7522         }
7523     }
7524 
7525     /**
7526      * Shifts the order of the given long array.
7527      *
7528      * <p>There is no special handling for multi-dimensional arrays. This method
7529      * does nothing for {@code null} or empty input arrays.</p>
7530      *
7531      * @param array  the array to shift, may be {@code null}.
7532      * @param offset
7533      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7534      *          rotate, than the effective offset is modulo the number of elements to rotate.
7535      * @since 3.5
7536      */
7537     public static void shift(final long[] array, final int offset) {
7538         if (array != null) {
7539             shift(array, 0, array.length, offset);
7540         }
7541     }
7542 
7543     /**
7544      * Shifts the order of a series of elements in the given long array.
7545      *
7546      * <p>There is no special handling for multi-dimensional arrays. This method
7547      * does nothing for {@code null} or empty input arrays.</p>
7548      *
7549      * @param array
7550      *            the array to shift, may be {@code null}.
7551      * @param startIndexInclusive
7552      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7553      *            change.
7554      * @param endIndexExclusive
7555      *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7556      *            change. Overvalue (&gt;array.length) is demoted to array length.
7557      * @param offset
7558      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7559      *          rotate, than the effective offset is modulo the number of elements to rotate.
7560      * @since 3.5
7561      */
7562     public static void shift(final long[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7563         if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7564             return;
7565         }
7566         startIndexInclusive = max0(startIndexInclusive);
7567         endIndexExclusive = Math.min(endIndexExclusive, array.length);
7568         int n = endIndexExclusive - startIndexInclusive;
7569         if (n <= 1) {
7570             return;
7571         }
7572         offset %= n;
7573         if (offset < 0) {
7574             offset += n;
7575         }
7576         // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7577         // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7578         while (n > 1 && offset > 0) {
7579             final int nOffset = n - offset;
7580             if (offset > nOffset) {
7581                 swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7582                 n = offset;
7583                 offset -= nOffset;
7584             } else if (offset < nOffset) {
7585                 swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7586                 startIndexInclusive += offset;
7587                 n = nOffset;
7588             } else {
7589                 swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7590                 break;
7591             }
7592         }
7593     }
7594 
7595     /**
7596      * Shifts the order of the given array.
7597      *
7598      * <p>There is no special handling for multi-dimensional arrays. This method
7599      * does nothing for {@code null} or empty input arrays.</p>
7600      *
7601      * @param array  the array to shift, may be {@code null}.
7602      * @param offset
7603      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7604      *          rotate, than the effective offset is modulo the number of elements to rotate.
7605      * @since 3.5
7606      */
7607     public static void shift(final Object[] array, final int offset) {
7608         if (array != null) {
7609             shift(array, 0, array.length, offset);
7610         }
7611     }
7612 
7613     /**
7614      * Shifts the order of a series of elements in the given array.
7615      *
7616      * <p>There is no special handling for multi-dimensional arrays. This method
7617      * does nothing for {@code null} or empty input arrays.</p>
7618      *
7619      * @param array
7620      *            the array to shift, may be {@code null}.
7621      * @param startIndexInclusive
7622      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7623      *            change.
7624      * @param endIndexExclusive
7625      *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7626      *            change. Overvalue (&gt;array.length) is demoted to array length.
7627      * @param offset
7628      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7629      *          rotate, than the effective offset is modulo the number of elements to rotate.
7630      * @since 3.5
7631      */
7632     public static void shift(final Object[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7633         if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7634             return;
7635         }
7636         startIndexInclusive = max0(startIndexInclusive);
7637         endIndexExclusive = Math.min(endIndexExclusive, array.length);
7638         int n = endIndexExclusive - startIndexInclusive;
7639         if (n <= 1) {
7640             return;
7641         }
7642         offset %= n;
7643         if (offset < 0) {
7644             offset += n;
7645         }
7646         // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7647         // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7648         while (n > 1 && offset > 0) {
7649             final int nOffset = n - offset;
7650             if (offset > nOffset) {
7651                 swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7652                 n = offset;
7653                 offset -= nOffset;
7654             } else if (offset < nOffset) {
7655                 swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7656                 startIndexInclusive += offset;
7657                 n = nOffset;
7658             } else {
7659                 swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7660                 break;
7661             }
7662         }
7663     }
7664 
7665     /**
7666      * Shifts the order of the given short array.
7667      *
7668      * <p>There is no special handling for multi-dimensional arrays. This method
7669      * does nothing for {@code null} or empty input arrays.</p>
7670      *
7671      * @param array  the array to shift, may be {@code null}.
7672      * @param offset
7673      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7674      *          rotate, than the effective offset is modulo the number of elements to rotate.
7675      * @since 3.5
7676      */
7677     public static void shift(final short[] array, final int offset) {
7678         if (array != null) {
7679             shift(array, 0, array.length, offset);
7680         }
7681     }
7682 
7683     /**
7684      * Shifts the order of a series of elements in the given short array.
7685      *
7686      * <p>There is no special handling for multi-dimensional arrays. This method
7687      * does nothing for {@code null} or empty input arrays.</p>
7688      *
7689      * @param array
7690      *            the array to shift, may be {@code null}.
7691      * @param startIndexInclusive
7692      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7693      *            change.
7694      * @param endIndexExclusive
7695      *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7696      *            change. Overvalue (&gt;array.length) is demoted to array length.
7697      * @param offset
7698      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7699      *          rotate, than the effective offset is modulo the number of elements to rotate.
7700      * @since 3.5
7701      */
7702     public static void shift(final short[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7703         if (array == null || startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7704             return;
7705         }
7706         startIndexInclusive = max0(startIndexInclusive);
7707         endIndexExclusive = Math.min(endIndexExclusive, array.length);
7708         int n = endIndexExclusive - startIndexInclusive;
7709         if (n <= 1) {
7710             return;
7711         }
7712         offset %= n;
7713         if (offset < 0) {
7714             offset += n;
7715         }
7716         // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7717         // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7718         while (n > 1 && offset > 0) {
7719             final int nOffset = n - offset;
7720             if (offset > nOffset) {
7721                 swap(array, startIndexInclusive, startIndexInclusive + n - nOffset,  nOffset);
7722                 n = offset;
7723                 offset -= nOffset;
7724             } else if (offset < nOffset) {
7725                 swap(array, startIndexInclusive, startIndexInclusive + nOffset,  offset);
7726                 startIndexInclusive += offset;
7727                 n = nOffset;
7728             } else {
7729                 swap(array, startIndexInclusive, startIndexInclusive + nOffset, offset);
7730                 break;
7731             }
7732         }
7733     }
7734 
7735     /**
7736      * 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
7737      * algorithm</a>.
7738      * <p>
7739      * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7740      * </p>
7741      * <p>
7742      * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7743      * with a {@link SecureRandom} argument.
7744      * </p>
7745      *
7746      * @param array the array to shuffle.
7747      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7748      * @since 3.6
7749      */
7750     public static void shuffle(final boolean[] array) {
7751         shuffle(array, random());
7752     }
7753 
7754     /**
7755      * 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
7756      * algorithm</a>.
7757      *
7758      * @param array  the array to shuffle, no-op if {@code null}.
7759      * @param random the source of randomness used to permute the elements, no-op if {@code null}.
7760      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7761      * @since 3.6
7762      */
7763     public static void shuffle(final boolean[] array, final Random random) {
7764         if (array != null && random != null) {
7765             for (int i = array.length; i > 1; i--) {
7766                 swap(array, i - 1, random.nextInt(i), 1);
7767             }
7768         }
7769     }
7770 
7771     /**
7772      * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
7773      * algorithm</a>.
7774      * <p>
7775      * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7776      * </p>
7777      * <p>
7778      * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7779      * with a {@link SecureRandom} argument.
7780      * </p>
7781      *
7782      * @param array the array to shuffle.
7783      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7784      * @since 3.6
7785      */
7786     public static void shuffle(final byte[] array) {
7787         shuffle(array, random());
7788     }
7789 
7790     /**
7791      * Shuffles randomly the elements of the specified array using the <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle
7792      * algorithm</a>.
7793      *
7794      * @param array  the array to shuffle, no-op if {@code null}.
7795      * @param random the source of randomness used to permute the elements, no-op if {@code null}.
7796      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7797      * @since 3.6
7798      */
7799     public static void shuffle(final byte[] array, final Random random) {
7800         if (array != null && random != null) {
7801             for (int i = array.length; i > 1; i--) {
7802                 swap(array, i - 1, random.nextInt(i), 1);
7803             }
7804         }
7805     }
7806 
7807     /**
7808      * 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
7809      * algorithm</a>.
7810      * <p>
7811      * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7812      * </p>
7813      * <p>
7814      * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7815      * with a {@link SecureRandom} argument.
7816      * </p>
7817      *
7818      * @param array the array to shuffle.
7819      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7820      * @since 3.6
7821      */
7822     public static void shuffle(final char[] array) {
7823         shuffle(array, random());
7824     }
7825 
7826     /**
7827      * 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
7828      * algorithm</a>.
7829      *
7830      * @param array  the array to shuffle, no-op if {@code null}.
7831      * @param random the source of randomness used to permute the elements, no-op if {@code null}.
7832      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7833      * @since 3.6
7834      */
7835     public static void shuffle(final char[] array, final Random random) {
7836         if (array != null && random != null) {
7837             for (int i = array.length; i > 1; i--) {
7838                 swap(array, i - 1, random.nextInt(i), 1);
7839             }
7840         }
7841     }
7842 
7843     /**
7844      * 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
7845      * algorithm</a>.
7846      * <p>
7847      * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7848      * </p>
7849      * <p>
7850      * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7851      * with a {@link SecureRandom} argument.
7852      * </p>
7853      *
7854      * @param array the array to shuffle.
7855      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7856      * @since 3.6
7857      */
7858     public static void shuffle(final double[] array) {
7859         shuffle(array, random());
7860     }
7861 
7862     /**
7863      * 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
7864      * algorithm</a>.
7865      *
7866      * @param array  the array to shuffle, no-op if {@code null}.
7867      * @param random the source of randomness used to permute the elements, no-op if {@code null}.
7868      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7869      * @since 3.6
7870      */
7871     public static void shuffle(final double[] array, final Random random) {
7872         if (array != null && random != null) {
7873             for (int i = array.length; i > 1; i--) {
7874                 swap(array, i - 1, random.nextInt(i), 1);
7875             }
7876         }
7877     }
7878 
7879     /**
7880      * 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
7881      * algorithm</a>.
7882      * <p>
7883      * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7884      * </p>
7885      * <p>
7886      * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7887      * with a {@link SecureRandom} argument.
7888      * </p>
7889      *
7890      * @param array the array to shuffle.
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 float[] array) {
7895         shuffle(array, random());
7896     }
7897 
7898     /**
7899      * 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
7900      * algorithm</a>.
7901      *
7902      * @param array  the array to shuffle, no-op if {@code null}.
7903      * @param random the source of randomness used to permute the elements, no-op if {@code null}.
7904      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7905      * @since 3.6
7906      */
7907     public static void shuffle(final float[] array, final Random random) {
7908         if (array != null && random != null) {
7909             for (int i = array.length; i > 1; i--) {
7910                 swap(array, i - 1, random.nextInt(i), 1);
7911             }
7912         }
7913     }
7914 
7915     /**
7916      * 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
7917      * algorithm</a>.
7918      * <p>
7919      * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7920      * </p>
7921      * <p>
7922      * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7923      * with a {@link SecureRandom} argument.
7924      * </p>
7925      *
7926      * @param array the array to shuffle.
7927      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7928      * @since 3.6
7929      */
7930     public static void shuffle(final int[] array) {
7931         shuffle(array, random());
7932     }
7933 
7934     /**
7935      * 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
7936      * algorithm</a>.
7937      *
7938      * @param array  the array to shuffle, no-op if {@code null}.
7939      * @param random the source of randomness used to permute the elements, no-op if {@code null}.
7940      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7941      * @since 3.6
7942      */
7943     public static void shuffle(final int[] array, final Random random) {
7944         if (array != null && random != null) {
7945             for (int i = array.length; i > 1; i--) {
7946                 swap(array, i - 1, random.nextInt(i), 1);
7947             }
7948         }
7949     }
7950 
7951     /**
7952      * 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
7953      * algorithm</a>.
7954      * <p>
7955      * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7956      * </p>
7957      * <p>
7958      * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7959      * with a {@link SecureRandom} argument.
7960      * </p>
7961      *
7962      * @param array the array to shuffle.
7963      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7964      * @since 3.6
7965      */
7966     public static void shuffle(final long[] array) {
7967         shuffle(array, random());
7968     }
7969 
7970     /**
7971      * 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
7972      * algorithm</a>.
7973      *
7974      * @param array  the array to shuffle, no-op if {@code null}.
7975      * @param random the source of randomness used to permute the elements, no-op if {@code null}.
7976      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
7977      * @since 3.6
7978      */
7979     public static void shuffle(final long[] array, final Random random) {
7980         if (array != null && random != null) {
7981             for (int i = array.length; i > 1; i--) {
7982                 swap(array, i - 1, random.nextInt(i), 1);
7983             }
7984         }
7985     }
7986 
7987     /**
7988      * 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
7989      * algorithm</a>.
7990      * <p>
7991      * This method uses the current {@link ThreadLocalRandom} as its random number generator.
7992      * </p>
7993      * <p>
7994      * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
7995      * with a {@link SecureRandom} argument.
7996      * </p>
7997      *
7998      * @param array the array to shuffle.
7999      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8000      * @since 3.6
8001      */
8002     public static void shuffle(final Object[] array) {
8003         shuffle(array, random());
8004     }
8005 
8006     /**
8007      * 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
8008      * algorithm</a>.
8009      *
8010      * @param array  the array to shuffle, no-op if {@code null}.
8011      * @param random the source of randomness used to permute the elements, no-op if {@code null}.
8012      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8013      * @since 3.6
8014      */
8015     public static void shuffle(final Object[] array, final Random random) {
8016         if (array != null && random != null) {
8017             for (int i = array.length; i > 1; i--) {
8018                 swap(array, i - 1, random.nextInt(i), 1);
8019             }
8020         }
8021     }
8022 
8023     /**
8024      * 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
8025      * algorithm</a>.
8026      * <p>
8027      * This method uses the current {@link ThreadLocalRandom} as its random number generator.
8028      * </p>
8029      * <p>
8030      * Instances of {@link ThreadLocalRandom} are not cryptographically secure. For security-sensitive applications, consider using a {@code shuffle} method
8031      * with a {@link SecureRandom} argument.
8032      * </p>
8033      *
8034      * @param array the array to shuffle.
8035      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8036      * @since 3.6
8037      */
8038     public static void shuffle(final short[] array) {
8039         shuffle(array, random());
8040     }
8041 
8042     /**
8043      * 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
8044      * algorithm</a>.
8045      *
8046      * @param array  the array to shuffle, no-op if {@code null}.
8047      * @param random the source of randomness used to permute the elements, no-op if {@code null}.
8048      * @see <a href="https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle">Fisher-Yates shuffle algorithm</a>
8049      * @since 3.6
8050      */
8051     public static void shuffle(final short[] array, final Random random) {
8052         if (array != null && random != null) {
8053             for (int i = array.length; i > 1; i--) {
8054                 swap(array, i - 1, random.nextInt(i), 1);
8055             }
8056         }
8057     }
8058 
8059     /**
8060      * Tests whether the given data array starts with an expected array, for example, signature bytes.
8061      * <p>
8062      * If both arrays are null, the method returns true. The method return false when one array is null and the other not.
8063      * </p>
8064      *
8065      * @param data     The data to search, maybe larger than the expected data.
8066      * @param expected The expected data to find.
8067      * @return whether a match was found.
8068      * @since 3.18.0
8069      */
8070     public static boolean startsWith(final byte[] data, final byte[] expected) {
8071         if (data == expected) {
8072             return true;
8073         }
8074         if (data == null || expected == null) {
8075             return false;
8076         }
8077         final int dataLen = data.length;
8078         if (expected.length > dataLen) {
8079             return false;
8080         }
8081         if (expected.length == dataLen) {
8082             // delegate to Arrays.equals() which has optimizations on Java > 8
8083             return Arrays.equals(data, expected);
8084         }
8085         // Once we are on Java 9+ we can delegate to Arrays here as well (or not).
8086         for (int i = 0; i < expected.length; i++) {
8087             if (data[i] != expected[i]) {
8088                 return false;
8089             }
8090         }
8091         return true;
8092     }
8093 
8094     /**
8095      * Produces a new {@code boolean} array containing the elements between the start and end indices.
8096      * <p>
8097      * The start index is inclusive, the end index exclusive. Null array input produces null output.
8098      * </p>
8099      *
8100      * @param array               the input array.
8101      * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8102      * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8103      *                            (&gt;array.length) is demoted to array length.
8104      * @return a new array containing the elements between the start and end indices.
8105      * @since 2.1
8106      * @see Arrays#copyOfRange(boolean[], int, int)
8107      */
8108     public static boolean[] subarray(final boolean[] array, int startIndexInclusive, int endIndexExclusive) {
8109         if (array == null) {
8110             return null;
8111         }
8112         startIndexInclusive = max0(startIndexInclusive);
8113         endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8114         final int newSize = endIndexExclusive - startIndexInclusive;
8115         if (newSize <= 0) {
8116             return EMPTY_BOOLEAN_ARRAY;
8117         }
8118         return arraycopy(array, startIndexInclusive, 0, newSize, boolean[]::new);
8119     }
8120 
8121     /**
8122      * Produces a new {@code byte} array containing the elements between the start and end indices.
8123      * <p>
8124      * The start index is inclusive, the end index exclusive. Null array input produces null output.
8125      * </p>
8126      *
8127      * @param array               the input array.
8128      * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8129      * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8130      *                            (&gt;array.length) is demoted to array length.
8131      * @return a new array containing the elements between the start and end indices.
8132      * @since 2.1
8133      * @see Arrays#copyOfRange(byte[], int, int)
8134      */
8135     public static byte[] subarray(final byte[] array, int startIndexInclusive, int endIndexExclusive) {
8136         if (array == null) {
8137             return null;
8138         }
8139         startIndexInclusive = max0(startIndexInclusive);
8140         endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8141         final int newSize = endIndexExclusive - startIndexInclusive;
8142         if (newSize <= 0) {
8143             return EMPTY_BYTE_ARRAY;
8144         }
8145         return arraycopy(array, startIndexInclusive, 0, newSize, byte[]::new);
8146     }
8147 
8148     /**
8149      * Produces a new {@code char} array containing the elements between the start and end indices.
8150      * <p>
8151      * The start index is inclusive, the end index exclusive. Null array input produces null output.
8152      * </p>
8153      *
8154      * @param array               the input array.
8155      * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8156      * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8157      *                            (&gt;array.length) is demoted to array length.
8158      * @return a new array containing the elements between the start and end indices.
8159      * @since 2.1
8160      * @see Arrays#copyOfRange(char[], int, int)
8161      */
8162     public static char[] subarray(final char[] array, int startIndexInclusive, int endIndexExclusive) {
8163         if (array == null) {
8164             return null;
8165         }
8166         startIndexInclusive = max0(startIndexInclusive);
8167         endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8168         final int newSize = endIndexExclusive - startIndexInclusive;
8169         if (newSize <= 0) {
8170             return EMPTY_CHAR_ARRAY;
8171         }
8172         return arraycopy(array, startIndexInclusive, 0, newSize, char[]::new);
8173     }
8174 
8175     /**
8176      * Produces a new {@code double} array containing the elements between the start and end indices.
8177      * <p>
8178      * The start index is inclusive, the end index exclusive. Null array input produces null output.
8179      * </p>
8180      *
8181      * @param array               the input array.
8182      * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8183      * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8184      *                            (&gt;array.length) is demoted to array length.
8185      * @return a new array containing the elements between the start and end indices.
8186      * @since 2.1
8187      * @see Arrays#copyOfRange(double[], int, int)
8188      */
8189     public static double[] subarray(final double[] array, int startIndexInclusive, int endIndexExclusive) {
8190         if (array == null) {
8191             return null;
8192         }
8193         startIndexInclusive = max0(startIndexInclusive);
8194         endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8195         final int newSize = endIndexExclusive - startIndexInclusive;
8196         if (newSize <= 0) {
8197             return EMPTY_DOUBLE_ARRAY;
8198         }
8199         return arraycopy(array, startIndexInclusive, 0, newSize, double[]::new);
8200     }
8201 
8202     /**
8203      * Produces a new {@code float} array containing the elements between the start and end indices.
8204      * <p>
8205      * The start index is inclusive, the end index exclusive. Null array input produces null output.
8206      * </p>
8207      *
8208      * @param array               the input array.
8209      * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8210      * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8211      *                            (&gt;array.length) is demoted to array length.
8212      * @return a new array containing the elements between the start and end indices.
8213      * @since 2.1
8214      * @see Arrays#copyOfRange(float[], int, int)
8215      */
8216     public static float[] subarray(final float[] array, int startIndexInclusive, int endIndexExclusive) {
8217         if (array == null) {
8218             return null;
8219         }
8220         startIndexInclusive = max0(startIndexInclusive);
8221         endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8222         final int newSize = endIndexExclusive - startIndexInclusive;
8223         if (newSize <= 0) {
8224             return EMPTY_FLOAT_ARRAY;
8225         }
8226         return arraycopy(array, startIndexInclusive, 0, newSize, float[]::new);
8227     }
8228 
8229     /**
8230      * Produces a new {@code int} array containing the elements between the start and end indices.
8231      * <p>
8232      * The start index is inclusive, the end index exclusive. Null array input produces null output.
8233      * </p>
8234      *
8235      * @param array               the input array.
8236      * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8237      * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8238      *                            (&gt;array.length) is demoted to array length.
8239      * @return a new array containing the elements between the start and end indices.
8240      * @since 2.1
8241      * @see Arrays#copyOfRange(int[], int, int)
8242      */
8243     public static int[] subarray(final int[] array, int startIndexInclusive, int endIndexExclusive) {
8244         if (array == null) {
8245             return null;
8246         }
8247         startIndexInclusive = max0(startIndexInclusive);
8248         endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8249         final int newSize = endIndexExclusive - startIndexInclusive;
8250         if (newSize <= 0) {
8251             return EMPTY_INT_ARRAY;
8252         }
8253         return arraycopy(array, startIndexInclusive, 0, newSize, int[]::new);
8254     }
8255 
8256     /**
8257      * Produces a new {@code long} array containing the elements between the start and end indices.
8258      * <p>
8259      * The start index is inclusive, the end index exclusive. Null array input produces null output.
8260      * </p>
8261      *
8262      * @param array               the input array.
8263      * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8264      * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8265      *                            (&gt;array.length) is demoted to array length.
8266      * @return a new array containing the elements between the start and end indices.
8267      * @since 2.1
8268      * @see Arrays#copyOfRange(long[], int, int)
8269      */
8270     public static long[] subarray(final long[] array, int startIndexInclusive, int endIndexExclusive) {
8271         if (array == null) {
8272             return null;
8273         }
8274         startIndexInclusive = max0(startIndexInclusive);
8275         endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8276         final int newSize = endIndexExclusive - startIndexInclusive;
8277         if (newSize <= 0) {
8278             return EMPTY_LONG_ARRAY;
8279         }
8280         return arraycopy(array, startIndexInclusive, 0, newSize, long[]::new);
8281     }
8282 
8283     /**
8284      * Produces a new {@code short} array containing the elements between the start and end indices.
8285      * <p>
8286      * The start index is inclusive, the end index exclusive. Null array input produces null output.
8287      * </p>
8288      *
8289      * @param array               the input array.
8290      * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8291      * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8292      *                            (&gt;array.length) is demoted to array length.
8293      * @return a new array containing the elements between the start and end indices.
8294      * @since 2.1
8295      * @see Arrays#copyOfRange(short[], int, int)
8296      */
8297     public static short[] subarray(final short[] array, int startIndexInclusive, int endIndexExclusive) {
8298         if (array == null) {
8299             return null;
8300         }
8301         startIndexInclusive = max0(startIndexInclusive);
8302         endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8303         final int newSize = endIndexExclusive - startIndexInclusive;
8304         if (newSize <= 0) {
8305             return EMPTY_SHORT_ARRAY;
8306         }
8307         return arraycopy(array, startIndexInclusive, 0, newSize, short[]::new);
8308     }
8309 
8310     /**
8311      * Produces a new array containing the elements between the start and end indices.
8312      * <p>
8313      * The start index is inclusive, the end index exclusive. Null array input produces null output.
8314      * </p>
8315      * <p>
8316      * The component type of the subarray is always the same as that of the input array. Thus, if the input is an array of type {@link Date}, the following
8317      * usage is envisaged:
8318      * </p>
8319      *
8320      * <pre>
8321      *
8322      * Date[] someDates = (Date[]) ArrayUtils.subarray(allDates, 2, 5);
8323      * </pre>
8324      *
8325      * @param <T>                 the component type of the array.
8326      * @param array               the input array.
8327      * @param startIndexInclusive the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in an empty array.
8328      * @param endIndexExclusive   elements up to endIndex-1 are present in the returned subarray. Undervalue (&lt; startIndex) produces empty array, overvalue
8329      *                            (&gt;array.length) is demoted to array length.
8330      * @return a new array containing the elements between the start and end indices.
8331      * @since 2.1
8332      * @see Arrays#copyOfRange(Object[], int, int)
8333      */
8334     public static <T> T[] subarray(final T[] array, int startIndexInclusive, int endIndexExclusive) {
8335         if (array == null) {
8336             return null;
8337         }
8338         startIndexInclusive = max0(startIndexInclusive);
8339         endIndexExclusive = max0(Math.min(endIndexExclusive, array.length));
8340         final int newSize = endIndexExclusive - startIndexInclusive;
8341         final Class<T> type = getComponentType(array);
8342         if (newSize <= 0) {
8343             return newInstance(type, 0);
8344         }
8345         return arraycopy(array, startIndexInclusive, 0, newSize, () -> newInstance(type, newSize));
8346     }
8347 
8348     /**
8349      * Swaps two elements in the given boolean array.
8350      *
8351      * <p>There is no special handling for multi-dimensional arrays. This method
8352      * does nothing for a {@code null} or empty input array or for overflow indices.
8353      * Negative indices are promoted to 0(zero).</p>
8354      *
8355      * Examples:
8356      * <ul>
8357      *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8358      *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8359      *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8360      *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8361      *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8362      * </ul>
8363      *
8364      * @param array  the array to swap, may be {@code null}.
8365      * @param offset1 the index of the first element to swap.
8366      * @param offset2 the index of the second element to swap.
8367      * @since 3.5
8368      */
8369     public static void swap(final boolean[] array, final int offset1, final int offset2) {
8370         swap(array, offset1, offset2, 1);
8371     }
8372 
8373     /**
8374      * Swaps a series of elements in the given boolean array.
8375      *
8376      * <p>This method does nothing for a {@code null} or empty input array or
8377      * for overflow indices. Negative indices are promoted to 0(zero). If any
8378      * of the sub-arrays to swap falls outside of the given array, then the
8379      * swap is stopped at the end of the array and as many as possible elements
8380      * are swapped.</p>
8381      *
8382      * Examples:
8383      * <ul>
8384      *     <li>ArrayUtils.swap([true, false, true, false], 0, 2, 1) -&gt; [true, false, true, false]</li>
8385      *     <li>ArrayUtils.swap([true, false, true, false], 0, 0, 1) -&gt; [true, false, true, false]</li>
8386      *     <li>ArrayUtils.swap([true, false, true, false], 0, 2, 2) -&gt; [true, false, true, false]</li>
8387      *     <li>ArrayUtils.swap([true, false, true, false], -3, 2, 2) -&gt; [true, false, true, false]</li>
8388      *     <li>ArrayUtils.swap([true, false, true, false], 0, 3, 3) -&gt; [false, false, true, true]</li>
8389      * </ul>
8390      *
8391      * @param array the array to swap, may be {@code null}.
8392      * @param offset1 the index of the first element in the series to swap.
8393      * @param offset2 the index of the second element in the series to swap.
8394      * @param len the number of elements to swap starting with the given indices.
8395      * @since 3.5
8396      */
8397     public static void swap(final boolean[] array, int offset1, int offset2, int len) {
8398         if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8399             return;
8400         }
8401         offset1 = max0(offset1);
8402         offset2 = max0(offset2);
8403         len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8404         for (int i = 0; i < len; i++, offset1++, offset2++) {
8405             final boolean aux = array[offset1];
8406             array[offset1] = array[offset2];
8407             array[offset2] = aux;
8408         }
8409     }
8410 
8411     /**
8412      * Swaps two elements in the given byte array.
8413      *
8414      * <p>There is no special handling for multi-dimensional arrays. This method
8415      * does nothing for a {@code null} or empty input array or for overflow indices.
8416      * Negative indices are promoted to 0(zero).</p>
8417      *
8418      * Examples:
8419      * <ul>
8420      *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8421      *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8422      *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8423      *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8424      *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8425      * </ul>
8426      *
8427      * @param array  the array to swap, may be {@code null}.
8428      * @param offset1 the index of the first element to swap.
8429      * @param offset2 the index of the second element to swap.
8430      * @since 3.5
8431      */
8432     public static void swap(final byte[] array, final int offset1, final int offset2) {
8433         swap(array, offset1, offset2, 1);
8434     }
8435 
8436     /**
8437      * Swaps a series of elements in the given byte array.
8438      *
8439      * <p>This method does nothing for a {@code null} or empty input array or
8440      * for overflow indices. Negative indices are promoted to 0(zero). If any
8441      * of the sub-arrays to swap falls outside of the given array, then the
8442      * swap is stopped at the end of the array and as many as possible elements
8443      * are swapped.</p>
8444      *
8445      * Examples:
8446      * <ul>
8447      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8448      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8449      *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8450      *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8451      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8452      * </ul>
8453      *
8454      * @param array the array to swap, may be {@code null}.
8455      * @param offset1 the index of the first element in the series to swap.
8456      * @param offset2 the index of the second element in the series to swap.
8457      * @param len the number of elements to swap starting with the given indices.
8458      * @since 3.5
8459      */
8460     public static void swap(final byte[] array, int offset1, int offset2, int len) {
8461         if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8462             return;
8463         }
8464         offset1 = max0(offset1);
8465         offset2 = max0(offset2);
8466         len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8467         for (int i = 0; i < len; i++, offset1++, offset2++) {
8468             final byte aux = array[offset1];
8469             array[offset1] = array[offset2];
8470             array[offset2] = aux;
8471         }
8472     }
8473 
8474     /**
8475      * Swaps two elements in the given char array.
8476      *
8477      * <p>There is no special handling for multi-dimensional arrays. This method
8478      * does nothing for a {@code null} or empty input array or for overflow indices.
8479      * Negative indices are promoted to 0(zero).</p>
8480      *
8481      * Examples:
8482      * <ul>
8483      *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8484      *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8485      *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8486      *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8487      *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8488      * </ul>
8489      *
8490      * @param array  the array to swap, may be {@code null}.
8491      * @param offset1 the index of the first element to swap.
8492      * @param offset2 the index of the second element to swap.
8493      * @since 3.5
8494      */
8495     public static void swap(final char[] array, final int offset1, final int offset2) {
8496         swap(array, offset1, offset2, 1);
8497     }
8498 
8499     /**
8500      * Swaps a series of elements in the given char array.
8501      *
8502      * <p>This method does nothing for a {@code null} or empty input array or
8503      * for overflow indices. Negative indices are promoted to 0(zero). If any
8504      * of the sub-arrays to swap falls outside of the given array, then the
8505      * swap is stopped at the end of the array and as many as possible elements
8506      * are swapped.</p>
8507      *
8508      * Examples:
8509      * <ul>
8510      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8511      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8512      *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8513      *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8514      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8515      * </ul>
8516      *
8517      * @param array the array to swap, may be {@code null}.
8518      * @param offset1 the index of the first element in the series to swap.
8519      * @param offset2 the index of the second element in the series to swap.
8520      * @param len the number of elements to swap starting with the given indices.
8521      * @since 3.5
8522      */
8523     public static void swap(final char[] array, int offset1, int offset2, int len) {
8524         if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8525             return;
8526         }
8527         offset1 = max0(offset1);
8528         offset2 = max0(offset2);
8529         len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8530         for (int i = 0; i < len; i++, offset1++, offset2++) {
8531             final char aux = array[offset1];
8532             array[offset1] = array[offset2];
8533             array[offset2] = aux;
8534         }
8535     }
8536 
8537     /**
8538      * Swaps two elements in the given double array.
8539      *
8540      * <p>There is no special handling for multi-dimensional arrays. This method
8541      * does nothing for a {@code null} or empty input array or for overflow indices.
8542      * Negative indices are promoted to 0(zero).</p>
8543      *
8544      * Examples:
8545      * <ul>
8546      *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8547      *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8548      *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8549      *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8550      *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8551      * </ul>
8552      *
8553      * @param array  the array to swap, may be {@code null}.
8554      * @param offset1 the index of the first element to swap.
8555      * @param offset2 the index of the second element to swap.
8556      * @since 3.5
8557      */
8558     public static void swap(final double[] array, final int offset1, final int offset2) {
8559         swap(array, offset1, offset2, 1);
8560     }
8561 
8562     /**
8563      * Swaps a series of elements in the given double array.
8564      *
8565      * <p>This method does nothing for a {@code null} or empty input array or
8566      * for overflow indices. Negative indices are promoted to 0(zero). If any
8567      * of the sub-arrays to swap falls outside of the given array, then the
8568      * swap is stopped at the end of the array and as many as possible elements
8569      * are swapped.</p>
8570      *
8571      * Examples:
8572      * <ul>
8573      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8574      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8575      *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8576      *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8577      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8578      * </ul>
8579      *
8580      * @param array the array to swap, may be {@code null}.
8581      * @param offset1 the index of the first element in the series to swap.
8582      * @param offset2 the index of the second element in the series to swap.
8583      * @param len the number of elements to swap starting with the given indices.
8584      * @since 3.5
8585      */
8586     public static void swap(final double[] array,  int offset1, int offset2, int len) {
8587         if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8588             return;
8589         }
8590         offset1 = max0(offset1);
8591         offset2 = max0(offset2);
8592         len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8593         for (int i = 0; i < len; i++, offset1++, offset2++) {
8594             final double aux = array[offset1];
8595             array[offset1] = array[offset2];
8596             array[offset2] = aux;
8597         }
8598     }
8599 
8600     /**
8601      * Swaps two elements in the given float array.
8602      *
8603      * <p>There is no special handling for multi-dimensional arrays. This method
8604      * does nothing for a {@code null} or empty input array or for overflow indices.
8605      * Negative indices are promoted to 0(zero).</p>
8606      *
8607      * Examples:
8608      * <ul>
8609      *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8610      *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8611      *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8612      *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8613      *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8614      * </ul>
8615      *
8616      * @param array  the array to swap, may be {@code null}.
8617      * @param offset1 the index of the first element to swap.
8618      * @param offset2 the index of the second element to swap.
8619      * @since 3.5
8620      */
8621     public static void swap(final float[] array, final int offset1, final int offset2) {
8622         swap(array, offset1, offset2, 1);
8623     }
8624 
8625     /**
8626      * Swaps a series of elements in the given float array.
8627      *
8628      * <p>This method does nothing for a {@code null} or empty input array or
8629      * for overflow indices. Negative indices are promoted to 0(zero). If any
8630      * of the sub-arrays to swap falls outside of the given array, then the
8631      * swap is stopped at the end of the array and as many as possible elements
8632      * are swapped.</p>
8633      *
8634      * Examples:
8635      * <ul>
8636      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8637      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8638      *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8639      *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8640      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8641      * </ul>
8642      *
8643      * @param array the array to swap, may be {@code null}.
8644      * @param offset1 the index of the first element in the series to swap.
8645      * @param offset2 the index of the second element in the series to swap.
8646      * @param len the number of elements to swap starting with the given indices.
8647      * @since 3.5
8648      */
8649     public static void swap(final float[] array, int offset1, int offset2, int len) {
8650         if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8651             return;
8652         }
8653         offset1 = max0(offset1);
8654         offset2 = max0(offset2);
8655         len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8656         for (int i = 0; i < len; i++, offset1++, offset2++) {
8657             final float aux = array[offset1];
8658             array[offset1] = array[offset2];
8659             array[offset2] = aux;
8660         }
8661 
8662     }
8663 
8664     /**
8665      * Swaps two elements in the given int array.
8666      *
8667      * <p>There is no special handling for multi-dimensional arrays. This method
8668      * does nothing for a {@code null} or empty input array or for overflow indices.
8669      * Negative indices are promoted to 0(zero).</p>
8670      *
8671      * Examples:
8672      * <ul>
8673      *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8674      *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8675      *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8676      *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8677      *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8678      * </ul>
8679      *
8680      * @param array  the array to swap, may be {@code null}.
8681      * @param offset1 the index of the first element to swap.
8682      * @param offset2 the index of the second element to swap.
8683      * @since 3.5
8684      */
8685     public static void swap(final int[] array, final int offset1, final int offset2) {
8686         swap(array, offset1, offset2, 1);
8687     }
8688 
8689     /**
8690      * Swaps a series of elements in the given int array.
8691      *
8692      * <p>This method does nothing for a {@code null} or empty input array or
8693      * for overflow indices. Negative indices are promoted to 0(zero). If any
8694      * of the sub-arrays to swap falls outside of the given array, then the
8695      * swap is stopped at the end of the array and as many as possible elements
8696      * are swapped.</p>
8697      *
8698      * Examples:
8699      * <ul>
8700      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8701      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8702      *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8703      *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8704      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8705      * </ul>
8706      *
8707      * @param array the array to swap, may be {@code null}.
8708      * @param offset1 the index of the first element in the series to swap.
8709      * @param offset2 the index of the second element in the series to swap.
8710      * @param len the number of elements to swap starting with the given indices.
8711      * @since 3.5
8712      */
8713     public static void swap(final int[] array,  int offset1, int offset2, int len) {
8714         if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8715             return;
8716         }
8717         offset1 = max0(offset1);
8718         offset2 = max0(offset2);
8719         len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8720         for (int i = 0; i < len; i++, offset1++, offset2++) {
8721             final int aux = array[offset1];
8722             array[offset1] = array[offset2];
8723             array[offset2] = aux;
8724         }
8725     }
8726 
8727     /**
8728      * Swaps two elements in the given long array.
8729      *
8730      * <p>There is no special handling for multi-dimensional arrays. This method
8731      * does nothing for a {@code null} or empty input array or for overflow indices.
8732      * Negative indices are promoted to 0(zero).</p>
8733      *
8734      * Examples:
8735      * <ul>
8736      *     <li>ArrayUtils.swap([true, false, true], 0, 2) -&gt; [true, false, true]</li>
8737      *     <li>ArrayUtils.swap([true, false, true], 0, 0) -&gt; [true, false, true]</li>
8738      *     <li>ArrayUtils.swap([true, false, true], 1, 0) -&gt; [false, true, true]</li>
8739      *     <li>ArrayUtils.swap([true, false, true], 0, 5) -&gt; [true, false, true]</li>
8740      *     <li>ArrayUtils.swap([true, false, true], -1, 1) -&gt; [false, true, true]</li>
8741      * </ul>
8742      *
8743      * @param array  the array to swap, may be {@code null}.
8744      * @param offset1 the index of the first element to swap.
8745      * @param offset2 the index of the second element to swap.
8746      * @since 3.5
8747      */
8748     public static void swap(final long[] array, final int offset1, final int offset2) {
8749         swap(array, offset1, offset2, 1);
8750     }
8751 
8752     /**
8753      * Swaps a series of elements in the given long array.
8754      *
8755      * <p>This method does nothing for a {@code null} or empty input array or
8756      * for overflow indices. Negative indices are promoted to 0(zero). If any
8757      * of the sub-arrays to swap falls outside of the given array, then the
8758      * swap is stopped at the end of the array and as many as possible elements
8759      * are swapped.</p>
8760      *
8761      * Examples:
8762      * <ul>
8763      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8764      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8765      *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8766      *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8767      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8768      * </ul>
8769      *
8770      * @param array the array to swap, may be {@code null}.
8771      * @param offset1 the index of the first element in the series to swap.
8772      * @param offset2 the index of the second element in the series to swap.
8773      * @param len the number of elements to swap starting with the given indices.
8774      * @since 3.5
8775      */
8776     public static void swap(final long[] array,  int offset1, int offset2, int len) {
8777         if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8778             return;
8779         }
8780         offset1 = max0(offset1);
8781         offset2 = max0(offset2);
8782         len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8783         for (int i = 0; i < len; i++, offset1++, offset2++) {
8784             final long aux = array[offset1];
8785             array[offset1] = array[offset2];
8786             array[offset2] = aux;
8787         }
8788     }
8789 
8790     /**
8791      * Swaps two elements in the given array.
8792      *
8793      * <p>There is no special handling for multi-dimensional arrays. This method
8794      * does nothing for a {@code null} or empty input array or for overflow indices.
8795      * Negative indices are promoted to 0(zero).</p>
8796      *
8797      * Examples:
8798      * <ul>
8799      *     <li>ArrayUtils.swap(["1", "2", "3"], 0, 2) -&gt; ["3", "2", "1"]</li>
8800      *     <li>ArrayUtils.swap(["1", "2", "3"], 0, 0) -&gt; ["1", "2", "3"]</li>
8801      *     <li>ArrayUtils.swap(["1", "2", "3"], 1, 0) -&gt; ["2", "1", "3"]</li>
8802      *     <li>ArrayUtils.swap(["1", "2", "3"], 0, 5) -&gt; ["1", "2", "3"]</li>
8803      *     <li>ArrayUtils.swap(["1", "2", "3"], -1, 1) -&gt; ["2", "1", "3"]</li>
8804      * </ul>
8805      *
8806      * @param array the array to swap, may be {@code null}.
8807      * @param offset1 the index of the first element to swap.
8808      * @param offset2 the index of the second element to swap.
8809      * @since 3.5
8810      */
8811     public static void swap(final Object[] array, final int offset1, final int offset2) {
8812         swap(array, offset1, offset2, 1);
8813     }
8814 
8815     /**
8816      * Swaps a series of elements in the given array.
8817      *
8818      * <p>This method does nothing for a {@code null} or empty input array or
8819      * for overflow indices. Negative indices are promoted to 0(zero). If any
8820      * of the sub-arrays to swap falls outside of the given array, then the
8821      * swap is stopped at the end of the array and as many as possible elements
8822      * are swapped.</p>
8823      *
8824      * Examples:
8825      * <ul>
8826      *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 0, 2, 1) -&gt; ["3", "2", "1", "4"]</li>
8827      *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 0, 0, 1) -&gt; ["1", "2", "3", "4"]</li>
8828      *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 2, 0, 2) -&gt; ["3", "4", "1", "2"]</li>
8829      *     <li>ArrayUtils.swap(["1", "2", "3", "4"], -3, 2, 2) -&gt; ["3", "4", "1", "2"]</li>
8830      *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 0, 3, 3) -&gt; ["4", "2", "3", "1"]</li>
8831      * </ul>
8832      *
8833      * @param array the array to swap, may be {@code null}.
8834      * @param offset1 the index of the first element in the series to swap.
8835      * @param offset2 the index of the second element in the series to swap.
8836      * @param len the number of elements to swap starting with the given indices.
8837      * @since 3.5
8838      */
8839     public static void swap(final Object[] array,  int offset1, int offset2, int len) {
8840         if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8841             return;
8842         }
8843         offset1 = max0(offset1);
8844         offset2 = max0(offset2);
8845         len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8846         for (int i = 0; i < len; i++, offset1++, offset2++) {
8847             final Object aux = array[offset1];
8848             array[offset1] = array[offset2];
8849             array[offset2] = aux;
8850         }
8851     }
8852 
8853     /**
8854      * Swaps two elements in the given short array.
8855      *
8856      * <p>There is no special handling for multi-dimensional arrays. This method
8857      * does nothing for a {@code null} or empty input array or for overflow indices.
8858      * Negative indices are promoted to 0(zero).</p>
8859      *
8860      * Examples:
8861      * <ul>
8862      *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
8863      *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
8864      *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
8865      *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
8866      *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
8867      * </ul>
8868      *
8869      * @param array  the array to swap, may be {@code null}.
8870      * @param offset1 the index of the first element to swap.
8871      * @param offset2 the index of the second element to swap.
8872      * @since 3.5
8873      */
8874     public static void swap(final short[] array, final int offset1, final int offset2) {
8875         swap(array, offset1, offset2, 1);
8876     }
8877 
8878     /**
8879      * Swaps a series of elements in the given short array.
8880      *
8881      * <p>This method does nothing for a {@code null} or empty input array or
8882      * for overflow indices. Negative indices are promoted to 0(zero). If any
8883      * of the sub-arrays to swap falls outside of the given array, then the
8884      * swap is stopped at the end of the array and as many as possible elements
8885      * are swapped.</p>
8886      *
8887      * Examples:
8888      * <ul>
8889      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
8890      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
8891      *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
8892      *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
8893      *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
8894      * </ul>
8895      *
8896      * @param array the array to swap, may be {@code null}.
8897      * @param offset1 the index of the first element in the series to swap.
8898      * @param offset2 the index of the second element in the series to swap.
8899      * @param len the number of elements to swap starting with the given indices.
8900      * @since 3.5
8901      */
8902     public static void swap(final short[] array, int offset1, int offset2, int len) {
8903         if (isEmpty(array) || offset1 >= array.length || offset2 >= array.length) {
8904             return;
8905         }
8906         offset1 = max0(offset1);
8907         offset2 = max0(offset2);
8908         if (offset1 == offset2) {
8909             return;
8910         }
8911         len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
8912         for (int i = 0; i < len; i++, offset1++, offset2++) {
8913             final short aux = array[offset1];
8914             array[offset1] = array[offset2];
8915             array[offset2] = aux;
8916         }
8917     }
8918 
8919     /**
8920      * Create a type-safe generic array.
8921      * <p>
8922      * The Java language does not allow an array to be created from a generic type:
8923      * </p>
8924      * <pre>
8925     public static &lt;T&gt; T[] createAnArray(int size) {
8926         return new T[size]; // compiler error here
8927     }
8928     public static &lt;T&gt; T[] createAnArray(int size) {
8929         return (T[]) new Object[size]; // ClassCastException at runtime
8930     }
8931      * </pre>
8932      * <p>
8933      * Therefore new arrays of generic types can be created with this method.
8934      * For example, an array of Strings can be created:
8935      * </p>
8936      * <pre>{@code
8937      * String[] array = ArrayUtils.toArray("1", "2");
8938      * String[] emptyArray = ArrayUtils.<String>toArray();
8939      * }</pre>
8940      * <p>
8941      * The method is typically used in scenarios, where the caller itself uses generic types
8942      * that have to be combined into an array.
8943      * </p>
8944      * <p>
8945      * Note, this method makes only sense to provide arguments of the same type so that the
8946      * compiler can deduce the type of the array itself. While it is possible to select the
8947      * type explicitly like in
8948      * {@code Number[] array = ArrayUtils.<Number>toArray(Integer.valueOf(42), Double.valueOf(Math.PI))},
8949      * there is no real advantage when compared to
8950      * {@code new Number[] {Integer.valueOf(42), Double.valueOf(Math.PI)}}.
8951      * </p>
8952      *
8953      * @param  <T>   the array's element type.
8954      * @param  items  the varargs array items, null allowed.
8955      * @return the array, not null unless a null array is passed in.
8956      * @since 3.0
8957      */
8958     public static <T> T[] toArray(@SuppressWarnings("unchecked") final T... items) {
8959         return items;
8960     }
8961 
8962     /**
8963      * Converts the given array into a {@link java.util.Map}. Each element of the array must be either a {@link java.util.Map.Entry} or an Array, containing at
8964      * least two elements, where the first element is used as key and the second as value.
8965      * <p>
8966      * This method can be used to initialize:
8967      * </p>
8968      *
8969      * <pre>
8970      *
8971      * // Create a Map mapping colors.
8972      * Map colorMap = ArrayUtils.toMap(new String[][] { { "RED", "#FF0000" }, { "GREEN", "#00FF00" }, { "BLUE", "#0000FF" } });
8973      * </pre>
8974      * <p>
8975      * This method returns {@code null} for a {@code null} input array.
8976      * </p>
8977      *
8978      * @param array an array whose elements are either a {@link java.util.Map.Entry} or an Array containing at least two elements, may be {@code null}.
8979      * @return a {@link Map} that was created from the array.
8980      * @throws IllegalArgumentException if one element of this Array is itself an Array containing less than two elements.
8981      * @throws IllegalArgumentException if the array contains elements other than {@link java.util.Map.Entry} and an Array.
8982      */
8983     public static Map<Object, Object> toMap(final Object[] array) {
8984         if (array == null) {
8985             return null;
8986         }
8987         final Map<Object, Object> map = new HashMap<>((int) (array.length * 1.5));
8988         for (int i = 0; i < array.length; i++) {
8989             final Object object = array[i];
8990             if (object instanceof Map.Entry<?, ?>) {
8991                 final Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
8992                 map.put(entry.getKey(), entry.getValue());
8993             } else if (object instanceof Object[]) {
8994                 final Object[] entry = (Object[]) object;
8995                 if (entry.length < 2) {
8996                     throw new IllegalArgumentException("Array element " + i + ", '"
8997                         + object
8998                         + "', has a length less than 2");
8999                 }
9000                 map.put(entry[0], entry[1]);
9001             } else {
9002                 throw new IllegalArgumentException("Array element " + i + ", '"
9003                         + object
9004                         + "', is neither of type Map.Entry nor an Array");
9005             }
9006         }
9007         return map;
9008     }
9009 
9010     /**
9011      * Converts an array of primitive booleans to objects.
9012      *
9013      * <p>This method returns {@code null} for a {@code null} input array.</p>
9014      *
9015      * @param array  a {@code boolean} array.
9016      * @return a {@link Boolean} array, {@code null} if null array input.
9017      */
9018     public static Boolean[] toObject(final boolean[] array) {
9019         if (array == null) {
9020             return null;
9021         }
9022         if (array.length == 0) {
9023             return EMPTY_BOOLEAN_OBJECT_ARRAY;
9024         }
9025         return setAll(new Boolean[array.length], i -> array[i] ? Boolean.TRUE : Boolean.FALSE);
9026     }
9027 
9028     /**
9029      * Converts an array of primitive bytes to objects.
9030      *
9031      * <p>This method returns {@code null} for a {@code null} input array.</p>
9032      *
9033      * @param array  a {@code byte} array.
9034      * @return a {@link Byte} array, {@code null} if null array input.
9035      */
9036     public static Byte[] toObject(final byte[] array) {
9037         if (array == null) {
9038             return null;
9039         }
9040         if (array.length == 0) {
9041             return EMPTY_BYTE_OBJECT_ARRAY;
9042         }
9043         return setAll(new Byte[array.length], i -> Byte.valueOf(array[i]));
9044     }
9045 
9046     /**
9047      * Converts an array of primitive chars to objects.
9048      *
9049      * <p>This method returns {@code null} for a {@code null} input array.</p>
9050      *
9051      * @param array a {@code char} array.
9052      * @return a {@link Character} array, {@code null} if null array input.
9053      */
9054     public static Character[] toObject(final char[] array) {
9055         if (array == null) {
9056             return null;
9057         }
9058         if (array.length == 0) {
9059             return EMPTY_CHARACTER_OBJECT_ARRAY;
9060         }
9061         return setAll(new Character[array.length], i -> Character.valueOf(array[i]));
9062      }
9063 
9064     /**
9065      * Converts an array of primitive doubles to objects.
9066      *
9067      * <p>This method returns {@code null} for a {@code null} input array.</p>
9068      *
9069      * @param array  a {@code double} array.
9070      * @return a {@link Double} array, {@code null} if null array input.
9071      */
9072     public static Double[] toObject(final double[] array) {
9073         if (array == null) {
9074             return null;
9075         }
9076         if (array.length == 0) {
9077             return EMPTY_DOUBLE_OBJECT_ARRAY;
9078         }
9079         return setAll(new Double[array.length], i -> Double.valueOf(array[i]));
9080     }
9081 
9082     /**
9083      * Converts an array of primitive floats to objects.
9084      *
9085      * <p>This method returns {@code null} for a {@code null} input array.</p>
9086      *
9087      * @param array  a {@code float} array.
9088      * @return a {@link Float} array, {@code null} if null array input.
9089      */
9090     public static Float[] toObject(final float[] array) {
9091         if (array == null) {
9092             return null;
9093         }
9094         if (array.length == 0) {
9095             return EMPTY_FLOAT_OBJECT_ARRAY;
9096         }
9097         return setAll(new Float[array.length], i -> Float.valueOf(array[i]));
9098     }
9099 
9100     /**
9101      * Converts an array of primitive ints to objects.
9102      *
9103      * <p>This method returns {@code null} for a {@code null} input array.</p>
9104      *
9105      * @param array  an {@code int} array.
9106      * @return an {@link Integer} array, {@code null} if null array input.
9107      */
9108     public static Integer[] toObject(final int[] array) {
9109         if (array == null) {
9110             return null;
9111         }
9112         if (array.length == 0) {
9113             return EMPTY_INTEGER_OBJECT_ARRAY;
9114         }
9115         return setAll(new Integer[array.length], i -> Integer.valueOf(array[i]));
9116     }
9117 
9118     /**
9119      * Converts an array of primitive longs to objects.
9120      *
9121      * <p>This method returns {@code null} for a {@code null} input array.</p>
9122      *
9123      * @param array  a {@code long} array.
9124      * @return a {@link Long} array, {@code null} if null array input.
9125      */
9126     public static Long[] toObject(final long[] array) {
9127         if (array == null) {
9128             return null;
9129         }
9130         if (array.length == 0) {
9131             return EMPTY_LONG_OBJECT_ARRAY;
9132         }
9133         return setAll(new Long[array.length], i -> Long.valueOf(array[i]));
9134     }
9135 
9136     /**
9137      * Converts an array of primitive shorts to objects.
9138      *
9139      * <p>This method returns {@code null} for a {@code null} input array.</p>
9140      *
9141      * @param array  a {@code short} array.
9142      * @return a {@link Short} array, {@code null} if null array input.
9143      */
9144     public static Short[] toObject(final short[] array) {
9145         if (array == null) {
9146             return null;
9147         }
9148         if (array.length == 0) {
9149             return EMPTY_SHORT_OBJECT_ARRAY;
9150         }
9151         return setAll(new Short[array.length], i -> Short.valueOf(array[i]));
9152     }
9153 
9154     /**
9155      * Converts an array of object Booleans to primitives.
9156      * <p>
9157      * This method returns {@code null} for a {@code null} input array.
9158      * </p>
9159      * <p>
9160      * Null array elements map to false, like {@code Boolean.parseBoolean(null)} and its callers return false.
9161      * </p>
9162      *
9163      * @param array a {@link Boolean} array, may be {@code null}.
9164      * @return a {@code boolean} array, {@code null} if null array input.
9165      */
9166     public static boolean[] toPrimitive(final Boolean[] array) {
9167         return toPrimitive(array, false);
9168     }
9169 
9170     /**
9171      * Converts an array of object Booleans to primitives handling {@code null}.
9172      * <p>
9173      * This method returns {@code null} for a {@code null} input array.
9174      * </p>
9175      *
9176      * @param array  a {@link Boolean} array, may be {@code null}.
9177      * @param valueForNull  the value to insert if {@code null} found.
9178      * @return a {@code boolean} array, {@code null} if null array input.
9179      */
9180     public static boolean[] toPrimitive(final Boolean[] array, final boolean valueForNull) {
9181         if (array == null) {
9182             return null;
9183         }
9184         if (array.length == 0) {
9185             return EMPTY_BOOLEAN_ARRAY;
9186         }
9187         final boolean[] result = new boolean[array.length];
9188         for (int i = 0; i < array.length; i++) {
9189             final Boolean b = array[i];
9190             result[i] = b == null ? valueForNull : b.booleanValue();
9191         }
9192         return result;
9193     }
9194 
9195     /**
9196      * Converts an array of object Bytes to primitives.
9197      * <p>
9198      * This method returns {@code null} for a {@code null} input array.
9199      * </p>
9200      *
9201      * @param array  a {@link Byte} array, may be {@code null}.
9202      * @return a {@code byte} array, {@code null} if null array input.
9203      * @throws NullPointerException if an array element is {@code null}.
9204      */
9205     public static byte[] toPrimitive(final Byte[] array) {
9206         if (array == null) {
9207             return null;
9208         }
9209         if (array.length == 0) {
9210             return EMPTY_BYTE_ARRAY;
9211         }
9212         final byte[] result = new byte[array.length];
9213         for (int i = 0; i < array.length; i++) {
9214             result[i] = array[i].byteValue();
9215         }
9216         return result;
9217     }
9218 
9219     /**
9220      * Converts an array of object Bytes to primitives handling {@code null}.
9221      * <p>
9222      * This method returns {@code null} for a {@code null} input array.
9223      * </p>
9224      *
9225      * @param array  a {@link Byte} array, may be {@code null}.
9226      * @param valueForNull  the value to insert if {@code null} found.
9227      * @return a {@code byte} array, {@code null} if null array input.
9228      */
9229     public static byte[] toPrimitive(final Byte[] array, final byte valueForNull) {
9230         if (array == null) {
9231             return null;
9232         }
9233         if (array.length == 0) {
9234             return EMPTY_BYTE_ARRAY;
9235         }
9236         final byte[] result = new byte[array.length];
9237         for (int i = 0; i < array.length; i++) {
9238             final Byte b = array[i];
9239             result[i] = b == null ? valueForNull : b.byteValue();
9240         }
9241         return result;
9242     }
9243 
9244     /**
9245      * Converts an array of object Characters to primitives.
9246      * <p>
9247      * This method returns {@code null} for a {@code null} input array.
9248      * </p>
9249      *
9250      * @param array  a {@link Character} array, may be {@code null}.
9251      * @return a {@code char} array, {@code null} if null array input.
9252      * @throws NullPointerException if an array element is {@code null}.
9253      */
9254     public static char[] toPrimitive(final Character[] array) {
9255         if (array == null) {
9256             return null;
9257         }
9258         if (array.length == 0) {
9259             return EMPTY_CHAR_ARRAY;
9260         }
9261         final char[] result = new char[array.length];
9262         for (int i = 0; i < array.length; i++) {
9263             result[i] = array[i].charValue();
9264         }
9265         return result;
9266     }
9267 
9268     /**
9269      * Converts an array of object Character to primitives handling {@code null}.
9270      * <p>
9271      * This method returns {@code null} for a {@code null} input array.
9272      * </p>
9273      *
9274      * @param array  a {@link Character} array, may be {@code null}.
9275      * @param valueForNull  the value to insert if {@code null} found.
9276      * @return a {@code char} array, {@code null} if null array input.
9277      */
9278     public static char[] toPrimitive(final Character[] array, final char valueForNull) {
9279         if (array == null) {
9280             return null;
9281         }
9282         if (array.length == 0) {
9283             return EMPTY_CHAR_ARRAY;
9284         }
9285         final char[] result = new char[array.length];
9286         for (int i = 0; i < array.length; i++) {
9287             final Character b = array[i];
9288             result[i] = b == null ? valueForNull : b.charValue();
9289         }
9290         return result;
9291     }
9292 
9293     /**
9294      * Converts an array of object Doubles to primitives.
9295      * <p>
9296      * This method returns {@code null} for a {@code null} input array.
9297      * </p>
9298      *
9299      * @param array  a {@link Double} array, may be {@code null}.
9300      * @return a {@code double} array, {@code null} if null array input.
9301      * @throws NullPointerException if an array element is {@code null}.
9302      */
9303     public static double[] toPrimitive(final Double[] array) {
9304         if (array == null) {
9305             return null;
9306         }
9307         if (array.length == 0) {
9308             return EMPTY_DOUBLE_ARRAY;
9309         }
9310         final double[] result = new double[array.length];
9311         for (int i = 0; i < array.length; i++) {
9312             result[i] = array[i].doubleValue();
9313         }
9314         return result;
9315     }
9316 
9317     /**
9318      * Converts an array of object Doubles to primitives handling {@code null}.
9319      * <p>
9320      * This method returns {@code null} for a {@code null} input array.
9321      * </p>
9322      *
9323      * @param array  a {@link Double} array, may be {@code null}.
9324      * @param valueForNull  the value to insert if {@code null} found.
9325      * @return a {@code double} array, {@code null} if null array input.
9326      */
9327     public static double[] toPrimitive(final Double[] array, final double valueForNull) {
9328         if (array == null) {
9329             return null;
9330         }
9331         if (array.length == 0) {
9332             return EMPTY_DOUBLE_ARRAY;
9333         }
9334         final double[] result = new double[array.length];
9335         for (int i = 0; i < array.length; i++) {
9336             final Double b = array[i];
9337             result[i] = b == null ? valueForNull : b.doubleValue();
9338         }
9339         return result;
9340     }
9341 
9342     /**
9343      * Converts an array of object Floats to primitives.
9344      * <p>
9345      * This method returns {@code null} for a {@code null} input array.
9346      * </p>
9347      *
9348      * @param array  a {@link Float} array, may be {@code null}.
9349      * @return a {@code float} array, {@code null} if null array input.
9350      * @throws NullPointerException if an array element is {@code null}.
9351      */
9352     public static float[] toPrimitive(final Float[] array) {
9353         if (array == null) {
9354             return null;
9355         }
9356         if (array.length == 0) {
9357             return EMPTY_FLOAT_ARRAY;
9358         }
9359         final float[] result = new float[array.length];
9360         for (int i = 0; i < array.length; i++) {
9361             result[i] = array[i].floatValue();
9362         }
9363         return result;
9364     }
9365 
9366     /**
9367      * Converts an array of object Floats to primitives handling {@code null}.
9368      * <p>
9369      * This method returns {@code null} for a {@code null} input array.
9370      * </p>
9371      *
9372      * @param array  a {@link Float} array, may be {@code null}.
9373      * @param valueForNull  the value to insert if {@code null} found.
9374      * @return a {@code float} array, {@code null} if null array input.
9375      */
9376     public static float[] toPrimitive(final Float[] array, final float valueForNull) {
9377         if (array == null) {
9378             return null;
9379         }
9380         if (array.length == 0) {
9381             return EMPTY_FLOAT_ARRAY;
9382         }
9383         final float[] result = new float[array.length];
9384         for (int i = 0; i < array.length; i++) {
9385             final Float b = array[i];
9386             result[i] = b == null ? valueForNull : b.floatValue();
9387         }
9388         return result;
9389     }
9390 
9391     /**
9392      * Converts an array of object Integers to primitives.
9393      * <p>
9394      * This method returns {@code null} for a {@code null} input array.
9395      * </p>
9396      *
9397      * @param array  a {@link Integer} array, may be {@code null}.
9398      * @return an {@code int} array, {@code null} if null array input.
9399      * @throws NullPointerException if an array element is {@code null}.
9400      */
9401     public static int[] toPrimitive(final Integer[] array) {
9402         if (array == null) {
9403             return null;
9404         }
9405         if (array.length == 0) {
9406             return EMPTY_INT_ARRAY;
9407         }
9408         final int[] result = new int[array.length];
9409         for (int i = 0; i < array.length; i++) {
9410             result[i] = array[i].intValue();
9411         }
9412         return result;
9413     }
9414 
9415     /**
9416      * Converts an array of object Integer to primitives handling {@code null}.
9417      * <p>
9418      * This method returns {@code null} for a {@code null} input array.
9419      * </p>
9420      *
9421      * @param array  a {@link Integer} array, may be {@code null}.
9422      * @param valueForNull  the value to insert if {@code null} found.
9423      * @return an {@code int} array, {@code null} if null array input.
9424      */
9425     public static int[] toPrimitive(final Integer[] array, final int valueForNull) {
9426         if (array == null) {
9427             return null;
9428         }
9429         if (array.length == 0) {
9430             return EMPTY_INT_ARRAY;
9431         }
9432         final int[] result = new int[array.length];
9433         for (int i = 0; i < array.length; i++) {
9434             final Integer b = array[i];
9435             result[i] = b == null ? valueForNull : b.intValue();
9436         }
9437         return result;
9438     }
9439 
9440     /**
9441      * Converts an array of object Longs to primitives.
9442      * <p>
9443      * This method returns {@code null} for a {@code null} input array.
9444      * </p>
9445      *
9446      * @param array  a {@link Long} array, may be {@code null}.
9447      * @return a {@code long} array, {@code null} if null array input.
9448      * @throws NullPointerException if an array element is {@code null}.
9449      */
9450     public static long[] toPrimitive(final Long[] array) {
9451         if (array == null) {
9452             return null;
9453         }
9454         if (array.length == 0) {
9455             return EMPTY_LONG_ARRAY;
9456         }
9457         final long[] result = new long[array.length];
9458         for (int i = 0; i < array.length; i++) {
9459             result[i] = array[i].longValue();
9460         }
9461         return result;
9462     }
9463 
9464     /**
9465      * Converts an array of object Long to primitives handling {@code null}.
9466      * <p>
9467      * This method returns {@code null} for a {@code null} input array.
9468      * </p>
9469      *
9470      * @param array  a {@link Long} array, may be {@code null}.
9471      * @param valueForNull  the value to insert if {@code null} found.
9472      * @return a {@code long} array, {@code null} if null array input.
9473      */
9474     public static long[] toPrimitive(final Long[] array, final long valueForNull) {
9475         if (array == null) {
9476             return null;
9477         }
9478         if (array.length == 0) {
9479             return EMPTY_LONG_ARRAY;
9480         }
9481         final long[] result = new long[array.length];
9482         for (int i = 0; i < array.length; i++) {
9483             final Long b = array[i];
9484             result[i] = b == null ? valueForNull : b.longValue();
9485         }
9486         return result;
9487     }
9488 
9489     /**
9490      * Create an array of primitive type from an array of wrapper types.
9491      * <p>
9492      * This method returns {@code null} for a {@code null} input array.
9493      * </p>
9494      *
9495      * @param array  an array of wrapper object.
9496      * @return an array of the corresponding primitive type, or the original array.
9497      * @since 3.5
9498      */
9499     public static Object toPrimitive(final Object array) {
9500         if (array == null) {
9501             return null;
9502         }
9503         final Class<?> ct = array.getClass().getComponentType();
9504         final Class<?> pt = ClassUtils.wrapperToPrimitive(ct);
9505         if (Boolean.TYPE.equals(pt)) {
9506             return toPrimitive((Boolean[]) array);
9507         }
9508         if (Character.TYPE.equals(pt)) {
9509             return toPrimitive((Character[]) array);
9510         }
9511         if (Byte.TYPE.equals(pt)) {
9512             return toPrimitive((Byte[]) array);
9513         }
9514         if (Integer.TYPE.equals(pt)) {
9515             return toPrimitive((Integer[]) array);
9516         }
9517         if (Long.TYPE.equals(pt)) {
9518             return toPrimitive((Long[]) array);
9519         }
9520         if (Short.TYPE.equals(pt)) {
9521             return toPrimitive((Short[]) array);
9522         }
9523         if (Double.TYPE.equals(pt)) {
9524             return toPrimitive((Double[]) array);
9525         }
9526         if (Float.TYPE.equals(pt)) {
9527             return toPrimitive((Float[]) array);
9528         }
9529         return array;
9530     }
9531 
9532     /**
9533      * Converts an array of object Shorts to primitives.
9534      * <p>
9535      * This method returns {@code null} for a {@code null} input array.
9536      * </p>
9537      *
9538      * @param array  a {@link Short} array, may be {@code null}.
9539      * @return a {@code byte} array, {@code null} if null array input.
9540      * @throws NullPointerException if an array element is {@code null}.
9541      */
9542     public static short[] toPrimitive(final Short[] array) {
9543         if (array == null) {
9544             return null;
9545         }
9546         if (array.length == 0) {
9547             return EMPTY_SHORT_ARRAY;
9548         }
9549         final short[] result = new short[array.length];
9550         for (int i = 0; i < array.length; i++) {
9551             result[i] = array[i].shortValue();
9552         }
9553         return result;
9554     }
9555 
9556     /**
9557      * Converts an array of object Short to primitives handling {@code null}.
9558      * <p>
9559      * This method returns {@code null} for a {@code null} input array.
9560      * </p>
9561      *
9562      * @param array  a {@link Short} array, may be {@code null}.
9563      * @param valueForNull  the value to insert if {@code null} found.
9564      * @return a {@code byte} array, {@code null} if null array input.
9565      */
9566     public static short[] toPrimitive(final Short[] array, final short valueForNull) {
9567         if (array == null) {
9568             return null;
9569         }
9570         if (array.length == 0) {
9571             return EMPTY_SHORT_ARRAY;
9572         }
9573         final short[] result = new short[array.length];
9574         for (int i = 0; i < array.length; i++) {
9575             final Short b = array[i];
9576             result[i] = b == null ? valueForNull : b.shortValue();
9577         }
9578         return result;
9579     }
9580 
9581     /**
9582      * Outputs an array as a String, treating {@code null} as an empty array.
9583      * <p>
9584      * Multi-dimensional arrays are handled correctly, including
9585      * multi-dimensional primitive arrays.
9586      * </p>
9587      * <p>
9588      * The format is that of Java source code, for example {@code {a,b}}.
9589      * </p>
9590      *
9591      * @param array  the array to get a toString for, may be {@code null}.
9592      * @return a String representation of the array, '{}' if null array input.
9593      */
9594     public static String toString(final Object array) {
9595         return toString(array, "{}");
9596     }
9597 
9598     /**
9599      * Outputs an array as a String handling {@code null}s.
9600      * <p>
9601      * Multi-dimensional arrays are handled correctly, including
9602      * multi-dimensional primitive arrays.
9603      * </p>
9604      * <p>
9605      * The format is that of Java source code, for example {@code {a,b}}.
9606      * </p>
9607      *
9608      * @param array  the array to get a toString for, may be {@code null}.
9609      * @param stringIfNull  the String to return if the array is {@code null}.
9610      * @return a String representation of the array.
9611      */
9612     public static String toString(final Object array, final String stringIfNull) {
9613         return array != null ? new ToStringBuilder(array, ToStringStyle.SIMPLE_STYLE).append(array).toString() : stringIfNull;
9614     }
9615 
9616     /**
9617      * Returns an array containing the string representation of each element in the argument array.
9618      * <p>
9619      * This method returns {@code null} for a {@code null} input array.
9620      * </p>
9621      *
9622      * @param array the {@code Object[]} to be processed, may be {@code null}.
9623      * @return {@code String[]} of the same size as the source with its element's string representation, {@code null} if null array input.
9624      * @since 3.6
9625      */
9626     public static String[] toStringArray(final Object[] array) {
9627         return toStringArray(array, "null");
9628     }
9629 
9630     /**
9631      * Returns an array containing the string representation of each element in the argument array handling {@code null} elements.
9632      * <p>
9633      * This method returns {@code null} for a {@code null} input array.
9634      * </p>
9635      *
9636      * @param array                the Object[] to be processed, may be {@code null}.
9637      * @param valueForNullElements the value to insert if {@code null} is found.
9638      * @return a {@link String} array, {@code null} if null array input.
9639      * @since 3.6
9640      */
9641     public static String[] toStringArray(final Object[] array, final String valueForNullElements) {
9642         if (null == array) {
9643             return null;
9644         }
9645         if (array.length == 0) {
9646             return EMPTY_STRING_ARRAY;
9647         }
9648         return map(array, String.class, e -> Objects.toString(e, valueForNullElements));
9649     }
9650 
9651     /**
9652      * ArrayUtils instances should NOT be constructed in standard programming. Instead, the class should be used as {@code ArrayUtils.clone(new int[] {2})}.
9653      * <p>
9654      * This constructor is public to permit tools that require a JavaBean instance to operate.
9655      * </p>
9656      *
9657      * @deprecated TODO Make private in 4.0.
9658      */
9659     @Deprecated
9660     public ArrayUtils() {
9661         // empty
9662     }
9663 }