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