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