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