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