View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3;
18  
19  import java.lang.reflect.Array;
20  import java.lang.reflect.Field;
21  import java.lang.reflect.Method;
22  import java.lang.reflect.Type;
23  import java.util.Arrays;
24  import java.util.BitSet;
25  import java.util.Comparator;
26  import java.util.HashMap;
27  import java.util.Map;
28  import java.util.Random;
29  
30  import org.apache.commons.lang3.builder.EqualsBuilder;
31  import org.apache.commons.lang3.builder.HashCodeBuilder;
32  import org.apache.commons.lang3.builder.ToStringBuilder;
33  import org.apache.commons.lang3.builder.ToStringStyle;
34  import org.apache.commons.lang3.math.NumberUtils;
35  import org.apache.commons.lang3.mutable.MutableInt;
36  
37  /**
38   * <p>Operations on arrays, primitive arrays (like {@code int[]}) and
39   * primitive wrapper arrays (like {@code Integer[]}).
40   *
41   * <p>This class tries to handle {@code null} input gracefully.
42   * An exception will not be thrown for a {@code null}
43   * array input. However, an Object array that contains a {@code null}
44   * element may throw an exception. Each method documents its behavior.
45   *
46   * <p>#ThreadSafe#
47   * @since 2.0
48   */
49  public class ArrayUtils {
50  
51      /**
52       * An empty immutable {@code boolean} array.
53       */
54      public static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
55  
56      /**
57       * An empty immutable {@code Boolean} array.
58       */
59      public static final Boolean[] EMPTY_BOOLEAN_OBJECT_ARRAY = new Boolean[0];
60  
61      /**
62       * An empty immutable {@code byte} array.
63       */
64      public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
65  
66      /**
67       * An empty immutable {@code Byte} array.
68       */
69      public static final Byte[] EMPTY_BYTE_OBJECT_ARRAY = new Byte[0];
70  
71      /**
72       * An empty immutable {@code char} array.
73       */
74      public static final char[] EMPTY_CHAR_ARRAY = new char[0];
75  
76      /**
77       * An empty immutable {@code Character} array.
78       */
79      public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = new Character[0];
80  
81      /**
82       * An empty immutable {@code Class} array.
83       */
84      public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class[0];
85  
86      /**
87       * An empty immutable {@code double} array.
88       */
89      public static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
90  
91      /**
92       * An empty immutable {@code Double} array.
93       */
94      public static final Double[] EMPTY_DOUBLE_OBJECT_ARRAY = new Double[0];
95  
96      /**
97       * An empty immutable {@code Field} array.
98       *
99       * @since 3.10
100      */
101     public static final Field[] EMPTY_FIELD_ARRAY = new Field[0];
102 
103     /**
104      * An empty immutable {@code float} array.
105      */
106     public static final float[] EMPTY_FLOAT_ARRAY = new float[0];
107 
108     /**
109      * An empty immutable {@code Float} array.
110      */
111     public static final Float[] EMPTY_FLOAT_OBJECT_ARRAY = new Float[0];
112 
113     /**
114      * An empty immutable {@code int} array.
115      */
116     public static final int[] EMPTY_INT_ARRAY = new int[0];
117 
118     /**
119      * An empty immutable {@code Integer} array.
120      */
121     public static final Integer[] EMPTY_INTEGER_OBJECT_ARRAY = new Integer[0];
122 
123     /**
124      * An empty immutable {@code long} array.
125      */
126     public static final long[] EMPTY_LONG_ARRAY = new long[0];
127 
128     /**
129      * An empty immutable {@code Long} array.
130      */
131     public static final Long[] EMPTY_LONG_OBJECT_ARRAY = new Long[0];
132 
133     /**
134      * An empty immutable {@code Method} array.
135      *
136      * @since 3.10
137      */
138     public static final Method[] EMPTY_METHOD_ARRAY = new Method[0];
139 
140     /**
141      * An empty immutable {@code Object} array.
142      */
143     public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
144 
145     /**
146      * An empty immutable {@code short} array.
147      */
148     public static final short[] EMPTY_SHORT_ARRAY = new short[0];
149 
150     /**
151      * An empty immutable {@code Short} array.
152      */
153     public static final Short[] EMPTY_SHORT_OBJECT_ARRAY = new Short[0];
154 
155     /**
156      * An empty immutable {@code String} array.
157      */
158     public static final String[] EMPTY_STRING_ARRAY = new String[0];
159 
160     /**
161      * An empty immutable {@code Throwable} array.
162      *
163      * @since 3.10
164      */
165     public static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];
166 
167     /**
168      * An empty immutable {@code Type} array.
169      *
170      * @since 3.10
171      */
172     public static final Type[] EMPTY_TYPE_ARRAY = new Type[0];
173 
174     /**
175      * The index value when an element is not found in a list or array: {@code -1}.
176      * This value is returned by methods in this class and can also be used in comparisons with values returned by
177      * various method from {@link java.util.List}.
178      */
179     public static final int INDEX_NOT_FOUND = -1;
180 
181     /**
182      * <p>Copies the given array and adds the given element at the end of the new array.
183      *
184      * <p>The new array contains the same elements of the input
185      * array plus the given element in the last position. The component type of
186      * the new array is the same as that of the input array.
187      *
188      * <p>If the input array is {@code null}, a new one element array is returned
189      *  whose component type is the same as the element.
190      *
191      * <pre>
192      * ArrayUtils.add(null, true)          = [true]
193      * ArrayUtils.add([true], false)       = [true, false]
194      * ArrayUtils.add([true, false], true) = [true, false, true]
195      * </pre>
196      *
197      * @param array  the array to copy and add the element to, may be {@code null}
198      * @param element  the object to add at the last index of the new array
199      * @return A new array containing the existing elements plus the new element
200      * @since 2.1
201      */
202     public static boolean[] add(final boolean[] array, final boolean element) {
203         final boolean[] newArray = (boolean[]) copyArrayGrow1(array, Boolean.TYPE);
204         newArray[newArray.length - 1] = element;
205         return newArray;
206     }
207 
208     /**
209      * <p>Inserts the specified element at the specified position in the array.
210      * Shifts the element currently at that position (if any) and any subsequent
211      * elements to the right (adds one to their indices).
212      *
213      * <p>This method returns a new array with the same elements of the input
214      * array plus the given element on the specified position. The component
215      * type of the returned array is always the same as that of the input
216      * array.
217      *
218      * <p>If the input array is {@code null}, a new one element array is returned
219      *  whose component type is the same as the element.
220      *
221      * <pre>
222      * ArrayUtils.add(null, 0, true)          = [true]
223      * ArrayUtils.add([true], 0, false)       = [false, true]
224      * ArrayUtils.add([false], 1, true)       = [false, true]
225      * ArrayUtils.add([true, false], 1, true) = [true, true, false]
226      * </pre>
227      *
228      * @param array  the array to add the element to, may be {@code null}
229      * @param index  the position of the new object
230      * @param element  the object to add
231      * @return A new array containing the existing elements and the new element
232      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt; array.length).
233      * @deprecated this method has been superseded by {@link #insert(int, boolean[], boolean...)} and
234      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
235      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
236      */
237     @Deprecated
238     public static boolean[] add(final boolean[] array, final int index, final boolean element) {
239         return (boolean[]) add(array, index, Boolean.valueOf(element), Boolean.TYPE);
240     }
241 
242     /**
243      * <p>Copies the given array and adds the given element at the end of the new array.
244      *
245      * <p>The new array contains the same elements of the input
246      * array plus the given element in the last position. The component type of
247      * the new array is the same as that of the input array.
248      *
249      * <p>If the input array is {@code null}, a new one element array is returned
250      *  whose component type is the same as the element.
251      *
252      * <pre>
253      * ArrayUtils.add(null, 0)   = [0]
254      * ArrayUtils.add([1], 0)    = [1, 0]
255      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
256      * </pre>
257      *
258      * @param array  the array to copy and add the element to, may be {@code null}
259      * @param element  the object to add at the last index of the new array
260      * @return A new array containing the existing elements plus the new element
261      * @since 2.1
262      */
263     public static byte[] add(final byte[] array, final byte element) {
264         final byte[] newArray = (byte[]) copyArrayGrow1(array, Byte.TYPE);
265         newArray[newArray.length - 1] = element;
266         return newArray;
267     }
268 
269     /**
270      * <p>Inserts the specified element at the specified position in the array.
271      * Shifts the element currently at that position (if any) and any subsequent
272      * elements to the right (adds one to their indices).
273      *
274      * <p>This method returns a new array with the same elements of the input
275      * array plus the given element on the specified position. The component
276      * type of the returned array is always the same as that of the input
277      * array.
278      *
279      * <p>If the input array is {@code null}, a new one element array is returned
280      *  whose component type is the same as the element.
281      *
282      * <pre>
283      * ArrayUtils.add([1], 0, 2)         = [2, 1]
284      * ArrayUtils.add([2, 6], 2, 3)      = [2, 6, 3]
285      * ArrayUtils.add([2, 6], 0, 1)      = [1, 2, 6]
286      * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
287      * </pre>
288      *
289      * @param array  the array to add the element to, may be {@code null}
290      * @param index  the position of the new object
291      * @param element  the object to add
292      * @return A new array containing the existing elements and the new element
293      * @throws IndexOutOfBoundsException if the index is out of range
294      * (index &lt; 0 || index &gt; array.length).
295      * @deprecated this method has been superseded by {@link #insert(int, byte[], byte...)} and
296      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
297      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
298      */
299     @Deprecated
300     public static byte[] add(final byte[] array, final int index, final byte element) {
301         return (byte[]) add(array, index, Byte.valueOf(element), Byte.TYPE);
302     }
303 
304     /**
305      * <p>Copies the given array and adds the given element at the end of the new array.
306      *
307      * <p>The new array contains the same elements of the input
308      * array plus the given element in the last position. The component type of
309      * the new array is the same as that of the input array.
310      *
311      * <p>If the input array is {@code null}, a new one element array is returned
312      *  whose component type is the same as the element.
313      *
314      * <pre>
315      * ArrayUtils.add(null, '0')       = ['0']
316      * ArrayUtils.add(['1'], '0')      = ['1', '0']
317      * ArrayUtils.add(['1', '0'], '1') = ['1', '0', '1']
318      * </pre>
319      *
320      * @param array  the array to copy and add the element to, may be {@code null}
321      * @param element  the object to add at the last index of the new array
322      * @return A new array containing the existing elements plus the new element
323      * @since 2.1
324      */
325     public static char[] add(final char[] array, final char element) {
326         final char[] newArray = (char[]) copyArrayGrow1(array, Character.TYPE);
327         newArray[newArray.length - 1] = element;
328         return newArray;
329     }
330 
331     /**
332      * <p>Inserts the specified element at the specified position in the array.
333      * Shifts the element currently at that position (if any) and any subsequent
334      * elements to the right (adds one to their indices).
335      *
336      * <p>This method returns a new array with the same elements of the input
337      * array plus the given element on the specified position. The component
338      * type of the returned array is always the same as that of the input
339      * array.
340      *
341      * <p>If the input array is {@code null}, a new one element array is returned
342      *  whose component type is the same as the element.
343      *
344      * <pre>
345      * ArrayUtils.add(null, 0, 'a')            = ['a']
346      * ArrayUtils.add(['a'], 0, 'b')           = ['b', 'a']
347      * ArrayUtils.add(['a', 'b'], 0, 'c')      = ['c', 'a', 'b']
348      * ArrayUtils.add(['a', 'b'], 1, 'k')      = ['a', 'k', 'b']
349      * ArrayUtils.add(['a', 'b', 'c'], 1, 't') = ['a', 't', 'b', 'c']
350      * </pre>
351      *
352      * @param array  the array to add the element to, may be {@code null}
353      * @param index  the position of the new object
354      * @param element  the object to add
355      * @return A new array containing the existing elements and the new element
356      * @throws IndexOutOfBoundsException if the index is out of range
357      * (index &lt; 0 || index &gt; array.length).
358      * @deprecated this method has been superseded by {@link #insert(int, char[], char...)} and
359      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
360      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
361      */
362     @Deprecated
363     public static char[] add(final char[] array, final int index, final char element) {
364         return (char[]) add(array, index, Character.valueOf(element), Character.TYPE);
365     }
366 
367     /**
368      * <p>Copies the given array and adds the given element at the end of the new array.
369      *
370      * <p>The new array contains the same elements of the input
371      * array plus the given element in the last position. The component type of
372      * the new array is the same as that of the input array.
373      *
374      * <p>If the input array is {@code null}, a new one element array is returned
375      *  whose component type is the same as the element.
376      *
377      * <pre>
378      * ArrayUtils.add(null, 0)   = [0]
379      * ArrayUtils.add([1], 0)    = [1, 0]
380      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
381      * </pre>
382      *
383      * @param array  the array to copy and add the element to, may be {@code null}
384      * @param element  the object to add at the last index of the new array
385      * @return A new array containing the existing elements plus the new element
386      * @since 2.1
387      */
388     public static double[] add(final double[] array, final double element) {
389         final double[] newArray = (double[]) copyArrayGrow1(array, Double.TYPE);
390         newArray[newArray.length - 1] = element;
391         return newArray;
392     }
393 
394     /**
395      * <p>Inserts the specified element at the specified position in the array.
396      * Shifts the element currently at that position (if any) and any subsequent
397      * elements to the right (adds one to their indices).
398      *
399      * <p>This method returns a new array with the same elements of the input
400      * array plus the given element on the specified position. The component
401      * type of the returned array is always the same as that of the input
402      * array.
403      *
404      * <p>If the input array is {@code null}, a new one element array is returned
405      *  whose component type is the same as the element.
406      *
407      * <pre>
408      * ArrayUtils.add([1.1], 0, 2.2)              = [2.2, 1.1]
409      * ArrayUtils.add([2.3, 6.4], 2, 10.5)        = [2.3, 6.4, 10.5]
410      * ArrayUtils.add([2.6, 6.7], 0, -4.8)        = [-4.8, 2.6, 6.7]
411      * ArrayUtils.add([2.9, 6.0, 0.3], 2, 1.0)    = [2.9, 6.0, 1.0, 0.3]
412      * </pre>
413      *
414      * @param array  the array to add the element to, may be {@code null}
415      * @param index  the position of the new object
416      * @param element  the object to add
417      * @return A new array containing the existing elements and the new element
418      * @throws IndexOutOfBoundsException if the index is out of range
419      * (index &lt; 0 || index &gt; array.length).
420      * @deprecated this method has been superseded by {@link #insert(int, double[], double...)} and
421      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
422      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
423      */
424     @Deprecated
425     public static double[] add(final double[] array, final int index, final double element) {
426         return (double[]) add(array, index, Double.valueOf(element), Double.TYPE);
427     }
428 
429     /**
430      * <p>Copies the given array and adds the given element at the end of the new array.
431      *
432      * <p>The new array contains the same elements of the input
433      * array plus the given element in the last position. The component type of
434      * the new array is the same as that of the input array.
435      *
436      * <p>If the input array is {@code null}, a new one element array is returned
437      *  whose component type is the same as the element.
438      *
439      * <pre>
440      * ArrayUtils.add(null, 0)   = [0]
441      * ArrayUtils.add([1], 0)    = [1, 0]
442      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
443      * </pre>
444      *
445      * @param array  the array to copy and add the element to, may be {@code null}
446      * @param element  the object to add at the last index of the new array
447      * @return A new array containing the existing elements plus the new element
448      * @since 2.1
449      */
450     public static float[] add(final float[] array, final float element) {
451         final float[] newArray = (float[]) copyArrayGrow1(array, Float.TYPE);
452         newArray[newArray.length - 1] = element;
453         return newArray;
454     }
455 
456     /**
457      * <p>Inserts the specified element at the specified position in the array.
458      * Shifts the element currently at that position (if any) and any subsequent
459      * elements to the right (adds one to their indices).
460      *
461      * <p>This method returns a new array with the same elements of the input
462      * array plus the given element on the specified position. The component
463      * type of the returned array is always the same as that of the input
464      * array.
465      *
466      * <p>If the input array is {@code null}, a new one element array is returned
467      *  whose component type is the same as the element.
468      *
469      * <pre>
470      * ArrayUtils.add([1.1f], 0, 2.2f)               = [2.2f, 1.1f]
471      * ArrayUtils.add([2.3f, 6.4f], 2, 10.5f)        = [2.3f, 6.4f, 10.5f]
472      * ArrayUtils.add([2.6f, 6.7f], 0, -4.8f)        = [-4.8f, 2.6f, 6.7f]
473      * ArrayUtils.add([2.9f, 6.0f, 0.3f], 2, 1.0f)   = [2.9f, 6.0f, 1.0f, 0.3f]
474      * </pre>
475      *
476      * @param array  the array to add the element to, may be {@code null}
477      * @param index  the position of the new object
478      * @param element  the object to add
479      * @return A new array containing the existing elements and the new element
480      * @throws IndexOutOfBoundsException if the index is out of range
481      * (index &lt; 0 || index &gt; array.length).
482      * @deprecated this method has been superseded by {@link #insert(int, float[], float...)} and
483      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
484      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
485      */
486     @Deprecated
487     public static float[] add(final float[] array, final int index, final float element) {
488         return (float[]) add(array, index, Float.valueOf(element), Float.TYPE);
489     }
490 
491     /**
492      * <p>Copies the given array and adds the given element at the end of the new array.
493      *
494      * <p>The new array contains the same elements of the input
495      * array plus the given element in the last position. The component type of
496      * the new array is the same as that of the input array.
497      *
498      * <p>If the input array is {@code null}, a new one element array is returned
499      *  whose component type is the same as the element.
500      *
501      * <pre>
502      * ArrayUtils.add(null, 0)   = [0]
503      * ArrayUtils.add([1], 0)    = [1, 0]
504      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
505      * </pre>
506      *
507      * @param array  the array to copy and add the element to, may be {@code null}
508      * @param element  the object to add at the last index of the new array
509      * @return A new array containing the existing elements plus the new element
510      * @since 2.1
511      */
512     public static int[] add(final int[] array, final int element) {
513         final int[] newArray = (int[]) copyArrayGrow1(array, Integer.TYPE);
514         newArray[newArray.length - 1] = element;
515         return newArray;
516     }
517 
518     /**
519      * <p>Inserts the specified element at the specified position in the array.
520      * Shifts the element currently at that position (if any) and any subsequent
521      * elements to the right (adds one to their indices).
522      *
523      * <p>This method returns a new array with the same elements of the input
524      * array plus the given element on the specified position. The component
525      * type of the returned array is always the same as that of the input
526      * array.
527      *
528      * <p>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      *
531      * <pre>
532      * ArrayUtils.add([1], 0, 2)         = [2, 1]
533      * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
534      * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
535      * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
536      * </pre>
537      *
538      * @param array  the array to add the element to, may be {@code null}
539      * @param index  the position of the new object
540      * @param element  the object to add
541      * @return A new array containing the existing elements and the new element
542      * @throws IndexOutOfBoundsException if the index is out of range
543      * (index &lt; 0 || index &gt; array.length).
544      * @deprecated this method has been superseded by {@link #insert(int, int[], int...)} and
545      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
546      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
547      */
548     @Deprecated
549     public static int[] add(final int[] array, final int index, final int element) {
550         return (int[]) add(array, index, Integer.valueOf(element), Integer.TYPE);
551     }
552 
553     /**
554      * <p>Inserts the specified element at the specified position in the array.
555      * Shifts the element currently at that position (if any) and any subsequent
556      * elements to the right (adds one to their indices).
557      *
558      * <p>This method returns a new array with the same elements of the input
559      * array plus the given element on the specified position. The component
560      * type of the returned array is always the same as that of the input
561      * array.
562      *
563      * <p>If the input array is {@code null}, a new one element array is returned
564      *  whose component type is the same as the element.
565      *
566      * <pre>
567      * ArrayUtils.add([1L], 0, 2L)           = [2L, 1L]
568      * ArrayUtils.add([2L, 6L], 2, 10L)      = [2L, 6L, 10L]
569      * ArrayUtils.add([2L, 6L], 0, -4L)      = [-4L, 2L, 6L]
570      * ArrayUtils.add([2L, 6L, 3L], 2, 1L)   = [2L, 6L, 1L, 3L]
571      * </pre>
572      *
573      * @param array  the array to add the element to, may be {@code null}
574      * @param index  the position of the new object
575      * @param element  the object to add
576      * @return A new array containing the existing elements and the new element
577      * @throws IndexOutOfBoundsException if the index is out of range
578      * (index &lt; 0 || index &gt; array.length).
579      * @deprecated this method has been superseded by {@link #insert(int, long[], long...)} and
580      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
581      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
582      */
583     @Deprecated
584     public static long[] add(final long[] array, final int index, final long element) {
585         return (long[]) add(array, index, Long.valueOf(element), Long.TYPE);
586     }
587 
588     /**
589      * <p>Copies the given array and adds the given element at the end of the new array.
590      *
591      * <p>The new array contains the same elements of the input
592      * array plus the given element in the last position. The component type of
593      * the new array is the same as that of the input array.
594      *
595      * <p>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      *
598      * <pre>
599      * ArrayUtils.add(null, 0)   = [0]
600      * ArrayUtils.add([1], 0)    = [1, 0]
601      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
602      * </pre>
603      *
604      * @param array  the array to copy and add the element to, may be {@code null}
605      * @param element  the object to add at the last index of the new array
606      * @return A new array containing the existing elements plus the new element
607      * @since 2.1
608      */
609     public static long[] add(final long[] array, final long element) {
610         final long[] newArray = (long[]) copyArrayGrow1(array, Long.TYPE);
611         newArray[newArray.length - 1] = element;
612         return newArray;
613     }
614 
615     /**
616      * Underlying implementation of add(array, index, element) methods.
617      * The last parameter is the class, which may not equal element.getClass
618      * for primitives.
619      *
620      * @param array  the array to add the element to, may be {@code null}
621      * @param index  the position of the new object
622      * @param element  the object to add
623      * @param clss the type of the element being added
624      * @return A new array containing the existing elements and the new element
625      */
626     private static Object add(final Object array, final int index, final Object element, final Class<?> clss) {
627         if (array == null) {
628             if (index != 0) {
629                 throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
630             }
631             final Object joinedArray = Array.newInstance(clss, 1);
632             Array.set(joinedArray, 0, element);
633             return joinedArray;
634         }
635         final int length = Array.getLength(array);
636         if (index > length || index < 0) {
637             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
638         }
639         final Object result = Array.newInstance(clss, length + 1);
640         System.arraycopy(array, 0, result, 0, index);
641         Array.set(result, index, element);
642         if (index < length) {
643             System.arraycopy(array, index, result, index + 1, length - index);
644         }
645         return result;
646     }
647 
648     /**
649      * <p>Inserts the specified element at the specified position in the array.
650      * Shifts the element currently at that position (if any) and any subsequent
651      * elements to the right (adds one to their indices).
652      *
653      * <p>This method returns a new array with the same elements of the input
654      * array plus the given element on the specified position. The component
655      * type of the returned array is always the same as that of the input
656      * array.
657      *
658      * <p>If the input array is {@code null}, a new one element array is returned
659      *  whose component type is the same as the element.
660      *
661      * <pre>
662      * ArrayUtils.add([1], 0, 2)         = [2, 1]
663      * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
664      * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
665      * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
666      * </pre>
667      *
668      * @param array  the array to add the element to, may be {@code null}
669      * @param index  the position of the new object
670      * @param element  the object to add
671      * @return A new array containing the existing elements and the new element
672      * @throws IndexOutOfBoundsException if the index is out of range
673      * (index &lt; 0 || index &gt; array.length).
674      * @deprecated this method has been superseded by {@link #insert(int, short[], short...)} and
675      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
676      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
677      */
678     @Deprecated
679     public static short[] add(final short[] array, final int index, final short element) {
680         return (short[]) add(array, index, Short.valueOf(element), Short.TYPE);
681     }
682 
683     /**
684      * <p>Copies the given array and adds the given element at the end of the new array.
685      *
686      * <p>The new array contains the same elements of the input
687      * array plus the given element in the last position. The component type of
688      * the new array is the same as that of the input array.
689      *
690      * <p>If the input array is {@code null}, a new one element array is returned
691      *  whose component type is the same as the element.
692      *
693      * <pre>
694      * ArrayUtils.add(null, 0)   = [0]
695      * ArrayUtils.add([1], 0)    = [1, 0]
696      * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
697      * </pre>
698      *
699      * @param array  the array to copy and add the element to, may be {@code null}
700      * @param element  the object to add at the last index of the new array
701      * @return A new array containing the existing elements plus the new element
702      * @since 2.1
703      */
704     public static short[] add(final short[] array, final short element) {
705         final short[] newArray = (short[]) copyArrayGrow1(array, Short.TYPE);
706         newArray[newArray.length - 1] = element;
707         return newArray;
708     }
709 
710 
711     /**
712      * <p>Inserts the specified element at the specified position in the array.
713      * Shifts the element currently at that position (if any) and any subsequent
714      * elements to the right (adds one to their indices).
715      *
716      * <p>This method returns a new array with the same elements of the input
717      * array plus the given element on the specified position. The component
718      * type of the returned array is always the same as that of the input
719      * array.
720      *
721      * <p>If the input array is {@code null}, a new one element array is returned
722      *  whose component type is the same as the element.
723      *
724      * <pre>
725      * ArrayUtils.add(null, 0, null)      = IllegalArgumentException
726      * ArrayUtils.add(null, 0, "a")       = ["a"]
727      * ArrayUtils.add(["a"], 1, null)     = ["a", null]
728      * ArrayUtils.add(["a"], 1, "b")      = ["a", "b"]
729      * ArrayUtils.add(["a", "b"], 3, "c") = ["a", "b", "c"]
730      * </pre>
731      *
732      * @param <T> the component type of the array
733      * @param array  the array to add the element to, may be {@code null}
734      * @param index  the position of the new object
735      * @param element  the object to add
736      * @return A new array containing the existing elements and the new element
737      * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt; array.length).
738      * @throws IllegalArgumentException if both array and element are null
739      * @deprecated this method has been superseded by {@link #insert(int, Object[], Object...) insert(int, T[], T...)} and
740      * may be removed in a future release. Please note the handling of {@code null} input arrays differs
741      * in the new method: inserting {@code X} into a {@code null} array results in {@code null} not {@code X}.
742      */
743     @Deprecated
744     public static <T> T[] add(final T[] array, final int index, final T element) {
745         Class<?> clss = null;
746         if (array != null) {
747             clss = array.getClass().getComponentType();
748         } else if (element != null) {
749             clss = element.getClass();
750         } else {
751             throw new IllegalArgumentException("Array and element cannot both be null");
752         }
753         @SuppressWarnings("unchecked") // the add method creates an array of type clss, which is type T
754         final T[] newArray = (T[]) add(array, index, element, clss);
755         return newArray;
756     }
757 
758     /**
759      * <p>Copies the given array and adds the given element at the end of the new array.
760      *
761      * <p>The new array contains the same elements of the input
762      * array plus the given element in the last position. The component type of
763      * the new array is the same as that of the input array.
764      *
765      * <p>If the input array is {@code null}, a new one element array is returned
766      *  whose component type is the same as the element, unless the element itself is null,
767      *  in which case the return type is Object[]
768      *
769      * <pre>
770      * ArrayUtils.add(null, null)      = IllegalArgumentException
771      * ArrayUtils.add(null, "a")       = ["a"]
772      * ArrayUtils.add(["a"], null)     = ["a", null]
773      * ArrayUtils.add(["a"], "b")      = ["a", "b"]
774      * ArrayUtils.add(["a", "b"], "c") = ["a", "b", "c"]
775      * </pre>
776      *
777      * @param <T> the component type of the array
778      * @param array  the array to "add" the element to, may be {@code null}
779      * @param element  the object to add, may be {@code null}
780      * @return A new array containing the existing elements plus the new element
781      * The returned array type will be that of the input array (unless null),
782      * in which case it will have the same type as the element.
783      * If both are null, an IllegalArgumentException is thrown
784      * @since 2.1
785      * @throws IllegalArgumentException if both arguments are null
786      */
787     public static <T> T[] add(final T[] array, final T element) {
788         final Class<?> type;
789         if (array != null) {
790             type = array.getClass().getComponentType();
791         } else if (element != null) {
792             type = element.getClass();
793         } else {
794             throw new IllegalArgumentException("Arguments cannot both be null");
795         }
796         @SuppressWarnings("unchecked") // type must be T
797         final
798         T[] newArray = (T[]) copyArrayGrow1(array, type);
799         newArray[newArray.length - 1] = element;
800         return newArray;
801     }
802 
803     /**
804      * <p>Adds all the elements of the given arrays into a new array.
805      * <p>The new array contains all of the element of {@code array1} followed
806      * by all of the elements {@code array2}. When an array is returned, it is always
807      * a new array.
808      *
809      * <pre>
810      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
811      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
812      * ArrayUtils.addAll([], [])         = []
813      * </pre>
814      *
815      * @param array1  the first array whose elements are added to the new array.
816      * @param array2  the second array whose elements are added to the new array.
817      * @return The new boolean[] array.
818      * @since 2.1
819      */
820     public static boolean[] addAll(final boolean[] array1, final boolean... array2) {
821         if (array1 == null) {
822             return clone(array2);
823         } else if (array2 == null) {
824             return clone(array1);
825         }
826         final boolean[] joinedArray = new boolean[array1.length + array2.length];
827         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
828         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
829         return joinedArray;
830     }
831 
832     /**
833      * <p>Adds all the elements of the given arrays into a new array.
834      * <p>The new array contains all of the element of {@code array1} followed
835      * by all of the elements {@code array2}. When an array is returned, it is always
836      * a new array.
837      *
838      * <pre>
839      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
840      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
841      * ArrayUtils.addAll([], [])         = []
842      * </pre>
843      *
844      * @param array1  the first array whose elements are added to the new array.
845      * @param array2  the second array whose elements are added to the new array.
846      * @return The new byte[] array.
847      * @since 2.1
848      */
849     public static byte[] addAll(final byte[] array1, final byte... array2) {
850         if (array1 == null) {
851             return clone(array2);
852         } else if (array2 == null) {
853             return clone(array1);
854         }
855         final byte[] joinedArray = new byte[array1.length + array2.length];
856         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
857         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
858         return joinedArray;
859     }
860 
861     /**
862      * <p>Adds all the elements of the given arrays into a new array.
863      * <p>The new array contains all of the element of {@code array1} followed
864      * by all of the elements {@code array2}. When an array is returned, it is always
865      * a new array.
866      *
867      * <pre>
868      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
869      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
870      * ArrayUtils.addAll([], [])         = []
871      * </pre>
872      *
873      * @param array1  the first array whose elements are added to the new array.
874      * @param array2  the second array whose elements are added to the new array.
875      * @return The new char[] array.
876      * @since 2.1
877      */
878     public static char[] addAll(final char[] array1, final char... array2) {
879         if (array1 == null) {
880             return clone(array2);
881         } else if (array2 == null) {
882             return clone(array1);
883         }
884         final char[] joinedArray = new char[array1.length + array2.length];
885         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
886         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
887         return joinedArray;
888     }
889 
890     /**
891      * <p>Adds all the elements of the given arrays into a new array.
892      * <p>The new array contains all of the element of {@code array1} followed
893      * by all of the elements {@code array2}. When an array is returned, it is always
894      * a new array.
895      *
896      * <pre>
897      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
898      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
899      * ArrayUtils.addAll([], [])         = []
900      * </pre>
901      *
902      * @param array1  the first array whose elements are added to the new array.
903      * @param array2  the second array whose elements are added to the new array.
904      * @return The new double[] array.
905      * @since 2.1
906      */
907     public static double[] addAll(final double[] array1, final double... array2) {
908         if (array1 == null) {
909             return clone(array2);
910         } else if (array2 == null) {
911             return clone(array1);
912         }
913         final double[] joinedArray = new double[array1.length + array2.length];
914         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
915         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
916         return joinedArray;
917     }
918 
919     /**
920      * <p>Adds all the elements of the given arrays into a new array.
921      * <p>The new array contains all of the element of {@code array1} followed
922      * by all of the elements {@code array2}. When an array is returned, it is always
923      * a new array.
924      *
925      * <pre>
926      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
927      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
928      * ArrayUtils.addAll([], [])         = []
929      * </pre>
930      *
931      * @param array1  the first array whose elements are added to the new array.
932      * @param array2  the second array whose elements are added to the new array.
933      * @return The new float[] array.
934      * @since 2.1
935      */
936     public static float[] addAll(final float[] array1, final float... array2) {
937         if (array1 == null) {
938             return clone(array2);
939         } else if (array2 == null) {
940             return clone(array1);
941         }
942         final float[] joinedArray = new float[array1.length + array2.length];
943         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
944         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
945         return joinedArray;
946     }
947 
948     /**
949      * <p>Adds all the elements of the given arrays into a new array.
950      * <p>The new array contains all of the element of {@code array1} followed
951      * by all of the elements {@code array2}. When an array is returned, it is always
952      * a new array.
953      *
954      * <pre>
955      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
956      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
957      * ArrayUtils.addAll([], [])         = []
958      * </pre>
959      *
960      * @param array1  the first array whose elements are added to the new array.
961      * @param array2  the second array whose elements are added to the new array.
962      * @return The new int[] array.
963      * @since 2.1
964      */
965     public static int[] addAll(final int[] array1, final int... array2) {
966         if (array1 == null) {
967             return clone(array2);
968         } else if (array2 == null) {
969             return clone(array1);
970         }
971         final int[] joinedArray = new int[array1.length + array2.length];
972         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
973         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
974         return joinedArray;
975     }
976 
977     /**
978      * <p>Adds all the elements of the given arrays into a new array.
979      * <p>The new array contains all of the element of {@code array1} followed
980      * by all of the elements {@code array2}. When an array is returned, it is always
981      * a new array.
982      *
983      * <pre>
984      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
985      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
986      * ArrayUtils.addAll([], [])         = []
987      * </pre>
988      *
989      * @param array1  the first array whose elements are added to the new array.
990      * @param array2  the second array whose elements are added to the new array.
991      * @return The new long[] array.
992      * @since 2.1
993      */
994     public static long[] addAll(final long[] array1, final long... array2) {
995         if (array1 == null) {
996             return clone(array2);
997         } else if (array2 == null) {
998             return clone(array1);
999         }
1000         final long[] joinedArray = new long[array1.length + array2.length];
1001         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1002         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1003         return joinedArray;
1004     }
1005 
1006     /**
1007      * <p>Adds all the elements of the given arrays into a new array.
1008      * <p>The new array contains all of the element of {@code array1} followed
1009      * by all of the elements {@code array2}. When an array is returned, it is always
1010      * a new array.
1011      *
1012      * <pre>
1013      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1014      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1015      * ArrayUtils.addAll([], [])         = []
1016      * </pre>
1017      *
1018      * @param array1  the first array whose elements are added to the new array.
1019      * @param array2  the second array whose elements are added to the new array.
1020      * @return The new short[] array.
1021      * @since 2.1
1022      */
1023     public static short[] addAll(final short[] array1, final short... array2) {
1024         if (array1 == null) {
1025             return clone(array2);
1026         } else if (array2 == null) {
1027             return clone(array1);
1028         }
1029         final short[] joinedArray = new short[array1.length + array2.length];
1030         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1031         System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1032         return joinedArray;
1033     }
1034 
1035     /**
1036      * <p>Adds all the elements of the given arrays into a new array.
1037      * <p>The new array contains all of the element of {@code array1} followed
1038      * by all of the elements {@code array2}. When an array is returned, it is always
1039      * a new array.
1040      *
1041      * <pre>
1042      * ArrayUtils.addAll(null, null)     = null
1043      * ArrayUtils.addAll(array1, null)   = cloned copy of array1
1044      * ArrayUtils.addAll(null, array2)   = cloned copy of array2
1045      * ArrayUtils.addAll([], [])         = []
1046      * ArrayUtils.addAll([null], [null]) = [null, null]
1047      * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
1048      * </pre>
1049      *
1050      * @param <T> the component type of the array
1051      * @param array1  the first array whose elements are added to the new array, may be {@code null}
1052      * @param array2  the second array whose elements are added to the new array, may be {@code null}
1053      * @return The new array, {@code null} if both arrays are {@code null}.
1054      *      The type of the new array is the type of the first array,
1055      *      unless the first array is null, in which case the type is the same as the second array.
1056      * @since 2.1
1057      * @throws IllegalArgumentException if the array types are incompatible
1058      */
1059     public static <T> T[] addAll(final T[] array1, @SuppressWarnings("unchecked") final T... array2) {
1060         if (array1 == null) {
1061             return clone(array2);
1062         } else if (array2 == null) {
1063             return clone(array1);
1064         }
1065         final Class<?> type1 = array1.getClass().getComponentType();
1066         @SuppressWarnings("unchecked") // OK, because array is of type T
1067         final T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);
1068         System.arraycopy(array1, 0, joinedArray, 0, array1.length);
1069         try {
1070             System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
1071         } catch (final ArrayStoreException ase) {
1072             // Check if problem was due to incompatible types
1073             /*
1074              * We do this here, rather than before the copy because:
1075              * - it would be a wasted check most of the time
1076              * - safer, in case check turns out to be too strict
1077              */
1078             final Class<?> type2 = array2.getClass().getComponentType();
1079             if (!type1.isAssignableFrom(type2)) {
1080                 throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of "
1081                         + type1.getName(), ase);
1082             }
1083             throw ase; // No, so rethrow original
1084         }
1085         return joinedArray;
1086     }
1087 
1088     /**
1089      * Copies the given array and adds the given element at the beginning of the new array.
1090      *
1091      * <p>
1092      * The new array contains the same elements of the input array plus the given element in the first position. The
1093      * component type of the new array is the same as that of the input array.
1094      * </p>
1095      *
1096      * <p>
1097      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1098      * element.
1099      * </p>
1100      *
1101      * <pre>
1102      * ArrayUtils.addFirst(null, true)          = [true]
1103      * ArrayUtils.addFirst([true], false)       = [false, true]
1104      * ArrayUtils.addFirst([true, false], true) = [true, true, false]
1105      * </pre>
1106      *
1107      * @param array the array to "add" the element to, may be {@code null}.
1108      * @param element the object to add.
1109      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1110      *         the input array (unless null), in which case it will have the same type as the element.
1111      * @since 3.10
1112      */
1113     public static boolean[] addFirst(final boolean[] array, final boolean element) {
1114         return array == null ? add(array, element) : insert(0, array, element);
1115     }
1116 
1117     /**
1118      * Copies the given array and adds the given element at the beginning of the new array.
1119      *
1120      * <p>
1121      * The new array contains the same elements of the input array plus the given element in the first position. The
1122      * component type of the new array is the same as that of the input array.
1123      * </p>
1124      *
1125      * <p>
1126      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1127      * element.
1128      * </p>
1129      *
1130      * <pre>
1131      * ArrayUtils.addFirst(null, 1)   = [1]
1132      * ArrayUtils.addFirst([1], 0)    = [0, 1]
1133      * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1134      * </pre>
1135      *
1136      * @param array the array to "add" the element to, may be {@code null}.
1137      * @param element the object to add.
1138      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1139      *         the input array (unless null), in which case it will have the same type as the element.
1140      * @since 3.10
1141      */
1142     public static byte[] addFirst(final byte[] array, final byte element) {
1143         return array == null ? add(array, element) : insert(0, array, element);
1144     }
1145 
1146     /**
1147      * Copies the given array and adds the given element at the beginning of the new array.
1148      *
1149      * <p>
1150      * The new array contains the same elements of the input array plus the given element in the first position. The
1151      * component type of the new array is the same as that of the input array.
1152      * </p>
1153      *
1154      * <p>
1155      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1156      * element.
1157      * </p>
1158      *
1159      * <pre>
1160      * ArrayUtils.addFirst(null, '1')       = ['1']
1161      * ArrayUtils.addFirst(['1'], '0')      = ['0', '1']
1162      * ArrayUtils.addFirst(['1', '0'], '1') = ['1', '1', '0']
1163      * </pre>
1164      *
1165      * @param array the array to "add" the element to, may be {@code null}.
1166      * @param element the object to add.
1167      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1168      *         the input array (unless null), in which case it will have the same type as the element.
1169      * @since 3.10
1170      */
1171     public static char[] addFirst(final char[] array, final char element) {
1172         return array == null ? add(array, element) : insert(0, array, element);
1173     }
1174 
1175     /**
1176      * Copies the given array and adds the given element at the beginning of the new array.
1177      *
1178      * <p>
1179      * The new array contains the same elements of the input array plus the given element in the first position. The
1180      * component type of the new array is the same as that of the input array.
1181      * </p>
1182      *
1183      * <p>
1184      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1185      * element.
1186      * </p>
1187      *
1188      * <pre>
1189      * ArrayUtils.addFirst(null, 1)   = [1]
1190      * ArrayUtils.addFirst([1], 0)    = [0, 1]
1191      * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1192      * </pre>
1193      *
1194      * @param array the array to "add" the element to, may be {@code null}.
1195      * @param element the object to add.
1196      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1197      *         the input array (unless null), in which case it will have the same type as the element.
1198      * @since 3.10
1199      */
1200     public static double[] addFirst(final double[] array, final double element) {
1201         return array == null ? add(array, element) : insert(0, array, element);
1202     }
1203 
1204     /**
1205      * Copies the given array and adds the given element at the beginning of the new array.
1206      *
1207      * <p>
1208      * The new array contains the same elements of the input array plus the given element in the first position. The
1209      * component type of the new array is the same as that of the input array.
1210      * </p>
1211      *
1212      * <p>
1213      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1214      * element.
1215      * </p>
1216      *
1217      * <pre>
1218      * ArrayUtils.addFirst(null, 1)   = [1]
1219      * ArrayUtils.addFirst([1], 0)    = [0, 1]
1220      * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1221      * </pre>
1222      *
1223      * @param array the array to "add" the element to, may be {@code null}.
1224      * @param element the object to add.
1225      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1226      *         the input array (unless null), in which case it will have the same type as the element.
1227      * @since 3.10
1228      */
1229     public static float[] addFirst(final float[] array, final float element) {
1230         return array == null ? add(array, element) : insert(0, array, element);
1231     }
1232 
1233     /**
1234      * Copies the given array and adds the given element at the beginning of the new array.
1235      *
1236      * <p>
1237      * The new array contains the same elements of the input array plus the given element in the first position. The
1238      * component type of the new array is the same as that of the input array.
1239      * </p>
1240      *
1241      * <p>
1242      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1243      * element.
1244      * </p>
1245      *
1246      * <pre>
1247      * ArrayUtils.addFirst(null, 1)   = [1]
1248      * ArrayUtils.addFirst([1], 0)    = [0, 1]
1249      * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1250      * </pre>
1251      *
1252      * @param array the array to "add" the element to, may be {@code null}.
1253      * @param element the object to add.
1254      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1255      *         the input array (unless null), in which case it will have the same type as the element.
1256      * @since 3.10
1257      */
1258     public static int[] addFirst(final int[] array, final int element) {
1259         return array == null ? add(array, element) : insert(0, array, element);
1260     }
1261 
1262     /**
1263      * Copies the given array and adds the given element at the beginning of the new array.
1264      *
1265      * <p>
1266      * The new array contains the same elements of the input array plus the given element in the first position. The
1267      * component type of the new array is the same as that of the input array.
1268      * </p>
1269      *
1270      * <p>
1271      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1272      * element.
1273      * </p>
1274      *
1275      * <pre>
1276      * ArrayUtils.addFirst(null, 1)   = [1]
1277      * ArrayUtils.addFirst([1], 0)    = [0, 1]
1278      * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1279      * </pre>
1280      *
1281      * @param array the array to "add" the element to, may be {@code null}.
1282      * @param element the object to add.
1283      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1284      *         the input array (unless null), in which case it will have the same type as the element.
1285      * @since 3.10
1286      */
1287     public static long[] addFirst(final long[] array, final long element) {
1288         return array == null ? add(array, element) : insert(0, array, element);
1289     }
1290 
1291     /**
1292      * Copies the given array and adds the given element at the beginning of the new array.
1293      *
1294      * <p>
1295      * The new array contains the same elements of the input array plus the given element in the first position. The
1296      * component type of the new array is the same as that of the input array.
1297      * </p>
1298      *
1299      * <p>
1300      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1301      * element.
1302      * </p>
1303      *
1304      * <pre>
1305      * ArrayUtils.addFirst(null, 1)   = [1]
1306      * ArrayUtils.addFirst([1], 0)    = [0, 1]
1307      * ArrayUtils.addFirst([1, 0], 1) = [1, 1, 0]
1308      * </pre>
1309      *
1310      * @param array the array to "add" the element to, may be {@code null}.
1311      * @param element the object to add.
1312      * @return A new array containing the existing elements plus the new element The returned array type will be that of
1313      *         the input array (unless null), in which case it will have the same type as the element.
1314      * @since 3.10
1315      */
1316     public static short[] addFirst(final short[] array, final short element) {
1317         return array == null ? add(array, element) : insert(0, array, element);
1318     }
1319 
1320     /**
1321      * Copies the given array and adds the given element at the beginning of the new array.
1322      *
1323      * <p>
1324      * The new array contains the same elements of the input array plus the given element in the first positioaddFirstaddFirstaddFirstn. The
1325      * component type of the new array is the same as that of the input array.
1326      * </p>
1327      *
1328      * <p>
1329      * If the input array is {@code null}, a new one element array is returned whose component type is the same as the
1330      * element, unless the element itself is null, in which case the return type is Object[]
1331      * </p>
1332      *
1333      * <pre>
1334      * ArrayUtils.addFirst(null, null)      = IllegalArgumentException
1335      * ArrayUtils.addFirst(null, "a")       = ["a"]
1336      * ArrayUtils.addFirst(["a"], null)     = [null, "a"]
1337      * ArrayUtils.addFirst(["a"], "b")      = ["b", "a"]
1338      * ArrayUtils.addFirst(["a", "b"], "c") = ["c", "a", "b"]
1339      * </pre>
1340      *
1341      * @param <T> the component type of the array
1342      * @param array the array to "add" the element to, may be {@code null}
1343      * @param element the object to add, may be {@code null}
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. If both are null,
1346      *         an IllegalArgumentException is thrown
1347      * @since 3.10
1348      * @throws IllegalArgumentException if both arguments are null
1349      */
1350     public static <T> T[] addFirst(final T[] array, final T element) {
1351         return array == null ? add(array, element) : insert(0, array, element);
1352     }
1353 
1354     /**
1355      * <p>Clones an array returning a typecast result and handling
1356      * {@code null}.
1357      *
1358      * <p>This method returns {@code null} for a {@code null} input array.
1359      *
1360      * @param array  the array to clone, may be {@code null}
1361      * @return the cloned array, {@code null} if {@code null} input
1362      */
1363     public static boolean[] clone(final boolean[] array) {
1364         if (array == null) {
1365             return null;
1366         }
1367         return array.clone();
1368     }
1369 
1370     /**
1371      * <p>Clones an array returning a typecast result and handling
1372      * {@code null}.
1373      *
1374      * <p>This method returns {@code null} for a {@code null} input array.
1375      *
1376      * @param array  the array to clone, may be {@code null}
1377      * @return the cloned array, {@code null} if {@code null} input
1378      */
1379     public static byte[] clone(final byte[] array) {
1380         if (array == null) {
1381             return null;
1382         }
1383         return array.clone();
1384     }
1385 
1386     /**
1387      * <p>Clones an array returning a typecast result and handling
1388      * {@code null}.
1389      *
1390      * <p>This method returns {@code null} for a {@code null} input array.
1391      *
1392      * @param array  the array to clone, may be {@code null}
1393      * @return the cloned array, {@code null} if {@code null} input
1394      */
1395     public static char[] clone(final char[] array) {
1396         if (array == null) {
1397             return null;
1398         }
1399         return array.clone();
1400     }
1401 
1402     /**
1403      * <p>Clones an array returning a typecast result and handling
1404      * {@code null}.
1405      *
1406      * <p>This method returns {@code null} for a {@code null} input array.
1407      *
1408      * @param array  the array to clone, may be {@code null}
1409      * @return the cloned array, {@code null} if {@code null} input
1410      */
1411     public static double[] clone(final double[] array) {
1412         if (array == null) {
1413             return null;
1414         }
1415         return array.clone();
1416     }
1417 
1418     /**
1419      * <p>Clones an array returning a typecast result and handling
1420      * {@code null}.
1421      *
1422      * <p>This method returns {@code null} for a {@code null} input array.
1423      *
1424      * @param array  the array to clone, may be {@code null}
1425      * @return the cloned array, {@code null} if {@code null} input
1426      */
1427     public static float[] clone(final float[] array) {
1428         if (array == null) {
1429             return null;
1430         }
1431         return array.clone();
1432     }
1433 
1434     /**
1435      * <p>Clones an array returning a typecast result and handling
1436      * {@code null}.
1437      *
1438      * <p>This method returns {@code null} for a {@code null} input array.
1439      *
1440      * @param array  the array to clone, may be {@code null}
1441      * @return the cloned array, {@code null} if {@code null} input
1442      */
1443     public static int[] clone(final int[] array) {
1444         if (array == null) {
1445             return null;
1446         }
1447         return array.clone();
1448     }
1449 
1450     /**
1451      * <p>Clones an array returning a typecast result and handling
1452      * {@code null}.
1453      *
1454      * <p>This method returns {@code null} for a {@code null} input array.
1455      *
1456      * @param array  the array to clone, may be {@code null}
1457      * @return the cloned array, {@code null} if {@code null} input
1458      */
1459     public static long[] clone(final long[] array) {
1460         if (array == null) {
1461             return null;
1462         }
1463         return array.clone();
1464     }
1465 
1466     /**
1467      * <p>Clones an array returning a typecast result and handling
1468      * {@code null}.
1469      *
1470      * <p>This method returns {@code null} for a {@code null} input array.
1471      *
1472      * @param array  the array to clone, may be {@code null}
1473      * @return the cloned array, {@code null} if {@code null} input
1474      */
1475     public static short[] clone(final short[] array) {
1476         if (array == null) {
1477             return null;
1478         }
1479         return array.clone();
1480     }
1481 
1482     // Clone
1483     //-----------------------------------------------------------------------
1484     /**
1485      * <p>Shallow clones an array returning a typecast result and handling
1486      * {@code null}.
1487      *
1488      * <p>The objects in the array are not cloned, thus there is no special
1489      * handling for multi-dimensional arrays.
1490      *
1491      * <p>This method returns {@code null} for a {@code null} input array.
1492      *
1493      * @param <T> the component type of the array
1494      * @param array  the array to shallow clone, may be {@code null}
1495      * @return the cloned array, {@code null} if {@code null} input
1496      */
1497     public static <T> T[] clone(final T[] array) {
1498         if (array == null) {
1499             return null;
1500         }
1501         return array.clone();
1502     }
1503 
1504     /**
1505      * <p>Checks if the value is in the given array.
1506      *
1507      * <p>The method returns {@code false} if a {@code null} array is passed in.
1508      *
1509      * @param array  the array to search through
1510      * @param valueToFind  the value to find
1511      * @return {@code true} if the array contains the object
1512      */
1513     public static boolean contains(final boolean[] array, final boolean valueToFind) {
1514         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1515     }
1516 
1517     /**
1518      * <p>Checks if the value is in the given array.
1519      *
1520      * <p>The method returns {@code false} if a {@code null} array is passed in.
1521      *
1522      * @param array  the array to search through
1523      * @param valueToFind  the value to find
1524      * @return {@code true} if the array contains the object
1525      */
1526     public static boolean contains(final byte[] array, final byte valueToFind) {
1527         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1528     }
1529 
1530     /**
1531      * <p>Checks if the value is in the given array.
1532      *
1533      * <p>The method returns {@code false} if a {@code null} array is passed in.
1534      *
1535      * @param array  the array to search through
1536      * @param valueToFind  the value to find
1537      * @return {@code true} if the array contains the object
1538      * @since 2.1
1539      */
1540     public static boolean contains(final char[] array, final char valueToFind) {
1541         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1542     }
1543 
1544     /**
1545      * <p>Checks if the value is in the given array.
1546      *
1547      * <p>The method returns {@code false} if a {@code null} array is passed in.
1548      *
1549      * @param array  the array to search through
1550      * @param valueToFind  the value to find
1551      * @return {@code true} if the array contains the object
1552      */
1553     public static boolean contains(final double[] array, final double valueToFind) {
1554         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1555     }
1556 
1557     /**
1558      * <p>Checks if a value falling within the given tolerance is in the
1559      * given array.  If the array contains a value within the inclusive range
1560      * defined by (value - tolerance) to (value + tolerance).
1561      *
1562      * <p>The method returns {@code false} if a {@code null} array
1563      * is passed in.
1564      *
1565      * @param array  the array to search
1566      * @param valueToFind  the value to find
1567      * @param tolerance  the array contains the tolerance of the search
1568      * @return true if value falling within tolerance is in array
1569      */
1570     public static boolean contains(final double[] array, final double valueToFind, final double tolerance) {
1571         return indexOf(array, valueToFind, 0, tolerance) != INDEX_NOT_FOUND;
1572     }
1573 
1574     /**
1575      * <p>Checks if the value is in the given array.
1576      *
1577      * <p>The method returns {@code false} if a {@code null} array is passed in.
1578      *
1579      * @param array  the array to search through
1580      * @param valueToFind  the value to find
1581      * @return {@code true} if the array contains the object
1582      */
1583     public static boolean contains(final float[] array, final float valueToFind) {
1584         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1585     }
1586 
1587     /**
1588      * <p>Checks if the value is in the given array.
1589      *
1590      * <p>The method returns {@code false} if a {@code null} array is passed in.
1591      *
1592      * @param array  the array to search through
1593      * @param valueToFind  the value to find
1594      * @return {@code true} if the array contains the object
1595      */
1596     public static boolean contains(final int[] array, final int valueToFind) {
1597         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1598     }
1599 
1600     /**
1601      * <p>Checks if the value is in the given array.
1602      *
1603      * <p>The method returns {@code false} if a {@code null} array is passed in.
1604      *
1605      * @param array  the array to search through
1606      * @param valueToFind  the value to find
1607      * @return {@code true} if the array contains the object
1608      */
1609     public static boolean contains(final long[] array, final long valueToFind) {
1610         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1611     }
1612 
1613     /**
1614      * <p>Checks if the object is in the given array.
1615      *
1616      * <p>The method returns {@code false} if a {@code null} array is passed in.
1617      *
1618      * @param array  the array to search through
1619      * @param objectToFind  the object to find
1620      * @return {@code true} if the array contains the object
1621      */
1622     public static boolean contains(final Object[] array, final Object objectToFind) {
1623         return indexOf(array, objectToFind) != INDEX_NOT_FOUND;
1624     }
1625 
1626     /**
1627      * <p>Checks if the value is in the given array.
1628      *
1629      * <p>The method returns {@code false} if a {@code null} array is passed in.
1630      *
1631      * @param array  the array to search through
1632      * @param valueToFind  the value to find
1633      * @return {@code true} if the array contains the object
1634      */
1635     public static boolean contains(final short[] array, final short valueToFind) {
1636         return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1637     }
1638 
1639     /**
1640      * Returns a copy of the given array of size 1 greater than the argument.
1641      * The last value of the array is left to the default value.
1642      *
1643      * @param array The array to copy, must not be {@code null}.
1644      * @param newArrayComponentType If {@code array} is {@code null}, create a
1645      * size 1 array of this type.
1646      * @return A new copy of the array of size 1 greater than the input.
1647      */
1648     private static Object copyArrayGrow1(final Object array, final Class<?> newArrayComponentType) {
1649         if (array != null) {
1650             final int arrayLength = Array.getLength(array);
1651             final Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
1652             System.arraycopy(array, 0, newArray, 0, arrayLength);
1653             return newArray;
1654         }
1655         return Array.newInstance(newArrayComponentType, 1);
1656     }
1657 
1658     /**
1659      * Gets the nTh element of an array or null if the index is out of bounds or the array is null.
1660      *
1661      * @param <T> The type of array elements.
1662      * @param array The array to index.
1663      * @param index The index
1664      * @return the nTh element of an array or null if the index is out of bounds or the array is null.
1665      * @since 3.11
1666      */
1667     public static <T> T get(final T[] array, final int index) {
1668         return get(array, index, null);
1669     }
1670 
1671     /**
1672      * Gets the nTh element of an array or a default value if the index is out of bounds.
1673      *
1674      * @param <T> The type of array elements.
1675      * @param array The array to index.
1676      * @param index The index
1677      * @param defaultValue The return value of the given index is out of bounds.
1678      * @return the nTh element of an array or a default value if the index is out of bounds.
1679      * @since 3.11
1680      */
1681     public static <T> T get(final T[] array, final int index, final T defaultValue) {
1682         return isArrayIndexValid(array, index) ? array[index] : defaultValue;
1683     }
1684 
1685     //-----------------------------------------------------------------------
1686     /**
1687      * <p>Returns the length of the specified array.
1688      * This method can deal with {@code Object} arrays and with primitive arrays.
1689      *
1690      * <p>If the input array is {@code null}, {@code 0} is returned.
1691      *
1692      * <pre>
1693      * ArrayUtils.getLength(null)            = 0
1694      * ArrayUtils.getLength([])              = 0
1695      * ArrayUtils.getLength([null])          = 1
1696      * ArrayUtils.getLength([true, false])   = 2
1697      * ArrayUtils.getLength([1, 2, 3])       = 3
1698      * ArrayUtils.getLength(["a", "b", "c"]) = 3
1699      * </pre>
1700      *
1701      * @param array  the array to retrieve the length from, may be null
1702      * @return The length of the array, or {@code 0} if the array is {@code null}
1703      * @throws IllegalArgumentException if the object argument is not an array.
1704      * @since 2.1
1705      */
1706     public static int getLength(final Object array) {
1707         if (array == null) {
1708             return 0;
1709         }
1710         return Array.getLength(array);
1711     }
1712 
1713     /**
1714      * <p>Get a hash code for an array handling multi-dimensional arrays correctly.
1715      *
1716      * <p>Multi-dimensional primitive arrays are also handled correctly by this method.
1717      *
1718      * @param array  the array to get a hash code for, {@code null} returns zero
1719      * @return a hash code for the array
1720      */
1721     public static int hashCode(final Object array) {
1722         return new HashCodeBuilder().append(array).toHashCode();
1723     }
1724 
1725     /**
1726      * Finds the indices of the given value in the array.
1727      *
1728      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
1729      *
1730      * @param array  the array to search through for the object, may be {@code null}
1731      * @param valueToFind  the value to find
1732      * @return a BitSet of all the the indices of the value within the array,
1733      *  an empty BitSet if not found or {@code null} array input
1734      * @since 3.10
1735      */
1736     public static BitSet indexesOf(final boolean[] array, final boolean valueToFind) {
1737         return indexesOf(array, valueToFind, 0);
1738     }
1739 
1740     /**
1741      * Finds the indices of the given value in the array starting at the given index.
1742      *
1743      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
1744      *
1745      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
1746      * length will return an empty BitSet ({@code -1}).</p>
1747      *
1748      * @param array  the array to search through for the object, may be {@code null}
1749      * @param valueToFind  the value to find
1750      * @param startIndex  the index to start searching at
1751      * @return a BitSet of all the indices of the value within the array,
1752      *  an empty BitSet if not found or {@code null}
1753      *  array input
1754      * @since 3.10
1755      */
1756     public static BitSet indexesOf(final boolean[] array, final boolean valueToFind, int startIndex) {
1757         final BitSet bitSet = new BitSet();
1758 
1759         if (array == null) {
1760             return bitSet;
1761         }
1762 
1763         while (startIndex < array.length) {
1764             startIndex = indexOf(array, valueToFind, startIndex);
1765 
1766             if (startIndex == INDEX_NOT_FOUND) {
1767                 break;
1768             }
1769 
1770             bitSet.set(startIndex);
1771             ++startIndex;
1772         }
1773 
1774         return bitSet;
1775     }
1776 
1777     /**
1778      * Finds the indices of the given value in the array.
1779      *
1780      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
1781      *
1782      * @param array  the array to search through for the object, may be {@code null}
1783      * @param valueToFind  the value to find
1784      * @return a BitSet of all the indices of the value within the array,
1785      *  an empty BitSet if not found or {@code null} array input
1786      * @since 3.10
1787      */
1788     public static BitSet indexesOf(final byte[] array, final byte valueToFind) {
1789         return indexesOf(array, valueToFind, 0);
1790     }
1791 
1792     /**
1793      * Finds the indices of the given value in the array starting at the given index.
1794      *
1795      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
1796      *
1797      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
1798      * length will return an empty BitSet.</p>
1799      *
1800      * @param array  the array to search through for the object, may be {@code null}
1801      * @param valueToFind  the value to find
1802      * @param startIndex  the index to start searching at
1803      * @return a BitSet of all the indices of the value within the array,
1804      *  an empty BitSet if not found or {@code null} array input
1805      * @since 3.10
1806      */
1807     public static BitSet indexesOf(final byte[] array, final byte valueToFind, int startIndex) {
1808         final BitSet bitSet = new BitSet();
1809 
1810         if (array == null) {
1811             return bitSet;
1812         }
1813 
1814         while (startIndex < array.length) {
1815             startIndex = indexOf(array, valueToFind, startIndex);
1816 
1817             if (startIndex == INDEX_NOT_FOUND) {
1818                 break;
1819             }
1820 
1821             bitSet.set(startIndex);
1822             ++startIndex;
1823         }
1824 
1825         return bitSet;
1826     }
1827 
1828     /**
1829      * Finds the indices of the given value in the array.
1830      *
1831      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
1832      *
1833      * @param array  the array to search through for the object, may be {@code null}
1834      * @param valueToFind  the value to find
1835      * @return a BitSet of all the indices of the value within the array,
1836      *  an empty BitSet if not found or {@code null} array input
1837      * @since 3.10
1838      */
1839     public static BitSet indexesOf(final char[] array, final char valueToFind) {
1840         return indexesOf(array, valueToFind, 0);
1841     }
1842 
1843     /**
1844      * Finds the indices of the given value in the array starting at the given index.
1845      *
1846      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
1847      *
1848      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
1849      * length will return an empty BitSet.</p>
1850      *
1851      * @param array  the array to search through for the object, may be {@code null}
1852      * @param valueToFind  the value to find
1853      * @param startIndex  the index to start searching at
1854      * @return a BitSet of all the indices of the value within the array,
1855      *  an empty BitSet if not found or {@code null} array input
1856      * @since 3.10
1857      */
1858     public static BitSet indexesOf(final char[] array, final char valueToFind, int startIndex) {
1859         final BitSet bitSet = new BitSet();
1860 
1861         if (array == null) {
1862             return bitSet;
1863         }
1864 
1865         while (startIndex < array.length) {
1866             startIndex = indexOf(array, valueToFind, startIndex);
1867 
1868             if (startIndex == INDEX_NOT_FOUND) {
1869                 break;
1870             }
1871 
1872             bitSet.set(startIndex);
1873             ++startIndex;
1874         }
1875 
1876         return bitSet;
1877     }
1878 
1879     /**
1880      * Finds the indices of the given value in the array.
1881      *
1882      * <p>This method returns empty BitSet for a {@code null} input array.</p>
1883      *
1884      * @param array  the array to search through for the object, may be {@code null}
1885      * @param valueToFind  the value to find
1886      * @return a BitSet of all the indices of the value within the array,
1887      *  an empty BitSet if not found or {@code null} array input
1888      * @since 3.10
1889      */
1890     public static BitSet indexesOf(final double[] array, final double valueToFind) {
1891         return indexesOf(array, valueToFind, 0);
1892     }
1893 
1894     /**
1895      * Finds the indices of the given value within a given tolerance in the array.
1896      *
1897      * <p>
1898      * This method will return all the indices of the value which fall between the region
1899      * defined by valueToFind - tolerance and valueToFind + tolerance, each time between the nearest integers.
1900      * </p>
1901      *
1902      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
1903      *
1904      * @param array  the array to search through for the object, may be {@code null}
1905      * @param valueToFind  the value to find
1906      * @param tolerance tolerance of the search
1907      * @return a BitSet of all the indices of the value within the array,
1908      *  an empty BitSet if not found or {@code null} array input
1909      * @since 3.10
1910      */
1911     public static BitSet indexesOf(final double[] array, final double valueToFind, final double tolerance) {
1912         return indexesOf(array, valueToFind, 0, tolerance);
1913     }
1914 
1915     /**
1916      * Finds the indices of the given value in the array starting at the given index.
1917      *
1918      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
1919      *
1920      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
1921      * length will return an empty BitSet.</p>
1922      *
1923      * @param array  the array to search through for the object, may be {@code null}
1924      * @param valueToFind  the value to find
1925      * @param startIndex  the index to start searching at
1926      * @return a BitSet of the indices of the value within the array,
1927      *  an empty BitSet if not found or {@code null} array input
1928      * @since 3.10
1929      */
1930     public static BitSet indexesOf(final double[] array, final double valueToFind, int startIndex) {
1931         final BitSet bitSet = new BitSet();
1932 
1933         if (array == null) {
1934             return bitSet;
1935         }
1936 
1937         while (startIndex < array.length) {
1938             startIndex = indexOf(array, valueToFind, startIndex);
1939 
1940             if (startIndex == INDEX_NOT_FOUND) {
1941                 break;
1942             }
1943 
1944             bitSet.set(startIndex);
1945             ++startIndex;
1946         }
1947 
1948         return bitSet;
1949     }
1950 
1951     /**
1952      * Finds the indices of the given value in the array starting at the given index.
1953      *
1954      * <p>
1955      * This method will return the indices of the values which fall between the region
1956      * defined by valueToFind - tolerance and valueToFind + tolerance, between the nearest integers.
1957      * </p>
1958      *
1959      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
1960      *
1961      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
1962      * length will return an empty BitSet.</p>
1963      *
1964      * @param array  the array to search through for the object, may be {@code null}
1965      * @param valueToFind  the value to find
1966      * @param startIndex  the index to start searching at
1967      * @param tolerance tolerance of the search
1968      * @return a BitSet of the indices of the value within the array,
1969      *  an empty BitSet if not found or {@code null} array input
1970      * @since 3.10
1971      */
1972     public static BitSet indexesOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
1973         final BitSet bitSet = new BitSet();
1974 
1975         if (array == null) {
1976             return bitSet;
1977         }
1978 
1979         while (startIndex < array.length) {
1980             startIndex = indexOf(array, valueToFind, startIndex, tolerance);
1981 
1982             if (startIndex == INDEX_NOT_FOUND) {
1983                 break;
1984             }
1985 
1986             bitSet.set(startIndex);
1987             ++startIndex;
1988         }
1989 
1990         return bitSet;
1991     }
1992 
1993     /**
1994      * Finds the indices of the given value in the array.
1995      *
1996      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
1997      *
1998      * @param array  the array to search through for the object, may be {@code null}
1999      * @param valueToFind  the value to find
2000      * @return a BitSet of all the indices of the value within the array,
2001      *  an empty BitSet if not found or {@code null} array input
2002      * @since 3.10
2003      */
2004     public static BitSet indexesOf(final float[] array, final float valueToFind) {
2005         return indexesOf(array, valueToFind, 0);
2006     }
2007 
2008     /**
2009      * Finds the indices of the given value in the array starting at the given index.
2010      *
2011      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2012      *
2013      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2014      * length will return empty BitSet.</p>
2015      *
2016      * @param array  the array to search through for the object, may be {@code null}
2017      * @param valueToFind  the value to find
2018      * @param startIndex  the index to start searching at
2019      * @return a BitSet of all the indices of the value within the array,
2020      *  an empty BitSet if not found or {@code null} array input
2021      * @since 3.10
2022      */
2023     public static BitSet indexesOf(final float[] array, final float valueToFind, int startIndex) {
2024         final BitSet bitSet = new BitSet();
2025 
2026         if (array == null) {
2027             return bitSet;
2028         }
2029 
2030         while (startIndex < array.length) {
2031             startIndex = indexOf(array, valueToFind, startIndex);
2032 
2033             if (startIndex == INDEX_NOT_FOUND) {
2034                 break;
2035             }
2036 
2037             bitSet.set(startIndex);
2038             ++startIndex;
2039         }
2040 
2041         return bitSet;
2042     }
2043 
2044     /**
2045      * Finds the indices of the given value in the array.
2046      *
2047      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2048      *
2049      * @param array  the array to search through for the object, may be {@code null}
2050      * @param valueToFind  the value to find
2051      * @return a BitSet of all the indices of the value within the array,
2052      *  an empty BitSet if not found or {@code null} array input
2053      * @since 3.10
2054      */
2055     public static BitSet indexesOf(final int[] array, final int valueToFind) {
2056         return indexesOf(array, valueToFind, 0);
2057     }
2058 
2059     /**
2060      * Finds the indices of the given value in the array starting at the given index.
2061      *
2062      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2063      *
2064      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2065      * length will return an empty BitSet.</p>
2066      *
2067      * @param array  the array to search through for the object, may be {@code null}
2068      * @param valueToFind  the value to find
2069      * @param startIndex  the index to start searching at
2070      * @return a BitSet of all the indices of the value within the array,
2071      *  an empty BitSet if not found or {@code null} array input
2072      * @since 3.10
2073      */
2074     public static BitSet indexesOf(final int[] array, final int valueToFind, int startIndex) {
2075         final BitSet bitSet = new BitSet();
2076 
2077         if (array == null) {
2078             return bitSet;
2079         }
2080 
2081         while (startIndex < array.length) {
2082             startIndex = indexOf(array, valueToFind, startIndex);
2083 
2084             if (startIndex == INDEX_NOT_FOUND) {
2085                 break;
2086             }
2087 
2088             bitSet.set(startIndex);
2089             ++startIndex;
2090         }
2091 
2092         return bitSet;
2093     }
2094 
2095     /**
2096      * Finds the indices of the given value in the array.
2097      *
2098      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2099      *
2100      * @param array  the array to search through for the object, may be {@code null}
2101      * @param valueToFind  the value to find
2102      * @return a BitSet of all the indices of the value within the array,
2103      *  an empty BitSet if not found or {@code null} array input
2104      * @since 3.10
2105      */
2106     public static BitSet indexesOf(final long[] array, final long valueToFind) {
2107         return indexesOf(array, valueToFind, 0);
2108     }
2109 
2110     /**
2111      * Finds the indices of the given value in the array starting at the given index.
2112      *
2113      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2114      *
2115      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2116      * length will return an empty BitSet.</p>
2117      *
2118      * @param array  the array to search through for the object, may be {@code null}
2119      * @param valueToFind  the value to find
2120      * @param startIndex  the index to start searching at
2121      * @return a BitSet of all the indices of the value within the array,
2122      *  an empty BitSet if not found or {@code null} array input
2123      * @since 3.10
2124      */
2125     public static BitSet indexesOf(final long[] array, final long valueToFind, int startIndex) {
2126         final BitSet bitSet = new BitSet();
2127 
2128         if (array == null) {
2129             return bitSet;
2130         }
2131 
2132         while (startIndex < array.length) {
2133             startIndex = indexOf(array, valueToFind, startIndex);
2134 
2135             if (startIndex == INDEX_NOT_FOUND) {
2136                 break;
2137             }
2138 
2139             bitSet.set(startIndex);
2140             ++startIndex;
2141         }
2142 
2143         return bitSet;
2144     }
2145 
2146     /**
2147      * Finds the indices of the given object in the array.
2148      *
2149      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2150      *
2151      * @param array  the array to search through for the object, may be {@code null}
2152      * @param objectToFind  the object to find, may be {@code null}
2153      * @return a BitSet of all the indices of the object within the array,
2154      *  an empty BitSet if not found or {@code null} array input
2155      * @since 3.10
2156      */
2157     public static BitSet indexesOf(final Object[] array, final Object objectToFind) {
2158         return indexesOf(array, objectToFind, 0);
2159     }
2160 
2161     /**
2162      * Finds the indices of the given object in the array starting at the given index.
2163      *
2164      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2165      *
2166      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2167      * length will return an empty BitSet.</p>
2168      *
2169      * @param array  the array to search through for the object, may be {@code null}
2170      * @param objectToFind  the object to find, may be {@code null}
2171      * @param startIndex  the index to start searching at
2172      * @return a BitSet of all the indices of the object within the array starting at the index,
2173      *  an empty BitSet if not found or {@code null} array input
2174      * @since 3.10
2175      */
2176     public static BitSet indexesOf(final Object[] array, final Object objectToFind, int startIndex) {
2177         final BitSet bitSet = new BitSet();
2178 
2179         if (array == null) {
2180             return bitSet;
2181         }
2182 
2183         while (startIndex < array.length) {
2184             startIndex = indexOf(array, objectToFind, startIndex);
2185 
2186             if (startIndex == INDEX_NOT_FOUND) {
2187                 break;
2188             }
2189 
2190             bitSet.set(startIndex);
2191             ++startIndex;
2192         }
2193 
2194         return bitSet;
2195     }
2196 
2197     /**
2198      * Finds the indices of the given value in the array.
2199      *
2200      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2201      *
2202      * @param array  the array to search through for the object, may be {@code null}
2203      * @param valueToFind  the value to find
2204      * @return a BitSet of all the indices of the value within the array,
2205      *  an empty BitSet if not found or {@code null} array input
2206      * @since 3.10
2207      */
2208     public static BitSet indexesOf(final short[] array, final short valueToFind) {
2209         return indexesOf(array, valueToFind, 0);
2210     }
2211 
2212     /**
2213      * Finds the indices of the given value in the array starting at the given index.
2214      *
2215      * <p>This method returns an empty BitSet for a {@code null} input array.</p>
2216      *
2217      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2218      * length will return an empty BitSet.</p>
2219      *
2220      * @param array  the array to search through for the object, may be {@code null}
2221      * @param valueToFind  the value to find
2222      * @param startIndex  the index to start searching at
2223      * @return a BitSet of all the indices of the value within the array,
2224      *  an empty BitSet if not found or {@code null} array input
2225      * @since 3.10
2226      */
2227     public static BitSet indexesOf(final short[] array, final short valueToFind, int startIndex) {
2228         final BitSet bitSet = new BitSet();
2229 
2230         if (array == null) {
2231             return bitSet;
2232         }
2233 
2234         while (startIndex < array.length) {
2235             startIndex = indexOf(array, valueToFind, startIndex);
2236 
2237             if (startIndex == INDEX_NOT_FOUND) {
2238                 break;
2239             }
2240 
2241             bitSet.set(startIndex);
2242             ++startIndex;
2243         }
2244 
2245         return bitSet;
2246     }
2247 
2248     // boolean IndexOf
2249     //-----------------------------------------------------------------------
2250     /**
2251      * <p>Finds the index of the given value in the array.
2252      *
2253      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2254      *
2255      * @param array  the array to search through for the object, may be {@code null}
2256      * @param valueToFind  the value to find
2257      * @return the index of the value within the array,
2258      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2259      */
2260     public static int indexOf(final boolean[] array, final boolean valueToFind) {
2261         return indexOf(array, valueToFind, 0);
2262     }
2263 
2264     /**
2265      * <p>Finds the index of the given value in the array starting at the given index.
2266      *
2267      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2268      *
2269      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2270      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2271      *
2272      * @param array  the array to search through for the object, may be {@code null}
2273      * @param valueToFind  the value to find
2274      * @param startIndex  the index to start searching at
2275      * @return the index of the value within the array,
2276      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null}
2277      *  array input
2278      */
2279     public static int indexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
2280         if (isEmpty(array)) {
2281             return INDEX_NOT_FOUND;
2282         }
2283         if (startIndex < 0) {
2284             startIndex = 0;
2285         }
2286         for (int i = startIndex; i < array.length; i++) {
2287             if (valueToFind == array[i]) {
2288                 return i;
2289             }
2290         }
2291         return INDEX_NOT_FOUND;
2292     }
2293 
2294     // byte IndexOf
2295     //-----------------------------------------------------------------------
2296     /**
2297      * <p>Finds the index of the given value in the array.
2298      *
2299      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2300      *
2301      * @param array  the array to search through for the object, may be {@code null}
2302      * @param valueToFind  the value to find
2303      * @return the index of the value within the array,
2304      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2305      */
2306     public static int indexOf(final byte[] array, final byte valueToFind) {
2307         return indexOf(array, valueToFind, 0);
2308     }
2309 
2310     /**
2311      * <p>Finds the index of the given value in the array starting at the given index.
2312      *
2313      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2314      *
2315      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2316      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2317      *
2318      * @param array  the array to search through for the object, may be {@code null}
2319      * @param valueToFind  the value to find
2320      * @param startIndex  the index to start searching at
2321      * @return the index of the value within the array,
2322      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2323      */
2324     public static int indexOf(final byte[] array, final byte valueToFind, int startIndex) {
2325         if (array == null) {
2326             return INDEX_NOT_FOUND;
2327         }
2328         if (startIndex < 0) {
2329             startIndex = 0;
2330         }
2331         for (int i = startIndex; i < array.length; i++) {
2332             if (valueToFind == array[i]) {
2333                 return i;
2334             }
2335         }
2336         return INDEX_NOT_FOUND;
2337     }
2338 
2339     // char IndexOf
2340     //-----------------------------------------------------------------------
2341     /**
2342      * <p>Finds the index of the given value in the array.
2343      *
2344      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2345      *
2346      * @param array  the array to search through for the object, may be {@code null}
2347      * @param valueToFind  the value to find
2348      * @return the index of the value within the array,
2349      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2350      * @since 2.1
2351      */
2352     public static int indexOf(final char[] array, final char valueToFind) {
2353         return indexOf(array, valueToFind, 0);
2354     }
2355 
2356     /**
2357      * <p>Finds the index of the given value in the array starting at the given index.
2358      *
2359      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2360      *
2361      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2362      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2363      *
2364      * @param array  the array to search through for the object, may be {@code null}
2365      * @param valueToFind  the value to find
2366      * @param startIndex  the index to start searching at
2367      * @return the index of the value within the array,
2368      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2369      * @since 2.1
2370      */
2371     public static int indexOf(final char[] array, final char valueToFind, int startIndex) {
2372         if (array == null) {
2373             return INDEX_NOT_FOUND;
2374         }
2375         if (startIndex < 0) {
2376             startIndex = 0;
2377         }
2378         for (int i = startIndex; i < array.length; i++) {
2379             if (valueToFind == array[i]) {
2380                 return i;
2381             }
2382         }
2383         return INDEX_NOT_FOUND;
2384     }
2385 
2386     // double IndexOf
2387     //-----------------------------------------------------------------------
2388     /**
2389      * <p>Finds the index of the given value in the array.
2390      *
2391      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2392      *
2393      * @param array  the array to search through for the object, may be {@code null}
2394      * @param valueToFind  the value to find
2395      * @return the index of the value within the array,
2396      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2397      */
2398     public static int indexOf(final double[] array, final double valueToFind) {
2399         return indexOf(array, valueToFind, 0);
2400     }
2401 
2402     /**
2403      * <p>Finds the index of the given value within a given tolerance in the array.
2404      * This method will return the index of the first value which falls between the region
2405      * defined by valueToFind - tolerance and valueToFind + tolerance.
2406      *
2407      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2408      *
2409      * @param array  the array to search through for the object, may be {@code null}
2410      * @param valueToFind  the value to find
2411      * @param tolerance tolerance of the search
2412      * @return the index of the value within the array,
2413      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2414      */
2415     public static int indexOf(final double[] array, final double valueToFind, final double tolerance) {
2416         return indexOf(array, valueToFind, 0, tolerance);
2417     }
2418 
2419     /**
2420      * <p>Finds the index of the given value in the array starting at the given index.
2421      *
2422      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2423      *
2424      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2425      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2426      *
2427      * @param array  the array to search through for the object, may be {@code null}
2428      * @param valueToFind  the value to find
2429      * @param startIndex  the index to start searching at
2430      * @return the index of the value within the array,
2431      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2432      */
2433     public static int indexOf(final double[] array, final double valueToFind, int startIndex) {
2434         if (isEmpty(array)) {
2435             return INDEX_NOT_FOUND;
2436         }
2437         if (startIndex < 0) {
2438             startIndex = 0;
2439         }
2440         final boolean searchNaN = Double.isNaN(valueToFind);
2441         for (int i = startIndex; i < array.length; i++) {
2442             final double element = array[i];
2443             if (valueToFind == element || (searchNaN && Double.isNaN(element))) {
2444                 return i;
2445             }
2446         }
2447         return INDEX_NOT_FOUND;
2448     }
2449 
2450     /**
2451      * <p>Finds the index of the given value in the array starting at the given index.
2452      * This method will return the index of the first value which falls between the region
2453      * defined by valueToFind - tolerance and valueToFind + tolerance.
2454      *
2455      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2456      *
2457      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2458      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2459      *
2460      * @param array  the array to search through for the object, may be {@code null}
2461      * @param valueToFind  the value to find
2462      * @param startIndex  the index to start searching at
2463      * @param tolerance tolerance of the search
2464      * @return the index of the value within the array,
2465      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2466      */
2467     public static int indexOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
2468         if (isEmpty(array)) {
2469             return INDEX_NOT_FOUND;
2470         }
2471         if (startIndex < 0) {
2472             startIndex = 0;
2473         }
2474         final double min = valueToFind - tolerance;
2475         final double max = valueToFind + tolerance;
2476         for (int i = startIndex; i < array.length; i++) {
2477             if (array[i] >= min && array[i] <= max) {
2478                 return i;
2479             }
2480         }
2481         return INDEX_NOT_FOUND;
2482     }
2483 
2484     // float IndexOf
2485     //-----------------------------------------------------------------------
2486     /**
2487      * <p>Finds the index of the given value in the array.
2488      *
2489      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2490      *
2491      * @param array  the array to search through for the object, may be {@code null}
2492      * @param valueToFind  the value to find
2493      * @return the index of the value within the array,
2494      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2495      */
2496     public static int indexOf(final float[] array, final float valueToFind) {
2497         return indexOf(array, valueToFind, 0);
2498     }
2499 
2500     /**
2501      * <p>Finds the index of the given value in the array starting at the given index.
2502      *
2503      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2504      *
2505      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2506      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2507      *
2508      * @param array  the array to search through for the object, may be {@code null}
2509      * @param valueToFind  the value to find
2510      * @param startIndex  the index to start searching at
2511      * @return the index of the value within the array,
2512      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2513      */
2514     public static int indexOf(final float[] array, final float valueToFind, int startIndex) {
2515         if (isEmpty(array)) {
2516             return INDEX_NOT_FOUND;
2517         }
2518         if (startIndex < 0) {
2519             startIndex = 0;
2520         }
2521         final boolean searchNaN = Float.isNaN(valueToFind);
2522         for (int i = startIndex; i < array.length; i++) {
2523             final float element = array[i];
2524             if (valueToFind == element || (searchNaN && Float.isNaN(element))) {
2525                 return i;
2526             }
2527         }
2528         return INDEX_NOT_FOUND;
2529     }
2530 
2531     // int IndexOf
2532     //-----------------------------------------------------------------------
2533     /**
2534      * <p>Finds the index of the given value in the array.
2535      *
2536      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2537      *
2538      * @param array  the array to search through for the object, may be {@code null}
2539      * @param valueToFind  the value to find
2540      * @return the index of the value within the array,
2541      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2542      */
2543     public static int indexOf(final int[] array, final int valueToFind) {
2544         return indexOf(array, valueToFind, 0);
2545     }
2546 
2547    /**
2548  * <p>Finds the index of the given value in the array starting at the given index.
2549  *
2550  * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2551  *
2552  * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2553  * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2554  *
2555  * @param array  the array to search through for the object, may be {@code null}
2556  * @param valueToFind  the value to find
2557  * @param startIndex  the index to start searching at
2558  * @return the index of the value within the array,
2559  *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2560  */
2561 public static int indexOf(final int[] array, final int valueToFind, int startIndex) {
2562     if (array == null) {
2563         return INDEX_NOT_FOUND;
2564     }
2565     if (startIndex < 0) {
2566         startIndex = 0;
2567     }
2568     for (int i = startIndex; i < array.length; i++) {
2569         if (valueToFind == array[i]) {
2570             return i;
2571         }
2572     }
2573     return INDEX_NOT_FOUND;
2574 }
2575 
2576     // long IndexOf
2577     //-----------------------------------------------------------------------
2578     /**
2579      * <p>Finds the index of the given value in the array.
2580      *
2581      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2582      *
2583      * @param array  the array to search through for the object, may be {@code null}
2584      * @param valueToFind  the value to find
2585      * @return the index of the value within the array,
2586      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2587      */
2588     public static int indexOf(final long[] array, final long valueToFind) {
2589         return indexOf(array, valueToFind, 0);
2590     }
2591 
2592     /**
2593      * <p>Finds the index of the given value in the array starting at the given index.
2594      *
2595      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2596      *
2597      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2598      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2599      *
2600      * @param array  the array to search through for the object, may be {@code null}
2601      * @param valueToFind  the value to find
2602      * @param startIndex  the index to start searching at
2603      * @return the index of the value within the array,
2604      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2605      */
2606     public static int indexOf(final long[] array, final long valueToFind, int startIndex) {
2607         if (array == null) {
2608             return INDEX_NOT_FOUND;
2609         }
2610         if (startIndex < 0) {
2611             startIndex = 0;
2612         }
2613         for (int i = startIndex; i < array.length; i++) {
2614             if (valueToFind == array[i]) {
2615                 return i;
2616             }
2617         }
2618         return INDEX_NOT_FOUND;
2619     }
2620 
2621     // Object IndexOf
2622     //-----------------------------------------------------------------------
2623     /**
2624      * <p>Finds the index of the given object in the array.
2625      *
2626      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2627      *
2628      * @param array  the array to search through for the object, may be {@code null}
2629      * @param objectToFind  the object to find, may be {@code null}
2630      * @return the index of the object within the array,
2631      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2632      */
2633     public static int indexOf(final Object[] array, final Object objectToFind) {
2634         return indexOf(array, objectToFind, 0);
2635     }
2636 
2637     /**
2638      * <p>Finds the index of the given object in the array starting at the given index.
2639      *
2640      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2641      *
2642      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2643      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2644      *
2645      * @param array  the array to search through for the object, may be {@code null}
2646      * @param objectToFind  the object to find, may be {@code null}
2647      * @param startIndex  the index to start searching at
2648      * @return the index of the object within the array starting at the index,
2649      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2650      */
2651     public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
2652         if (array == null) {
2653             return INDEX_NOT_FOUND;
2654         }
2655         if (startIndex < 0) {
2656             startIndex = 0;
2657         }
2658         if (objectToFind == null) {
2659             for (int i = startIndex; i < array.length; i++) {
2660                 if (array[i] == null) {
2661                     return i;
2662                 }
2663             }
2664         } else {
2665             for (int i = startIndex; i < array.length; i++) {
2666                 if (objectToFind.equals(array[i])) {
2667                     return i;
2668                 }
2669             }
2670         }
2671         return INDEX_NOT_FOUND;
2672     }
2673 
2674     // short IndexOf
2675     //-----------------------------------------------------------------------
2676     /**
2677      * <p>Finds the index of the given value in the array.
2678      *
2679      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2680      *
2681      * @param array  the array to search through for the object, may be {@code null}
2682      * @param valueToFind  the value to find
2683      * @return the index of the value within the array,
2684      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2685      */
2686     public static int indexOf(final short[] array, final short valueToFind) {
2687         return indexOf(array, valueToFind, 0);
2688     }
2689 
2690     /**
2691      * <p>Finds the index of the given value in the array starting at the given index.
2692      *
2693      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
2694      *
2695      * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2696      * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
2697      *
2698      * @param array  the array to search through for the object, may be {@code null}
2699      * @param valueToFind  the value to find
2700      * @param startIndex  the index to start searching at
2701      * @return the index of the value within the array,
2702      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2703      */
2704     public static int indexOf(final short[] array, final short valueToFind, int startIndex) {
2705         if (array == null) {
2706             return INDEX_NOT_FOUND;
2707         }
2708         if (startIndex < 0) {
2709             startIndex = 0;
2710         }
2711         for (int i = startIndex; i < array.length; i++) {
2712             if (valueToFind == array[i]) {
2713                 return i;
2714             }
2715         }
2716         return INDEX_NOT_FOUND;
2717     }
2718 
2719     /**
2720      * <p>Inserts elements into an array at the given index (starting from zero).</p>
2721      *
2722      * <p>When an array is returned, it is always a new array.</p>
2723      *
2724      * <pre>
2725      * ArrayUtils.insert(index, null, null)      = null
2726      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
2727      * ArrayUtils.insert(index, null, values)    = null
2728      * </pre>
2729      *
2730      * @param index the position within {@code array} to insert the new values
2731      * @param array the array to insert the values into, may be {@code null}
2732      * @param values the new values to insert, may be {@code null}
2733      * @return The new array.
2734      * @throws IndexOutOfBoundsException if {@code array} is provided
2735      * and either {@code index < 0} or {@code index > array.length}
2736      * @since 3.6
2737      */
2738     public static boolean[] insert(final int index, final boolean[] array, final boolean... values) {
2739         if (array == null) {
2740             return null;
2741         }
2742         if (ArrayUtils.isEmpty(values)) {
2743             return clone(array);
2744         }
2745         if (index < 0 || index > array.length) {
2746             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
2747         }
2748 
2749         final boolean[] result = new boolean[array.length + values.length];
2750 
2751         System.arraycopy(values, 0, result, index, values.length);
2752         if (index > 0) {
2753             System.arraycopy(array, 0, result, 0, index);
2754         }
2755         if (index < array.length) {
2756             System.arraycopy(array, index, result, index + values.length, array.length - index);
2757         }
2758         return result;
2759     }
2760 
2761     /**
2762      * <p>Inserts elements into an array at the given index (starting from zero).</p>
2763      *
2764      * <p>When an array is returned, it is always a new array.</p>
2765      *
2766      * <pre>
2767      * ArrayUtils.insert(index, null, null)      = null
2768      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
2769      * ArrayUtils.insert(index, null, values)    = null
2770      * </pre>
2771      *
2772      * @param index the position within {@code array} to insert the new values
2773      * @param array the array to insert the values into, may be {@code null}
2774      * @param values the new values to insert, may be {@code null}
2775      * @return The new array.
2776      * @throws IndexOutOfBoundsException if {@code array} is provided
2777      * and either {@code index < 0} or {@code index > array.length}
2778      * @since 3.6
2779      */
2780     public static byte[] insert(final int index, final byte[] array, final byte... values) {
2781         if (array == null) {
2782             return null;
2783         }
2784         if (ArrayUtils.isEmpty(values)) {
2785             return clone(array);
2786         }
2787         if (index < 0 || index > array.length) {
2788             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
2789         }
2790 
2791         final byte[] result = new byte[array.length + values.length];
2792 
2793         System.arraycopy(values, 0, result, index, values.length);
2794         if (index > 0) {
2795             System.arraycopy(array, 0, result, 0, index);
2796         }
2797         if (index < array.length) {
2798             System.arraycopy(array, index, result, index + values.length, array.length - index);
2799         }
2800         return result;
2801     }
2802 
2803     /**
2804      * <p>Inserts elements into an array at the given index (starting from zero).</p>
2805      *
2806      * <p>When an array is returned, it is always a new array.</p>
2807      *
2808      * <pre>
2809      * ArrayUtils.insert(index, null, null)      = null
2810      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
2811      * ArrayUtils.insert(index, null, values)    = null
2812      * </pre>
2813      *
2814      * @param index the position within {@code array} to insert the new values
2815      * @param array the array to insert the values into, may be {@code null}
2816      * @param values the new values to insert, may be {@code null}
2817      * @return The new array.
2818      * @throws IndexOutOfBoundsException if {@code array} is provided
2819      * and either {@code index < 0} or {@code index > array.length}
2820      * @since 3.6
2821      */
2822     public static char[] insert(final int index, final char[] array, final char... values) {
2823         if (array == null) {
2824             return null;
2825         }
2826         if (ArrayUtils.isEmpty(values)) {
2827             return clone(array);
2828         }
2829         if (index < 0 || index > array.length) {
2830             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
2831         }
2832 
2833         final char[] result = new char[array.length + values.length];
2834 
2835         System.arraycopy(values, 0, result, index, values.length);
2836         if (index > 0) {
2837             System.arraycopy(array, 0, result, 0, index);
2838         }
2839         if (index < array.length) {
2840             System.arraycopy(array, index, result, index + values.length, array.length - index);
2841         }
2842         return result;
2843     }
2844 
2845     /**
2846      * <p>Inserts elements into an array at the given index (starting from zero).</p>
2847      *
2848      * <p>When an array is returned, it is always a new array.</p>
2849      *
2850      * <pre>
2851      * ArrayUtils.insert(index, null, null)      = null
2852      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
2853      * ArrayUtils.insert(index, null, values)    = null
2854      * </pre>
2855      *
2856      * @param index the position within {@code array} to insert the new values
2857      * @param array the array to insert the values into, may be {@code null}
2858      * @param values the new values to insert, may be {@code null}
2859      * @return The new array.
2860      * @throws IndexOutOfBoundsException if {@code array} is provided
2861      * and either {@code index < 0} or {@code index > array.length}
2862      * @since 3.6
2863      */
2864     public static double[] insert(final int index, final double[] array, final double... values) {
2865         if (array == null) {
2866             return null;
2867         }
2868         if (ArrayUtils.isEmpty(values)) {
2869             return clone(array);
2870         }
2871         if (index < 0 || index > array.length) {
2872             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
2873         }
2874 
2875         final double[] result = new double[array.length + values.length];
2876 
2877         System.arraycopy(values, 0, result, index, values.length);
2878         if (index > 0) {
2879             System.arraycopy(array, 0, result, 0, index);
2880         }
2881         if (index < array.length) {
2882             System.arraycopy(array, index, result, index + values.length, array.length - index);
2883         }
2884         return result;
2885     }
2886 
2887     /**
2888      * <p>Inserts elements into an array at the given index (starting from zero).</p>
2889      *
2890      * <p>When an array is returned, it is always a new array.</p>
2891      *
2892      * <pre>
2893      * ArrayUtils.insert(index, null, null)      = null
2894      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
2895      * ArrayUtils.insert(index, null, values)    = null
2896      * </pre>
2897      *
2898      * @param index the position within {@code array} to insert the new values
2899      * @param array the array to insert the values into, may be {@code null}
2900      * @param values the new values to insert, may be {@code null}
2901      * @return The new array.
2902      * @throws IndexOutOfBoundsException if {@code array} is provided
2903      * and either {@code index < 0} or {@code index > array.length}
2904      * @since 3.6
2905      */
2906     public static float[] insert(final int index, final float[] array, final float... values) {
2907         if (array == null) {
2908             return null;
2909         }
2910         if (ArrayUtils.isEmpty(values)) {
2911             return clone(array);
2912         }
2913         if (index < 0 || index > array.length) {
2914             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
2915         }
2916 
2917         final float[] result = new float[array.length + values.length];
2918 
2919         System.arraycopy(values, 0, result, index, values.length);
2920         if (index > 0) {
2921             System.arraycopy(array, 0, result, 0, index);
2922         }
2923         if (index < array.length) {
2924             System.arraycopy(array, index, result, index + values.length, array.length - index);
2925         }
2926         return result;
2927     }
2928 
2929     /**
2930      * <p>Inserts elements into an array at the given index (starting from zero).</p>
2931      *
2932      * <p>When an array is returned, it is always a new array.</p>
2933      *
2934      * <pre>
2935      * ArrayUtils.insert(index, null, null)      = null
2936      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
2937      * ArrayUtils.insert(index, null, values)    = null
2938      * </pre>
2939      *
2940      * @param index the position within {@code array} to insert the new values
2941      * @param array the array to insert the values into, may be {@code null}
2942      * @param values the new values to insert, may be {@code null}
2943      * @return The new array.
2944      * @throws IndexOutOfBoundsException if {@code array} is provided
2945      * and either {@code index < 0} or {@code index > array.length}
2946      * @since 3.6
2947      */
2948     public static int[] insert(final int index, final int[] array, final int... values) {
2949         if (array == null) {
2950             return null;
2951         }
2952         if (ArrayUtils.isEmpty(values)) {
2953             return clone(array);
2954         }
2955         if (index < 0 || index > array.length) {
2956             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
2957         }
2958 
2959         final int[] result = new int[array.length + values.length];
2960 
2961         System.arraycopy(values, 0, result, index, values.length);
2962         if (index > 0) {
2963             System.arraycopy(array, 0, result, 0, index);
2964         }
2965         if (index < array.length) {
2966             System.arraycopy(array, index, result, index + values.length, array.length - index);
2967         }
2968         return result;
2969     }
2970 
2971     /**
2972      * <p>Inserts elements into an array at the given index (starting from zero).</p>
2973      *
2974      * <p>When an array is returned, it is always a new array.</p>
2975      *
2976      * <pre>
2977      * ArrayUtils.insert(index, null, null)      = null
2978      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
2979      * ArrayUtils.insert(index, null, values)    = null
2980      * </pre>
2981      *
2982      * @param index the position within {@code array} to insert the new values
2983      * @param array the array to insert the values into, may be {@code null}
2984      * @param values the new values to insert, may be {@code null}
2985      * @return The new array.
2986      * @throws IndexOutOfBoundsException if {@code array} is provided
2987      * and either {@code index < 0} or {@code index > array.length}
2988      * @since 3.6
2989      */
2990     public static long[] insert(final int index, final long[] array, final long... values) {
2991         if (array == null) {
2992             return null;
2993         }
2994         if (ArrayUtils.isEmpty(values)) {
2995             return clone(array);
2996         }
2997         if (index < 0 || index > array.length) {
2998             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
2999         }
3000 
3001         final long[] result = new long[array.length + values.length];
3002 
3003         System.arraycopy(values, 0, result, index, values.length);
3004         if (index > 0) {
3005             System.arraycopy(array, 0, result, 0, index);
3006         }
3007         if (index < array.length) {
3008             System.arraycopy(array, index, result, index + values.length, array.length - index);
3009         }
3010         return result;
3011     }
3012 
3013     /**
3014      * <p>Inserts elements into an array at the given index (starting from zero).</p>
3015      *
3016      * <p>When an array is returned, it is always a new array.</p>
3017      *
3018      * <pre>
3019      * ArrayUtils.insert(index, null, null)      = null
3020      * ArrayUtils.insert(index, array, null)     = cloned copy of 'array'
3021      * ArrayUtils.insert(index, null, values)    = null
3022      * </pre>
3023      *
3024      * @param index the position within {@code array} to insert the new values
3025      * @param array the array to insert the values into, may be {@code null}
3026      * @param values the new values to insert, may be {@code null}
3027      * @return The new array.
3028      * @throws IndexOutOfBoundsException if {@code array} is provided
3029      * and either {@code index < 0} or {@code index > array.length}
3030      * @since 3.6
3031      */
3032     public static short[] insert(final int index, final short[] array, final short... values) {
3033         if (array == null) {
3034             return null;
3035         }
3036         if (ArrayUtils.isEmpty(values)) {
3037             return clone(array);
3038         }
3039         if (index < 0 || index > array.length) {
3040             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3041         }
3042 
3043         final short[] result = new short[array.length + values.length];
3044 
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      * <p>Inserts elements into an array at the given index (starting from zero).</p>
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 <T> The type of elements in {@code array} and {@code values}
3067      * @param index the position within {@code array} to insert the new values
3068      * @param array the array to insert the values into, may be {@code null}
3069      * @param values the new values to insert, may be {@code null}
3070      * @return The new array.
3071      * @throws IndexOutOfBoundsException if {@code array} is provided
3072      * and either {@code index < 0} or {@code index > array.length}
3073      * @since 3.6
3074      */
3075     @SafeVarargs
3076     public static <T> T[] insert(final int index, final T[] array, final T... values) {
3077         /*
3078          * Note on use of @SafeVarargs:
3079          *
3080          * By returning null when 'array' is null, we avoid returning the vararg
3081          * array to the caller. We also avoid relying on the type of the vararg
3082          * array, by inspecting the component type of 'array'.
3083          */
3084 
3085         if (array == null) {
3086             return null;
3087         }
3088         if (ArrayUtils.isEmpty(values)) {
3089             return clone(array);
3090         }
3091         if (index < 0 || index > array.length) {
3092             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + array.length);
3093         }
3094 
3095         final Class<?> type = array.getClass().getComponentType();
3096         @SuppressWarnings("unchecked") // OK, because array and values are of type T
3097         final
3098         T[] result = (T[]) Array.newInstance(type, array.length + values.length);
3099 
3100         System.arraycopy(values, 0, result, index, values.length);
3101         if (index > 0) {
3102             System.arraycopy(array, 0, result, 0, index);
3103         }
3104         if (index < array.length) {
3105             System.arraycopy(array, index, result, index + values.length, array.length - index);
3106         }
3107         return result;
3108     }
3109 
3110     /**
3111      * Returns whether a given array can safely be accessed at the given index.
3112      *
3113      * <pre>
3114      * ArrayUtils.isArrayIndexValid(null, 0)       = false
3115      * ArrayUtils.isArrayIndexValid([], 0)         = false
3116      * ArrayUtils.isArrayIndexValid(["a"], 0)      = true
3117      * </pre>
3118      *
3119      * @param <T> the component type of the array
3120      * @param array the array to inspect, may be null
3121      * @param index the index of the array to be inspected
3122      * @return Whether the given index is safely-accessible in the given array
3123      * @since 3.8
3124      */
3125     public static <T> boolean isArrayIndexValid(final T[] array, final int index) {
3126         return index >= 0 && getLength(array) > index;
3127     }
3128 
3129     /**
3130      * <p>Checks if an array of primitive booleans is empty or {@code null}.
3131      *
3132      * @param array  the array to test
3133      * @return {@code true} if the array is empty or {@code null}
3134      * @since 2.1
3135      */
3136     public static boolean isEmpty(final boolean[] array) {
3137         return getLength(array) == 0;
3138     }
3139 
3140     /**
3141      * <p>Checks if an array of primitive bytes is empty or {@code null}.
3142      *
3143      * @param array  the array to test
3144      * @return {@code true} if the array is empty or {@code null}
3145      * @since 2.1
3146      */
3147     public static boolean isEmpty(final byte[] array) {
3148         return getLength(array) == 0;
3149     }
3150 
3151     // IndexOf search
3152     // ----------------------------------------------------------------------
3153 
3154     /**
3155      * <p>Checks if an array of primitive chars is empty or {@code null}.
3156      *
3157      * @param array  the array to test
3158      * @return {@code true} if the array is empty or {@code null}
3159      * @since 2.1
3160      */
3161     public static boolean isEmpty(final char[] array) {
3162         return getLength(array) == 0;
3163     }
3164 
3165     /**
3166      * <p>Checks if an array of primitive doubles is empty or {@code null}.
3167      *
3168      * @param array  the array to test
3169      * @return {@code true} if the array is empty or {@code null}
3170      * @since 2.1
3171      */
3172     public static boolean isEmpty(final double[] array) {
3173         return getLength(array) == 0;
3174     }
3175 
3176     /**
3177      * <p>Checks if an array of primitive floats is empty or {@code null}.
3178      *
3179      * @param array  the array to test
3180      * @return {@code true} if the array is empty or {@code null}
3181      * @since 2.1
3182      */
3183     public static boolean isEmpty(final float[] array) {
3184         return getLength(array) == 0;
3185     }
3186 
3187     /**
3188      * <p>Checks if an array of primitive ints is empty or {@code null}.
3189      *
3190      * @param array  the array to test
3191      * @return {@code true} if the array is empty or {@code null}
3192      * @since 2.1
3193      */
3194     public static boolean isEmpty(final int[] array) {
3195         return getLength(array) == 0;
3196     }
3197 
3198 
3199 
3200     /**
3201      * <p>Checks if an array of primitive longs is empty or {@code null}.
3202      *
3203      * @param array  the array to test
3204      * @return {@code true} if the array is empty or {@code null}
3205      * @since 2.1
3206      */
3207     public static boolean isEmpty(final long[] array) {
3208         return getLength(array) == 0;
3209     }
3210 
3211     // ----------------------------------------------------------------------
3212     /**
3213      * <p>Checks if an array of Objects is empty or {@code null}.
3214      *
3215      * @param array  the array to test
3216      * @return {@code true} if the array is empty or {@code null}
3217      * @since 2.1
3218      */
3219     public static boolean isEmpty(final Object[] array) {
3220         return getLength(array) == 0;
3221     }
3222 
3223     /**
3224      * <p>Checks if an array of primitive shorts is empty or {@code null}.
3225      *
3226      * @param array  the array to test
3227      * @return {@code true} if the array is empty or {@code null}
3228      * @since 2.1
3229      */
3230     public static boolean isEmpty(final short[] array) {
3231         return getLength(array) == 0;
3232     }
3233 
3234     /**
3235      * <p>Compares two arrays, using equals(), handling multi-dimensional arrays
3236      * correctly.
3237      *
3238      * <p>Multi-dimensional primitive arrays are also handled correctly by this method.
3239      *
3240      * @param array1  the left hand array to compare, may be {@code null}
3241      * @param array2  the right hand array to compare, may be {@code null}
3242      * @return {@code true} if the arrays are equal
3243      * @deprecated this method has been replaced by {@code java.util.Objects.deepEquals(Object, Object)} and will be
3244      * removed from future releases.
3245      */
3246     @Deprecated
3247     public static boolean isEquals(final Object array1, final Object array2) {
3248         return new EqualsBuilder().append(array1, array2).isEquals();
3249     }
3250 
3251     /**
3252      * <p>Checks if an array of primitive booleans is not empty and not {@code null}.
3253      *
3254      * @param array  the array to test
3255      * @return {@code true} if the array is not empty and not {@code null}
3256      * @since 2.5
3257      */
3258     public static boolean isNotEmpty(final boolean[] array) {
3259         return !isEmpty(array);
3260     }
3261 
3262     /**
3263      * <p>Checks if an array of primitive bytes is not empty and not {@code null}.
3264      *
3265      * @param array  the array to test
3266      * @return {@code true} if the array is not empty and not {@code null}
3267      * @since 2.5
3268      */
3269     public static boolean isNotEmpty(final byte[] array) {
3270         return !isEmpty(array);
3271     }
3272 
3273     /**
3274      * <p>Checks if an array of primitive chars is not empty and not {@code null}.
3275      *
3276      * @param array  the array to test
3277      * @return {@code true} if the array is not empty and not {@code null}
3278      * @since 2.5
3279      */
3280     public static boolean isNotEmpty(final char[] array) {
3281         return !isEmpty(array);
3282     }
3283 
3284     /**
3285      * <p>Checks if an array of primitive doubles is not empty and not {@code null}.
3286      *
3287      * @param array  the array to test
3288      * @return {@code true} if the array is not empty and not {@code null}
3289      * @since 2.5
3290      */
3291     public static boolean isNotEmpty(final double[] array) {
3292         return !isEmpty(array);
3293     }
3294 
3295     /**
3296      * <p>Checks if an array of primitive floats is not empty and not {@code null}.
3297      *
3298      * @param array  the array to test
3299      * @return {@code true} if the array is not empty and not {@code null}
3300      * @since 2.5
3301      */
3302     public static boolean isNotEmpty(final float[] array) {
3303         return !isEmpty(array);
3304     }
3305 
3306     /**
3307      * <p>Checks if an array of primitive ints is not empty and not {@code null}.
3308      *
3309      * @param array  the array to test
3310      * @return {@code true} if the array is not empty and not {@code null}
3311      * @since 2.5
3312      */
3313     public static boolean isNotEmpty(final int[] array) {
3314         return !isEmpty(array);
3315     }
3316 
3317     /**
3318      * <p>Checks if an array of primitive longs is not empty and not {@code null}.
3319      *
3320      * @param array  the array to test
3321      * @return {@code true} if the array is not empty and not {@code null}
3322      * @since 2.5
3323      */
3324     public static boolean isNotEmpty(final long[] array) {
3325         return !isEmpty(array);
3326     }
3327 
3328     /**
3329      * <p>Checks if an array of primitive shorts is not empty and not {@code null}.
3330      *
3331      * @param array  the array to test
3332      * @return {@code true} if the array is not empty and not {@code null}
3333      * @since 2.5
3334      */
3335     public static boolean isNotEmpty(final short[] array) {
3336         return !isEmpty(array);
3337     }
3338 
3339     // ----------------------------------------------------------------------
3340     /**
3341      * <p>Checks if an array of Objects is not empty and not {@code null}.
3342      *
3343      * @param <T> the component type of the array
3344      * @param array  the array to test
3345      * @return {@code true} if the array is not empty and not {@code null}
3346      * @since 2.5
3347      */
3348      public static <T> boolean isNotEmpty(final T[] array) {
3349          return !isEmpty(array);
3350      }
3351 
3352     /**
3353      * <p>Checks whether two arrays are the same length, treating
3354      * {@code null} arrays as length {@code 0}.
3355      *
3356      * @param array1 the first array, may be {@code null}
3357      * @param array2 the second array, may be {@code null}
3358      * @return {@code true} if length of arrays matches, treating
3359      *  {@code null} as an empty array
3360      */
3361     public static boolean isSameLength(final boolean[] array1, final boolean[] array2) {
3362         return getLength(array1) == getLength(array2);
3363     }
3364 
3365     /**
3366      * <p>Checks whether two arrays are the same length, treating
3367      * {@code null} arrays as length {@code 0}.
3368      *
3369      * @param array1 the first array, may be {@code null}
3370      * @param array2 the second array, may be {@code null}
3371      * @return {@code true} if length of arrays matches, treating
3372      *  {@code null} as an empty array
3373      */
3374     public static boolean isSameLength(final byte[] array1, final byte[] array2) {
3375         return getLength(array1) == getLength(array2);
3376     }
3377 
3378     /**
3379      * <p>Checks whether two arrays are the same length, treating
3380      * {@code null} arrays as length {@code 0}.
3381      *
3382      * @param array1 the first array, may be {@code null}
3383      * @param array2 the second array, may be {@code null}
3384      * @return {@code true} if length of arrays matches, treating
3385      *  {@code null} as an empty array
3386      */
3387     public static boolean isSameLength(final char[] array1, final char[] array2) {
3388         return getLength(array1) == getLength(array2);
3389     }
3390 
3391     /**
3392      * <p>Checks whether two arrays are the same length, treating
3393      * {@code null} arrays as length {@code 0}.
3394      *
3395      * @param array1 the first array, may be {@code null}
3396      * @param array2 the second array, may be {@code null}
3397      * @return {@code true} if length of arrays matches, treating
3398      *  {@code null} as an empty array
3399      */
3400     public static boolean isSameLength(final double[] array1, final double[] array2) {
3401         return getLength(array1) == getLength(array2);
3402     }
3403 
3404     /**
3405      * <p>Checks whether two arrays are the same length, treating
3406      * {@code null} arrays as length {@code 0}.
3407      *
3408      * @param array1 the first array, may be {@code null}
3409      * @param array2 the second array, may be {@code null}
3410      * @return {@code true} if length of arrays matches, treating
3411      *  {@code null} as an empty array
3412      */
3413     public static boolean isSameLength(final float[] array1, final float[] array2) {
3414         return getLength(array1) == getLength(array2);
3415     }
3416 
3417     /**
3418      * <p>Checks whether two arrays are the same length, treating
3419      * {@code null} arrays as length {@code 0}.
3420      *
3421      * @param array1 the first array, may be {@code null}
3422      * @param array2 the second array, may be {@code null}
3423      * @return {@code true} if length of arrays matches, treating
3424      *  {@code null} as an empty array
3425      */
3426     public static boolean isSameLength(final int[] array1, final int[] array2) {
3427         return getLength(array1) == getLength(array2);
3428     }
3429 
3430     /**
3431      * <p>Checks whether two arrays are the same length, treating
3432      * {@code null} arrays as length {@code 0}.
3433      *
3434      * @param array1 the first array, may be {@code null}
3435      * @param array2 the second array, may be {@code null}
3436      * @return {@code true} if length of arrays matches, treating
3437      *  {@code null} as an empty array
3438      */
3439     public static boolean isSameLength(final long[] array1, final long[] array2) {
3440         return getLength(array1) == getLength(array2);
3441     }
3442 
3443     /**
3444      * <p>Checks whether two arrays are the same length, treating
3445      * {@code null} arrays as length {@code 0}.
3446      *
3447      * <p>Any multi-dimensional aspects of the arrays are ignored.
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      * @since 3.11
3454      */
3455     public static boolean isSameLength(final Object array1, final Object array2) {
3456         return getLength(array1) == getLength(array2);
3457     }
3458 
3459 
3460     /**
3461      * <p>Checks whether two arrays are the same length, treating
3462      * {@code null} arrays as length {@code 0}.
3463      *
3464      * <p>Any multi-dimensional aspects of the arrays are ignored.
3465      *
3466      * @param array1 the first array, may be {@code null}
3467      * @param array2 the second array, may be {@code null}
3468      * @return {@code true} if length of arrays matches, treating
3469      *  {@code null} as an empty array
3470      */
3471     public static boolean isSameLength(final Object[] array1, final Object[] array2) {
3472         return getLength(array1) == getLength(array2);
3473     }
3474 
3475     /**
3476      * <p>Checks whether two arrays are the same length, treating
3477      * {@code null} arrays as length {@code 0}.
3478      *
3479      * @param array1 the first array, may be {@code null}
3480      * @param array2 the second array, may be {@code null}
3481      * @return {@code true} if length of arrays matches, treating
3482      *  {@code null} as an empty array
3483      */
3484     public static boolean isSameLength(final short[] array1, final short[] array2) {
3485         return getLength(array1) == getLength(array2);
3486     }
3487 
3488     /**
3489      * <p>Checks whether two arrays are the same type taking into account
3490      * multi-dimensional arrays.
3491      *
3492      * @param array1 the first array, must not be {@code null}
3493      * @param array2 the second array, must not be {@code null}
3494      * @return {@code true} if type of arrays matches
3495      * @throws IllegalArgumentException if either array is {@code null}
3496      */
3497     public static boolean isSameType(final Object array1, final Object array2) {
3498         if (array1 == null || array2 == null) {
3499             throw new IllegalArgumentException("The Array must not be null");
3500         }
3501         return array1.getClass().getName().equals(array2.getClass().getName());
3502     }
3503 
3504     /**
3505      * <p>This method checks whether the provided array is sorted according to natural ordering
3506      * ({@code false} before {@code true}).
3507      *
3508      * @param array the array to check
3509      * @return whether the array is sorted according to natural ordering
3510      * @since 3.4
3511      */
3512     public static boolean isSorted(final boolean[] array) {
3513         if (array == null || array.length < 2) {
3514             return true;
3515         }
3516 
3517         boolean previous = array[0];
3518         final int n = array.length;
3519         for (int i = 1; i < n; i++) {
3520             final boolean current = array[i];
3521             if (BooleanUtils.compare(previous, current) > 0) {
3522                 return false;
3523             }
3524 
3525             previous = current;
3526         }
3527         return true;
3528     }
3529 
3530     /**
3531      * <p>This method checks whether the provided array is sorted according to natural ordering.
3532      *
3533      * @param array the array to check
3534      * @return whether the array is sorted according to natural ordering
3535      * @since 3.4
3536      */
3537     public static boolean isSorted(final byte[] array) {
3538         if (array == null || array.length < 2) {
3539             return true;
3540         }
3541 
3542         byte previous = array[0];
3543         final int n = array.length;
3544         for (int i = 1; i < n; i++) {
3545             final byte current = array[i];
3546             if (NumberUtils.compare(previous, current) > 0) {
3547                 return false;
3548             }
3549 
3550             previous = current;
3551         }
3552         return true;
3553     }
3554 
3555     /**
3556      * <p>This method checks whether the provided array is sorted according to natural ordering.
3557      *
3558      * @param array the array to check
3559      * @return whether the array is sorted according to natural ordering
3560      * @since 3.4
3561      */
3562     public static boolean isSorted(final char[] array) {
3563         if (array == null || array.length < 2) {
3564             return true;
3565         }
3566 
3567         char previous = array[0];
3568         final int n = array.length;
3569         for (int i = 1; i < n; i++) {
3570             final char current = array[i];
3571             if (CharUtils.compare(previous, current) > 0) {
3572                 return false;
3573             }
3574 
3575             previous = current;
3576         }
3577         return true;
3578     }
3579 
3580     /**
3581      * <p>This method checks whether the provided array is sorted according to natural ordering.
3582      *
3583      * @param array the array to check
3584      * @return whether the array is sorted according to natural ordering
3585      * @since 3.4
3586      */
3587     public static boolean isSorted(final double[] array) {
3588         if (array == null || array.length < 2) {
3589             return true;
3590         }
3591 
3592         double previous = array[0];
3593         final int n = array.length;
3594         for (int i = 1; i < n; i++) {
3595             final double current = array[i];
3596             if (Double.compare(previous, current) > 0) {
3597                 return false;
3598             }
3599 
3600             previous = current;
3601         }
3602         return true;
3603     }
3604 
3605     /**
3606      * <p>This method checks whether the provided array is sorted according to natural ordering.
3607      *
3608      * @param array the array to check
3609      * @return whether the array is sorted according to natural ordering
3610      * @since 3.4
3611      */
3612     public static boolean isSorted(final float[] array) {
3613         if (array == null || array.length < 2) {
3614             return true;
3615         }
3616 
3617         float previous = array[0];
3618         final int n = array.length;
3619         for (int i = 1; i < n; i++) {
3620             final float current = array[i];
3621             if (Float.compare(previous, current) > 0) {
3622                 return false;
3623             }
3624 
3625             previous = current;
3626         }
3627         return true;
3628     }
3629 
3630     /**
3631      * <p>This method checks whether the provided array is sorted according to natural ordering.
3632      *
3633      * @param array the array to check
3634      * @return whether the array is sorted according to natural ordering
3635      * @since 3.4
3636      */
3637     public static boolean isSorted(final int[] array) {
3638         if (array == null || array.length < 2) {
3639             return true;
3640         }
3641 
3642         int previous = array[0];
3643         final int n = array.length;
3644         for (int i = 1; i < n; i++) {
3645             final int current = array[i];
3646             if (NumberUtils.compare(previous, current) > 0) {
3647                 return false;
3648             }
3649 
3650             previous = current;
3651         }
3652         return true;
3653     }
3654 
3655     /**
3656      * <p>This method checks whether the provided array is sorted according to natural ordering.
3657      *
3658      * @param array the array to check
3659      * @return whether the array is sorted according to natural ordering
3660      * @since 3.4
3661      */
3662     public static boolean isSorted(final long[] array) {
3663         if (array == null || array.length < 2) {
3664             return true;
3665         }
3666 
3667         long previous = array[0];
3668         final int n = array.length;
3669         for (int i = 1; i < n; i++) {
3670             final long current = array[i];
3671             if (NumberUtils.compare(previous, current) > 0) {
3672                 return false;
3673             }
3674 
3675             previous = current;
3676         }
3677         return true;
3678     }
3679 
3680     /**
3681      * <p>This method checks whether the provided array is sorted according to natural ordering.
3682      *
3683      * @param array the array to check
3684      * @return whether the array is sorted according to natural ordering
3685      * @since 3.4
3686      */
3687     public static boolean isSorted(final short[] array) {
3688         if (array == null || array.length < 2) {
3689             return true;
3690         }
3691 
3692         short previous = array[0];
3693         final int n = array.length;
3694         for (int i = 1; i < n; i++) {
3695             final short current = array[i];
3696             if (NumberUtils.compare(previous, current) > 0) {
3697                 return false;
3698             }
3699 
3700             previous = current;
3701         }
3702         return true;
3703     }
3704 
3705     /**
3706      * <p>This method checks whether the provided array is sorted according to the class's
3707      * {@code compareTo} method.
3708      *
3709      * @param array the array to check
3710      * @param <T> the datatype of the array to check, it must implement {@code Comparable}
3711      * @return whether the array is sorted
3712      * @since 3.4
3713      */
3714     public static <T extends Comparable<? super T>> boolean isSorted(final T[] array) {
3715         return isSorted(array, Comparable::compareTo);
3716     }
3717 
3718     /**
3719      * <p>This method checks whether the provided array is sorted according to the provided {@code Comparator}.
3720      *
3721      * @param array the array to check
3722      * @param comparator the {@code Comparator} to compare over
3723      * @param <T> the datatype of the array
3724      * @return whether the array is sorted
3725      * @since 3.4
3726      */
3727     public static <T> boolean isSorted(final T[] array, final Comparator<T> comparator) {
3728         if (comparator == null) {
3729             throw new IllegalArgumentException("Comparator should not be null.");
3730         }
3731 
3732         if (array == null || array.length < 2) {
3733             return true;
3734         }
3735 
3736         T previous = array[0];
3737         final int n = array.length;
3738         for (int i = 1; i < n; i++) {
3739             final T current = array[i];
3740             if (comparator.compare(previous, current) > 0) {
3741                 return false;
3742             }
3743 
3744             previous = current;
3745         }
3746         return true;
3747     }
3748 
3749     /**
3750      * <p>Finds the last index of the given value within the array.
3751      *
3752      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) if
3753      * {@code null} array input.
3754      *
3755      * @param array  the array to traverse backwards looking for the object, may be {@code null}
3756      * @param valueToFind  the object to find
3757      * @return the last index of the value within the array,
3758      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3759      */
3760     public static int lastIndexOf(final boolean[] array, final boolean valueToFind) {
3761         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
3762     }
3763 
3764     /**
3765      * <p>Finds the last index of the given value in the array starting at the given index.
3766      *
3767      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3768      *
3769      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than
3770      * the array length will search from the end of the array.
3771      *
3772      * @param array  the array to traverse for looking for the object, may be {@code null}
3773      * @param valueToFind  the value to find
3774      * @param startIndex  the start index to traverse backwards from
3775      * @return the last index of the value within the array,
3776      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3777      */
3778     public static int lastIndexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
3779         if (isEmpty(array)) {
3780             return INDEX_NOT_FOUND;
3781         }
3782         if (startIndex < 0) {
3783             return INDEX_NOT_FOUND;
3784         } else if (startIndex >= array.length) {
3785             startIndex = array.length - 1;
3786         }
3787         for (int i = startIndex; i >= 0; i--) {
3788             if (valueToFind == array[i]) {
3789                 return i;
3790             }
3791         }
3792         return INDEX_NOT_FOUND;
3793     }
3794 
3795     /**
3796      * <p>Finds the last index of the given value within the array.
3797      *
3798      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3799      *
3800      * @param array  the array to traverse backwards looking for the object, may be {@code null}
3801      * @param valueToFind  the object to find
3802      * @return the last index of the value within the array,
3803      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3804      */
3805     public static int lastIndexOf(final byte[] array, final byte valueToFind) {
3806         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
3807     }
3808 
3809     /**
3810      * <p>Finds the last index of the given value in the array starting at the given index.
3811      *
3812      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3813      *
3814      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
3815      * array length will search from the end of the array.
3816      *
3817      * @param array  the array to traverse for looking for the object, may be {@code null}
3818      * @param valueToFind  the value to find
3819      * @param startIndex  the start index to traverse backwards from
3820      * @return the last index of the value within the array,
3821      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3822      */
3823     public static int lastIndexOf(final byte[] array, final byte valueToFind, int startIndex) {
3824         if (array == null) {
3825             return INDEX_NOT_FOUND;
3826         }
3827         if (startIndex < 0) {
3828             return INDEX_NOT_FOUND;
3829         } else if (startIndex >= array.length) {
3830             startIndex = array.length - 1;
3831         }
3832         for (int i = startIndex; i >= 0; i--) {
3833             if (valueToFind == array[i]) {
3834                 return i;
3835             }
3836         }
3837         return INDEX_NOT_FOUND;
3838     }
3839 
3840     /**
3841      * <p>Finds the last index of the given value within the array.
3842      *
3843      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3844      *
3845      * @param array  the array to traverse backwards looking for the object, may be {@code null}
3846      * @param valueToFind  the object to find
3847      * @return the last index of the value within the array,
3848      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3849      * @since 2.1
3850      */
3851     public static int lastIndexOf(final char[] array, final char valueToFind) {
3852         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
3853     }
3854 
3855     /**
3856      * <p>Finds the last index of the given value in the array starting at the given index.
3857      *
3858      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3859      *
3860      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
3861      * array length will search from the end of the array.
3862      *
3863      * @param array  the array to traverse for looking for the object, may be {@code null}
3864      * @param valueToFind  the value to find
3865      * @param startIndex  the start index to traverse backwards from
3866      * @return the last index of the value within the array,
3867      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3868      * @since 2.1
3869      */
3870     public static int lastIndexOf(final char[] array, final char valueToFind, int startIndex) {
3871         if (array == null) {
3872             return INDEX_NOT_FOUND;
3873         }
3874         if (startIndex < 0) {
3875             return INDEX_NOT_FOUND;
3876         } else if (startIndex >= array.length) {
3877             startIndex = array.length - 1;
3878         }
3879         for (int i = startIndex; i >= 0; i--) {
3880             if (valueToFind == array[i]) {
3881                 return i;
3882             }
3883         }
3884         return INDEX_NOT_FOUND;
3885     }
3886 
3887     /**
3888      * <p>Finds the last index of the given value within the array.
3889      *
3890      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3891      *
3892      * @param array  the array to traverse backwards looking for the object, may be {@code null}
3893      * @param valueToFind  the object to find
3894      * @return the last index of the value within the array,
3895      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3896      */
3897     public static int lastIndexOf(final double[] array, final double valueToFind) {
3898         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
3899     }
3900 
3901     /**
3902      * <p>Finds the last index of the given value within a given tolerance in the array.
3903      * This method will return the index of the last value which falls between the region
3904      * defined by valueToFind - tolerance and valueToFind + tolerance.
3905      *
3906      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3907      *
3908      * @param array  the array to search through for the object, may be {@code null}
3909      * @param valueToFind  the value to find
3910      * @param tolerance tolerance of the search
3911      * @return the index of the value within the array,
3912      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3913      */
3914     public static int lastIndexOf(final double[] array, final double valueToFind, final double tolerance) {
3915         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance);
3916     }
3917 
3918     /**
3919      * <p>Finds the last index of the given value in the array starting at the given index.
3920      *
3921      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3922      *
3923      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
3924      * array length will search from the end of the array.
3925      *
3926      * @param array  the array to traverse for looking for the object, may be {@code null}
3927      * @param valueToFind  the value to find
3928      * @param startIndex  the start index to traverse backwards from
3929      * @return the last index of the value within the array,
3930      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3931      */
3932     public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex) {
3933         if (isEmpty(array)) {
3934             return INDEX_NOT_FOUND;
3935         }
3936         if (startIndex < 0) {
3937             return INDEX_NOT_FOUND;
3938         } else if (startIndex >= array.length) {
3939             startIndex = array.length - 1;
3940         }
3941         for (int i = startIndex; i >= 0; i--) {
3942             if (valueToFind == array[i]) {
3943                 return i;
3944             }
3945         }
3946         return INDEX_NOT_FOUND;
3947     }
3948 
3949     /**
3950      * <p>Finds the last index of the given value in the array starting at the given index.
3951      * This method will return the index of the last value which falls between the region
3952      * defined by valueToFind - tolerance and valueToFind + tolerance.
3953      *
3954      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3955      *
3956      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
3957      * array length will search from the end of the array.
3958      *
3959      * @param array  the array to traverse for looking for the object, may be {@code null}
3960      * @param valueToFind  the value to find
3961      * @param startIndex  the start index to traverse backwards from
3962      * @param tolerance  search for value within plus/minus this amount
3963      * @return the last index of the value within the array,
3964      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3965      */
3966     public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
3967         if (isEmpty(array)) {
3968             return INDEX_NOT_FOUND;
3969         }
3970         if (startIndex < 0) {
3971             return INDEX_NOT_FOUND;
3972         } else if (startIndex >= array.length) {
3973             startIndex = array.length - 1;
3974         }
3975         final double min = valueToFind - tolerance;
3976         final double max = valueToFind + tolerance;
3977         for (int i = startIndex; i >= 0; i--) {
3978             if (array[i] >= min && array[i] <= max) {
3979                 return i;
3980             }
3981         }
3982         return INDEX_NOT_FOUND;
3983     }
3984 
3985     /**
3986      * <p>Finds the last index of the given value within the array.
3987      *
3988      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3989      *
3990      * @param array  the array to traverse backwards looking for the object, may be {@code null}
3991      * @param valueToFind  the object to find
3992      * @return the last index of the value within the array,
3993      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3994      */
3995     public static int lastIndexOf(final float[] array, final float valueToFind) {
3996         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
3997     }
3998 
3999 
4000     /**
4001      * <p>Finds the last index of the given value in the array starting at the given index.
4002      *
4003      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4004      *
4005      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
4006      * array length will search from the end of the array.
4007      *
4008      * @param array  the array to traverse for looking for the object, may be {@code null}
4009      * @param valueToFind  the value to find
4010      * @param startIndex  the start index to traverse backwards from
4011      * @return the last index of the value within the array,
4012      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4013      */
4014     public static int lastIndexOf(final float[] array, final float valueToFind, int startIndex) {
4015         if (isEmpty(array)) {
4016             return INDEX_NOT_FOUND;
4017         }
4018         if (startIndex < 0) {
4019             return INDEX_NOT_FOUND;
4020         } else if (startIndex >= array.length) {
4021             startIndex = array.length - 1;
4022         }
4023         for (int i = startIndex; i >= 0; i--) {
4024             if (valueToFind == array[i]) {
4025                 return i;
4026             }
4027         }
4028         return INDEX_NOT_FOUND;
4029     }
4030 
4031     /**
4032      * <p>Finds the last index of the given value within the array.
4033      *
4034      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4035      *
4036      * @param array  the array to traverse backwards looking for the object, may be {@code null}
4037      * @param valueToFind  the object to find
4038      * @return the last index of the value within the array,
4039      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4040      */
4041     public static int lastIndexOf(final int[] array, final int valueToFind) {
4042         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4043     }
4044 
4045     /**
4046      * <p>Finds the last index of the given value in the array starting at the given index.
4047      *
4048      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4049      *
4050      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
4051      * array length will search from the end of the array.
4052      *
4053      * @param array  the array to traverse for looking for the object, may be {@code null}
4054      * @param valueToFind  the value to find
4055      * @param startIndex  the start index to traverse backwards from
4056      * @return the last index of the value within the array,
4057      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4058      */
4059     public static int lastIndexOf(final int[] array, final int valueToFind, int startIndex) {
4060         if (array == null) {
4061             return INDEX_NOT_FOUND;
4062         }
4063         if (startIndex < 0) {
4064             return INDEX_NOT_FOUND;
4065         } else if (startIndex >= array.length) {
4066             startIndex = array.length - 1;
4067         }
4068         for (int i = startIndex; i >= 0; i--) {
4069             if (valueToFind == array[i]) {
4070                 return i;
4071             }
4072         }
4073         return INDEX_NOT_FOUND;
4074     }
4075 
4076     /**
4077      * <p>Finds the last index of the given value within the array.
4078      *
4079      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4080      *
4081      * @param array  the array to traverse backwards looking for the object, may be {@code null}
4082      * @param valueToFind  the object to find
4083      * @return the last index of the value within the array,
4084      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4085      */
4086     public static int lastIndexOf(final long[] array, final long valueToFind) {
4087         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4088     }
4089 
4090     /**
4091      * <p>Finds the last index of the given value in the array starting at the given index.
4092      *
4093      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4094      *
4095      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
4096      * array length will search from the end of the array.
4097      *
4098      * @param array  the array to traverse for looking for the object, may be {@code null}
4099      * @param valueToFind  the value to find
4100      * @param startIndex  the start index to traverse backwards from
4101      * @return the last index of the value within the array,
4102      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4103      */
4104     public static int lastIndexOf(final long[] array, final long valueToFind, int startIndex) {
4105         if (array == null) {
4106             return INDEX_NOT_FOUND;
4107         }
4108         if (startIndex < 0) {
4109             return INDEX_NOT_FOUND;
4110         } else if (startIndex >= array.length) {
4111             startIndex = array.length - 1;
4112         }
4113         for (int i = startIndex; i >= 0; i--) {
4114             if (valueToFind == array[i]) {
4115                 return i;
4116             }
4117         }
4118         return INDEX_NOT_FOUND;
4119     }
4120 
4121     /**
4122      * <p>Finds the last index of the given object within the array.
4123      *
4124      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4125      *
4126      * @param array  the array to traverse backwards looking for the object, may be {@code null}
4127      * @param objectToFind  the object to find, may be {@code null}
4128      * @return the last index of the object within the array,
4129      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4130      */
4131     public static int lastIndexOf(final Object[] array, final Object objectToFind) {
4132         return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
4133     }
4134 
4135     /**
4136      * <p>Finds the last index of the given object in the array starting at the given index.
4137      *
4138      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4139      *
4140      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than
4141      * the array length will search from the end of the array.
4142      *
4143      * @param array  the array to traverse for looking for the object, may be {@code null}
4144      * @param objectToFind  the object to find, may be {@code null}
4145      * @param startIndex  the start index to traverse backwards from
4146      * @return the last index of the object within the array,
4147      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4148      */
4149     public static int lastIndexOf(final Object[] array, final Object objectToFind, int startIndex) {
4150         if (array == null) {
4151             return INDEX_NOT_FOUND;
4152         }
4153         if (startIndex < 0) {
4154             return INDEX_NOT_FOUND;
4155         } else if (startIndex >= array.length) {
4156             startIndex = array.length - 1;
4157         }
4158         if (objectToFind == null) {
4159             for (int i = startIndex; i >= 0; i--) {
4160                 if (array[i] == null) {
4161                     return i;
4162                 }
4163             }
4164         } else if (array.getClass().getComponentType().isInstance(objectToFind)) {
4165             for (int i = startIndex; i >= 0; i--) {
4166                 if (objectToFind.equals(array[i])) {
4167                     return i;
4168                 }
4169             }
4170         }
4171         return INDEX_NOT_FOUND;
4172     }
4173 
4174     /**
4175      * <p>Finds the last index of the given value within the array.
4176      *
4177      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4178      *
4179      * @param array  the array to traverse backwards looking for the object, may be {@code null}
4180      * @param valueToFind  the object to find
4181      * @return the last index of the value within the array,
4182      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4183      */
4184     public static int lastIndexOf(final short[] array, final short valueToFind) {
4185         return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4186     }
4187 
4188     /**
4189      * <p>Finds the last index of the given value in the array starting at the given index.
4190      *
4191      * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4192      *
4193      * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
4194      * array length will search from the end of the array.
4195      *
4196      * @param array  the array to traverse for looking for the object, may be {@code null}
4197      * @param valueToFind  the value to find
4198      * @param startIndex  the start index to traverse backwards from
4199      * @return the last index of the value within the array,
4200      *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4201      */
4202     public static int lastIndexOf(final short[] array, final short valueToFind, int startIndex) {
4203         if (array == null) {
4204             return INDEX_NOT_FOUND;
4205         }
4206         if (startIndex < 0) {
4207             return INDEX_NOT_FOUND;
4208         } else if (startIndex >= array.length) {
4209             startIndex = array.length - 1;
4210         }
4211         for (int i = startIndex; i >= 0; i--) {
4212             if (valueToFind == array[i]) {
4213                 return i;
4214             }
4215         }
4216         return INDEX_NOT_FOUND;
4217     }
4218 
4219     /**
4220      * <p>Defensive programming technique to change a {@code null}
4221      * reference to an empty one.
4222      *
4223      * <p>This method returns an empty array for a {@code null} input array.
4224      *
4225      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4226      * the empty {@code public static} references in this class.
4227      *
4228      * @param array  the array to check for {@code null} or empty
4229      * @return the same array, {@code public static} empty array if {@code null} or empty input
4230      * @since 2.5
4231      */
4232     public static boolean[] nullToEmpty(final boolean[] array) {
4233         if (isEmpty(array)) {
4234             return EMPTY_BOOLEAN_ARRAY;
4235         }
4236         return array;
4237     }
4238 
4239     /**
4240      * <p>Defensive programming technique to change a {@code null}
4241      * reference to an empty one.
4242      *
4243      * <p>This method returns an empty array for a {@code null} input array.
4244      *
4245      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4246      * the empty {@code public static} references in this class.
4247      *
4248      * @param array  the array to check for {@code null} or empty
4249      * @return the same array, {@code public static} empty array if {@code null} or empty input
4250      * @since 2.5
4251      */
4252     public static Boolean[] nullToEmpty(final Boolean[] array) {
4253         if (isEmpty(array)) {
4254             return EMPTY_BOOLEAN_OBJECT_ARRAY;
4255         }
4256         return array;
4257     }
4258 
4259     /**
4260      * <p>Defensive programming technique to change a {@code null}
4261      * reference to an empty one.
4262      *
4263      * <p>This method returns an empty array for a {@code null} input array.
4264      *
4265      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4266      * the empty {@code public static} references in this class.
4267      *
4268      * @param array  the array to check for {@code null} or empty
4269      * @return the same array, {@code public static} empty array if {@code null} or empty input
4270      * @since 2.5
4271      */
4272     public static byte[] nullToEmpty(final byte[] array) {
4273         if (isEmpty(array)) {
4274             return EMPTY_BYTE_ARRAY;
4275         }
4276         return array;
4277     }
4278 
4279     /**
4280      * <p>Defensive programming technique to change a {@code null}
4281      * reference to an empty one.
4282      *
4283      * <p>This method returns an empty array for a {@code null} input array.
4284      *
4285      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4286      * the empty {@code public static} references in this class.
4287      *
4288      * @param array  the array to check for {@code null} or empty
4289      * @return the same array, {@code public static} empty array if {@code null} or empty input
4290      * @since 2.5
4291      */
4292     public static Byte[] nullToEmpty(final Byte[] array) {
4293         if (isEmpty(array)) {
4294             return EMPTY_BYTE_OBJECT_ARRAY;
4295         }
4296         return array;
4297     }
4298 
4299     /**
4300      * <p>Defensive programming technique to change a {@code null}
4301      * reference to an empty one.
4302      *
4303      * <p>This method returns an empty array for a {@code null} input array.
4304      *
4305      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4306      * the empty {@code public static} references in this class.
4307      *
4308      * @param array  the array to check for {@code null} or empty
4309      * @return the same array, {@code public static} empty array if {@code null} or empty input
4310      * @since 2.5
4311      */
4312     public static char[] nullToEmpty(final char[] array) {
4313         if (isEmpty(array)) {
4314             return EMPTY_CHAR_ARRAY;
4315         }
4316         return array;
4317     }
4318 
4319     /**
4320      * <p>Defensive programming technique to change a {@code null}
4321      * reference to an empty one.
4322      *
4323      * <p>This method returns an empty array for a {@code null} input array.
4324      *
4325      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4326      * the empty {@code public static} references in this class.
4327      *
4328      * @param array  the array to check for {@code null} or empty
4329      * @return the same array, {@code public static} empty array if {@code null} or empty input
4330      * @since 2.5
4331      */
4332     public static Character[] nullToEmpty(final Character[] array) {
4333         if (isEmpty(array)) {
4334             return EMPTY_CHARACTER_OBJECT_ARRAY;
4335         }
4336         return array;
4337     }
4338 
4339     /**
4340      * <p>Defensive programming technique to change a {@code null}
4341      * reference to an empty one.
4342      *
4343      * <p>This method returns an empty array for a {@code null} input array.
4344      *
4345      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4346      * the empty {@code public static} references in this class.
4347      *
4348      * @param array  the array to check for {@code null} or empty
4349      * @return the same array, {@code public static} empty array if {@code null} or empty input
4350      * @since 3.2
4351      */
4352     public static Class<?>[] nullToEmpty(final Class<?>[] array) {
4353         if (isEmpty(array)) {
4354             return EMPTY_CLASS_ARRAY;
4355         }
4356         return array;
4357     }
4358 
4359     /**
4360      * <p>Defensive programming technique to change a {@code null}
4361      * reference to an empty one.
4362      *
4363      * <p>This method returns an empty array for a {@code null} input array.
4364      *
4365      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4366      * the empty {@code public static} references in this class.
4367      *
4368      * @param array  the array to check for {@code null} or empty
4369      * @return the same array, {@code public static} empty array if {@code null} or empty input
4370      * @since 2.5
4371      */
4372     public static double[] nullToEmpty(final double[] array) {
4373         if (isEmpty(array)) {
4374             return EMPTY_DOUBLE_ARRAY;
4375         }
4376         return array;
4377     }
4378 
4379     /**
4380      * <p>Defensive programming technique to change a {@code null}
4381      * reference to an empty one.
4382      *
4383      * <p>This method returns an empty array for a {@code null} input array.
4384      *
4385      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4386      * the empty {@code public static} references in this class.
4387      *
4388      * @param array  the array to check for {@code null} or empty
4389      * @return the same array, {@code public static} empty array if {@code null} or empty input
4390      * @since 2.5
4391      */
4392     public static Double[] nullToEmpty(final Double[] array) {
4393         if (isEmpty(array)) {
4394             return EMPTY_DOUBLE_OBJECT_ARRAY;
4395         }
4396         return array;
4397     }
4398 
4399     /**
4400      * <p>Defensive programming technique to change a {@code null}
4401      * reference to an empty one.
4402      *
4403      * <p>This method returns an empty array for a {@code null} input array.
4404      *
4405      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4406      * the empty {@code public static} references in this class.
4407      *
4408      * @param array  the array to check for {@code null} or empty
4409      * @return the same array, {@code public static} empty array if {@code null} or empty input
4410      * @since 2.5
4411      */
4412     public static float[] nullToEmpty(final float[] array) {
4413         if (isEmpty(array)) {
4414             return EMPTY_FLOAT_ARRAY;
4415         }
4416         return array;
4417     }
4418 
4419     /**
4420      * <p>Defensive programming technique to change a {@code null}
4421      * reference to an empty one.
4422      *
4423      * <p>This method returns an empty array for a {@code null} input array.
4424      *
4425      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4426      * the empty {@code public static} references in this class.
4427      *
4428      * @param array  the array to check for {@code null} or empty
4429      * @return the same array, {@code public static} empty array if {@code null} or empty input
4430      * @since 2.5
4431      */
4432     public static Float[] nullToEmpty(final Float[] array) {
4433         if (isEmpty(array)) {
4434             return EMPTY_FLOAT_OBJECT_ARRAY;
4435         }
4436         return array;
4437     }
4438 
4439     /**
4440      * <p>Defensive programming technique to change a {@code null}
4441      * reference to an empty one.
4442      *
4443      * <p>This method returns an empty array for a {@code null} input array.
4444      *
4445      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4446      * the empty {@code public static} references in this class.
4447      *
4448      * @param array  the array to check for {@code null} or empty
4449      * @return the same array, {@code public static} empty array if {@code null} or empty input
4450      * @since 2.5
4451      */
4452     public static int[] nullToEmpty(final int[] array) {
4453         if (isEmpty(array)) {
4454             return EMPTY_INT_ARRAY;
4455         }
4456         return array;
4457     }
4458 
4459     /**
4460      * <p>Defensive programming technique to change a {@code null}
4461      * reference to an empty one.
4462      *
4463      * <p>This method returns an empty array for a {@code null} input array.
4464      *
4465      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4466      * the empty {@code public static} references in this class.
4467      *
4468      * @param array  the array to check for {@code null} or empty
4469      * @return the same array, {@code public static} empty array if {@code null} or empty input
4470      * @since 2.5
4471      */
4472     public static Integer[] nullToEmpty(final Integer[] array) {
4473         if (isEmpty(array)) {
4474             return EMPTY_INTEGER_OBJECT_ARRAY;
4475         }
4476         return array;
4477     }
4478 
4479     // Primitive/Object array converters
4480     // ----------------------------------------------------------------------
4481 
4482     /**
4483      * <p>Defensive programming technique to change a {@code null}
4484      * reference to an empty one.
4485      *
4486      * <p>This method returns an empty array for a {@code null} input array.
4487      *
4488      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4489      * the empty {@code public static} references in this class.
4490      *
4491      * @param array  the array to check for {@code null} or empty
4492      * @return the same array, {@code public static} empty array if {@code null} or empty input
4493      * @since 2.5
4494      */
4495     public static long[] nullToEmpty(final long[] array) {
4496         if (isEmpty(array)) {
4497             return EMPTY_LONG_ARRAY;
4498         }
4499         return array;
4500     }
4501 
4502     /**
4503      * <p>Defensive programming technique to change a {@code null}
4504      * reference to an empty one.
4505      *
4506      * <p>This method returns an empty array for a {@code null} input array.
4507      *
4508      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4509      * the empty {@code public static} references in this class.
4510      *
4511      * @param array  the array to check for {@code null} or empty
4512      * @return the same array, {@code public static} empty array if {@code null} or empty input
4513      * @since 2.5
4514      */
4515     public static Long[] nullToEmpty(final Long[] array) {
4516         if (isEmpty(array)) {
4517             return EMPTY_LONG_OBJECT_ARRAY;
4518         }
4519         return array;
4520     }
4521 
4522     /**
4523      * <p>Defensive programming technique to change a {@code null}
4524      * reference to an empty one.
4525      *
4526      * <p>This method returns an empty array for a {@code null} input array.
4527      *
4528      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4529      * the empty {@code public static} references in this class.
4530      *
4531      * @param array  the array to check for {@code null} or empty
4532      * @return the same array, {@code public static} empty array if {@code null} or empty input
4533      * @since 2.5
4534      */
4535     public static Object[] nullToEmpty(final Object[] array) {
4536         if (isEmpty(array)) {
4537             return EMPTY_OBJECT_ARRAY;
4538         }
4539         return array;
4540     }
4541 
4542     /**
4543      * <p>Defensive programming technique to change a {@code null}
4544      * reference to an empty one.
4545      *
4546      * <p>This method returns an empty array for a {@code null} input array.
4547      *
4548      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4549      * the empty {@code public static} references in this class.
4550      *
4551      * @param array  the array to check for {@code null} or empty
4552      * @return the same array, {@code public static} empty array if {@code null} or empty input
4553      * @since 2.5
4554      */
4555     public static short[] nullToEmpty(final short[] array) {
4556         if (isEmpty(array)) {
4557             return EMPTY_SHORT_ARRAY;
4558         }
4559         return array;
4560     }
4561 
4562     /**
4563      * <p>Defensive programming technique to change a {@code null}
4564      * reference to an empty one.
4565      *
4566      * <p>This method returns an empty array for a {@code null} input array.
4567      *
4568      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4569      * the empty {@code public static} references in this class.
4570      *
4571      * @param array  the array to check for {@code null} or empty
4572      * @return the same array, {@code public static} empty array if {@code null} or empty input
4573      * @since 2.5
4574      */
4575     public static Short[] nullToEmpty(final Short[] array) {
4576         if (isEmpty(array)) {
4577             return EMPTY_SHORT_OBJECT_ARRAY;
4578         }
4579         return array;
4580     }
4581 
4582     /**
4583      * <p>Defensive programming technique to change a {@code null}
4584      * reference to an empty one.
4585      *
4586      * <p>This method returns an empty array for a {@code null} input array.
4587      *
4588      * <p>As a memory optimizing technique an empty array passed in will be overridden with
4589      * the empty {@code public static} references in this class.
4590      *
4591      * @param array  the array to check for {@code null} or empty
4592      * @return the same array, {@code public static} empty array if {@code null} or empty input
4593      * @since 2.5
4594      */
4595     public static String[] nullToEmpty(final String[] array) {
4596         if (isEmpty(array)) {
4597             return EMPTY_STRING_ARRAY;
4598         }
4599         return array;
4600     }
4601 
4602     // nullToEmpty
4603     //-----------------------------------------------------------------------
4604     /**
4605      * <p>Defensive programming technique to change a {@code null}
4606      * reference to an empty one.
4607      *
4608      * <p>This method returns an empty array for a {@code null} input array.
4609      *
4610      * @param array  the array to check for {@code null} or empty
4611      * @param type   the class representation of the desired array
4612      * @param <T>  the class type
4613      * @return the same array, {@code public static} empty array if {@code null}
4614      * @throws IllegalArgumentException if the type argument is null
4615      * @since 3.5
4616      */
4617     public static <T> T[] nullToEmpty(final T[] array, final Class<T[]> type) {
4618         if (type == null) {
4619             throw new IllegalArgumentException("The type must not be null");
4620         }
4621 
4622         if (array == null) {
4623             return type.cast(Array.newInstance(type.getComponentType(), 0));
4624         }
4625         return array;
4626     }
4627 
4628     /**
4629      * <p>Removes the element at the specified position from the specified array.
4630      * All subsequent elements are shifted to the left (subtracts one from
4631      * their indices).
4632      *
4633      * <p>This method returns a new array with the same elements of the input
4634      * array except the element on the specified position. The component
4635      * type of the returned array is always the same as that of the input
4636      * array.
4637      *
4638      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4639      * will be thrown, because in that case no valid index can be specified.
4640      *
4641      * <pre>
4642      * ArrayUtils.remove([true], 0)              = []
4643      * ArrayUtils.remove([true, false], 0)       = [false]
4644      * ArrayUtils.remove([true, false], 1)       = [true]
4645      * ArrayUtils.remove([true, true, false], 1) = [true, false]
4646      * </pre>
4647      *
4648      * @param array  the array to remove the element from, may not be {@code null}
4649      * @param index  the position of the element to be removed
4650      * @return A new array containing the existing elements except the element
4651      *         at the specified position.
4652      * @throws IndexOutOfBoundsException if the index is out of range
4653      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4654      * @since 2.1
4655      */
4656     public static boolean[] remove(final boolean[] array, final int index) {
4657         return (boolean[]) remove((Object) array, index);
4658     }
4659 
4660     /**
4661      * <p>Removes the element at the specified position from the specified array.
4662      * All subsequent elements are shifted to the left (subtracts one from
4663      * their indices).
4664      *
4665      * <p>This method returns a new array with the same elements of the input
4666      * array except the element on the specified position. The component
4667      * type of the returned array is always the same as that of the input
4668      * array.
4669      *
4670      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4671      * will be thrown, because in that case no valid index can be specified.
4672      *
4673      * <pre>
4674      * ArrayUtils.remove([1], 0)          = []
4675      * ArrayUtils.remove([1, 0], 0)       = [0]
4676      * ArrayUtils.remove([1, 0], 1)       = [1]
4677      * ArrayUtils.remove([1, 0, 1], 1)    = [1, 1]
4678      * </pre>
4679      *
4680      * @param array  the array to remove the element from, may not be {@code null}
4681      * @param index  the position of the element to be removed
4682      * @return A new array containing the existing elements except the element
4683      *         at the specified position.
4684      * @throws IndexOutOfBoundsException if the index is out of range
4685      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4686      * @since 2.1
4687      */
4688     public static byte[] remove(final byte[] array, final int index) {
4689         return (byte[]) remove((Object) array, index);
4690     }
4691 
4692     /**
4693      * <p>Removes the element at the specified position from the specified array.
4694      * All subsequent elements are shifted to the left (subtracts one from
4695      * their indices).
4696      *
4697      * <p>This method returns a new array with the same elements of the input
4698      * array except the element on the specified position. The component
4699      * type of the returned array is always the same as that of the input
4700      * array.
4701      *
4702      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4703      * will be thrown, because in that case no valid index can be specified.
4704      *
4705      * <pre>
4706      * ArrayUtils.remove(['a'], 0)           = []
4707      * ArrayUtils.remove(['a', 'b'], 0)      = ['b']
4708      * ArrayUtils.remove(['a', 'b'], 1)      = ['a']
4709      * ArrayUtils.remove(['a', 'b', 'c'], 1) = ['a', 'c']
4710      * </pre>
4711      *
4712      * @param array  the array to remove the element from, may not be {@code null}
4713      * @param index  the position of the element to be removed
4714      * @return A new array containing the existing elements except the element
4715      *         at the specified position.
4716      * @throws IndexOutOfBoundsException if the index is out of range
4717      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4718      * @since 2.1
4719      */
4720     public static char[] remove(final char[] array, final int index) {
4721         return (char[]) remove((Object) array, index);
4722     }
4723 
4724     /**
4725      * <p>Removes the element at the specified position from the specified array.
4726      * All subsequent elements are shifted to the left (subtracts one from
4727      * their indices).
4728      *
4729      * <p>This method returns a new array with the same elements of the input
4730      * array except the element on the specified position. The component
4731      * type of the returned array is always the same as that of the input
4732      * array.
4733      *
4734      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4735      * will be thrown, because in that case no valid index can be specified.
4736      *
4737      * <pre>
4738      * ArrayUtils.remove([1.1], 0)           = []
4739      * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
4740      * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
4741      * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
4742      * </pre>
4743      *
4744      * @param array  the array to remove the element from, may not be {@code null}
4745      * @param index  the position of the element to be removed
4746      * @return A new array containing the existing elements except the element
4747      *         at the specified position.
4748      * @throws IndexOutOfBoundsException if the index is out of range
4749      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4750      * @since 2.1
4751      */
4752     public static double[] remove(final double[] array, final int index) {
4753         return (double[]) remove((Object) array, index);
4754     }
4755 
4756     /**
4757      * <p>Removes the element at the specified position from the specified array.
4758      * All subsequent elements are shifted to the left (subtracts one from
4759      * their indices).
4760      *
4761      * <p>This method returns a new array with the same elements of the input
4762      * array except the element on the specified position. The component
4763      * type of the returned array is always the same as that of the input
4764      * array.
4765      *
4766      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4767      * will be thrown, because in that case no valid index can be specified.
4768      *
4769      * <pre>
4770      * ArrayUtils.remove([1.1], 0)           = []
4771      * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
4772      * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
4773      * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
4774      * </pre>
4775      *
4776      * @param array  the array to remove the element from, may not be {@code null}
4777      * @param index  the position of the element to be removed
4778      * @return A new array containing the existing elements except the element
4779      *         at the specified position.
4780      * @throws IndexOutOfBoundsException if the index is out of range
4781      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4782      * @since 2.1
4783      */
4784     public static float[] remove(final float[] array, final int index) {
4785         return (float[]) remove((Object) array, index);
4786     }
4787 
4788     /**
4789      * <p>Removes the element at the specified position from the specified array.
4790      * All subsequent elements are shifted to the left (subtracts one from
4791      * their indices).
4792      *
4793      * <p>This method returns a new array with the same elements of the input
4794      * array except the element on the specified position. The component
4795      * type of the returned array is always the same as that of the input
4796      * array.
4797      *
4798      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4799      * will be thrown, because in that case no valid index can be specified.
4800      *
4801      * <pre>
4802      * ArrayUtils.remove([1], 0)         = []
4803      * ArrayUtils.remove([2, 6], 0)      = [6]
4804      * ArrayUtils.remove([2, 6], 1)      = [2]
4805      * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
4806      * </pre>
4807      *
4808      * @param array  the array to remove the element from, may not be {@code null}
4809      * @param index  the position of the element to be removed
4810      * @return A new array containing the existing elements except the element
4811      *         at the specified position.
4812      * @throws IndexOutOfBoundsException if the index is out of range
4813      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4814      * @since 2.1
4815      */
4816     public static int[] remove(final int[] array, final int index) {
4817         return (int[]) remove((Object) array, index);
4818     }
4819 
4820     /**
4821      * <p>Removes the element at the specified position from the specified array.
4822      * All subsequent elements are shifted to the left (subtracts one from
4823      * their indices).
4824      *
4825      * <p>This method returns a new array with the same elements of the input
4826      * array except the element on the specified position. The component
4827      * type of the returned array is always the same as that of the input
4828      * array.
4829      *
4830      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4831      * will be thrown, because in that case no valid index can be specified.
4832      *
4833      * <pre>
4834      * ArrayUtils.remove([1], 0)         = []
4835      * ArrayUtils.remove([2, 6], 0)      = [6]
4836      * ArrayUtils.remove([2, 6], 1)      = [2]
4837      * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
4838      * </pre>
4839      *
4840      * @param array  the array to remove the element from, may not be {@code null}
4841      * @param index  the position of the element to be removed
4842      * @return A new array containing the existing elements except the element
4843      *         at the specified position.
4844      * @throws IndexOutOfBoundsException if the index is out of range
4845      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4846      * @since 2.1
4847      */
4848     public static long[] remove(final long[] array, final int index) {
4849         return (long[]) remove((Object) array, index);
4850     }
4851 
4852     /**
4853      * <p>Removes the element at the specified position from the specified array.
4854      * All subsequent elements are shifted to the left (subtracts one from
4855      * their indices).
4856      *
4857      * <p>This method returns a new array with the same elements of the input
4858      * array except the element on the specified position. The component
4859      * type of the returned array is always the same as that of the input
4860      * array.
4861      *
4862      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4863      * will be thrown, because in that case no valid index can be specified.
4864      *
4865      * @param array  the array to remove the element from, may not be {@code null}
4866      * @param index  the position of the element to be removed
4867      * @return A new array containing the existing elements except the element
4868      *         at the specified position.
4869      * @throws IndexOutOfBoundsException if the index is out of range
4870      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4871      * @since 2.1
4872      */
4873     private static Object remove(final Object array, final int index) {
4874         final int length = getLength(array);
4875         if (index < 0 || index >= length) {
4876             throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
4877         }
4878 
4879         final Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
4880         System.arraycopy(array, 0, result, 0, index);
4881         if (index < length - 1) {
4882             System.arraycopy(array, index + 1, result, index, length - index - 1);
4883         }
4884 
4885         return result;
4886     }
4887 
4888     /**
4889      * <p>Removes the element at the specified position from the specified array.
4890      * All subsequent elements are shifted to the left (subtracts one from
4891      * their indices).
4892      *
4893      * <p>This method returns a new array with the same elements of the input
4894      * array except the element on the specified position. The component
4895      * type of the returned array is always the same as that of the input
4896      * array.
4897      *
4898      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4899      * will be thrown, because in that case no valid index can be specified.
4900      *
4901      * <pre>
4902      * ArrayUtils.remove([1], 0)         = []
4903      * ArrayUtils.remove([2, 6], 0)      = [6]
4904      * ArrayUtils.remove([2, 6], 1)      = [2]
4905      * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
4906      * </pre>
4907      *
4908      * @param array  the array to remove the element from, may not be {@code null}
4909      * @param index  the position of the element to be removed
4910      * @return A new array containing the existing elements except the element
4911      *         at the specified position.
4912      * @throws IndexOutOfBoundsException if the index is out of range
4913      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4914      * @since 2.1
4915      */
4916     public static short[] remove(final short[] array, final int index) {
4917         return (short[]) remove((Object) array, index);
4918     }
4919 
4920     /**
4921      * <p>Removes the element at the specified position from the specified array.
4922      * All subsequent elements are shifted to the left (subtracts one from
4923      * their indices).
4924      *
4925      * <p>This method returns a new array with the same elements of the input
4926      * array except the element on the specified position. The component
4927      * type of the returned array is always the same as that of the input
4928      * array.
4929      *
4930      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4931      * will be thrown, because in that case no valid index can be specified.
4932      *
4933      * <pre>
4934      * ArrayUtils.remove(["a"], 0)           = []
4935      * ArrayUtils.remove(["a", "b"], 0)      = ["b"]
4936      * ArrayUtils.remove(["a", "b"], 1)      = ["a"]
4937      * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"]
4938      * </pre>
4939      *
4940      * @param <T> the component type of the array
4941      * @param array  the array to remove the element from, may not be {@code null}
4942      * @param index  the position of the element to be removed
4943      * @return A new array containing the existing elements except the element
4944      *         at the specified position.
4945      * @throws IndexOutOfBoundsException if the index is out of range
4946      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4947      * @since 2.1
4948      */
4949     @SuppressWarnings("unchecked") // remove() always creates an array of the same type as its input
4950     public static <T> T[] remove(final T[] array, final int index) {
4951         return (T[]) remove((Object) array, index);
4952     }
4953 
4954     /**
4955      * <p>Removes the elements at the specified positions from the specified array.
4956      * All remaining elements are shifted to the left.
4957      *
4958      * <p>This method returns a new array with the same elements of the input
4959      * array except those at the specified positions. The component
4960      * type of the returned array is always the same as that of the input
4961      * array.
4962      *
4963      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4964      * will be thrown, because in that case no valid index can be specified.
4965      *
4966      * <pre>
4967      * ArrayUtils.removeAll([true, false, true], 0, 2) = [false]
4968      * ArrayUtils.removeAll([true, false, true], 1, 2) = [true]
4969      * </pre>
4970      *
4971      * @param array   the array to remove the element from, may not be {@code null}
4972      * @param indices the positions of the elements to be removed
4973      * @return A new array containing the existing elements except those
4974      *         at the specified positions.
4975      * @throws IndexOutOfBoundsException if any index is out of range
4976      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
4977      * @since 3.0.1
4978      */
4979     public static boolean[] removeAll(final boolean[] array, final int... indices) {
4980         return (boolean[]) removeAll((Object) array, indices);
4981     }
4982 
4983     /**
4984      * <p>Removes the elements at the specified positions from the specified array.
4985      * All remaining elements are shifted to the left.
4986      *
4987      * <p>This method returns a new array with the same elements of the input
4988      * array except those at the specified positions. The component
4989      * type of the returned array is always the same as that of the input
4990      * array.
4991      *
4992      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4993      * will be thrown, because in that case no valid index can be specified.
4994      *
4995      * <pre>
4996      * ArrayUtils.removeAll([1], 0)             = []
4997      * ArrayUtils.removeAll([2, 6], 0)          = [6]
4998      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
4999      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5000      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5001      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5002      * </pre>
5003      *
5004      * @param array   the array to remove the element from, may not be {@code null}
5005      * @param indices the positions of the elements to be removed
5006      * @return A new array containing the existing elements except those
5007      *         at the specified positions.
5008      * @throws IndexOutOfBoundsException if any index is out of range
5009      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5010      * @since 3.0.1
5011      */
5012     public static byte[] removeAll(final byte[] array, final int... indices) {
5013         return (byte[]) removeAll((Object) array, indices);
5014     }
5015 
5016     /**
5017      * <p>Removes the elements at the specified positions from the specified array.
5018      * All remaining elements are shifted to the left.
5019      *
5020      * <p>This method returns a new array with the same elements of the input
5021      * array except those at the specified positions. The component
5022      * type of the returned array is always the same as that of the input
5023      * array.
5024      *
5025      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5026      * will be thrown, because in that case no valid index can be specified.
5027      *
5028      * <pre>
5029      * ArrayUtils.removeAll([1], 0)             = []
5030      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5031      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5032      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5033      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5034      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5035      * </pre>
5036      *
5037      * @param array   the array to remove the element from, may not be {@code null}
5038      * @param indices the positions of the elements to be removed
5039      * @return A new array containing the existing elements except those
5040      *         at the specified positions.
5041      * @throws IndexOutOfBoundsException if any index is out of range
5042      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5043      * @since 3.0.1
5044      */
5045     public static char[] removeAll(final char[] array, final int... indices) {
5046         return (char[]) removeAll((Object) array, indices);
5047     }
5048 
5049     /**
5050      * <p>Removes the elements at the specified positions from the specified array.
5051      * All remaining elements are shifted to the left.
5052      *
5053      * <p>This method returns a new array with the same elements of the input
5054      * array except those at the specified positions. The component
5055      * type of the returned array is always the same as that of the input
5056      * array.
5057      *
5058      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5059      * will be thrown, because in that case no valid index can be specified.
5060      *
5061      * <pre>
5062      * ArrayUtils.removeAll([1], 0)             = []
5063      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5064      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5065      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5066      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5067      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5068      * </pre>
5069      *
5070      * @param array   the array to remove the element from, may not be {@code null}
5071      * @param indices the positions of the elements to be removed
5072      * @return A new array containing the existing elements except those
5073      *         at the specified positions.
5074      * @throws IndexOutOfBoundsException if any index is out of range
5075      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5076      * @since 3.0.1
5077      */
5078     public static double[] removeAll(final double[] array, final int... indices) {
5079         return (double[]) removeAll((Object) array, indices);
5080     }
5081 
5082     /**
5083      * <p>Removes the elements at the specified positions from the specified array.
5084      * All remaining elements are shifted to the left.
5085      *
5086      * <p>This method returns a new array with the same elements of the input
5087      * array except those at the specified positions. The component
5088      * type of the returned array is always the same as that of the input
5089      * array.
5090      *
5091      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5092      * will be thrown, because in that case no valid index can be specified.
5093      *
5094      * <pre>
5095      * ArrayUtils.removeAll([1], 0)             = []
5096      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5097      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5098      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5099      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5100      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5101      * </pre>
5102      *
5103      * @param array   the array to remove the element from, may not be {@code null}
5104      * @param indices the positions of the elements to be removed
5105      * @return A new array containing the existing elements except those
5106      *         at the specified positions.
5107      * @throws IndexOutOfBoundsException if any index is out of range
5108      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5109      * @since 3.0.1
5110      */
5111     public static float[] removeAll(final float[] array, final int... indices) {
5112         return (float[]) removeAll((Object) array, indices);
5113     }
5114 
5115     /**
5116      * <p>Removes the elements at the specified positions from the specified array.
5117      * All remaining elements are shifted to the left.
5118      *
5119      * <p>This method returns a new array with the same elements of the input
5120      * array except those at the specified positions. The component
5121      * type of the returned array is always the same as that of the input
5122      * array.
5123      *
5124      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5125      * will be thrown, because in that case no valid index can be specified.
5126      *
5127      * <pre>
5128      * ArrayUtils.removeAll([1], 0)             = []
5129      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5130      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5131      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5132      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5133      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5134      * </pre>
5135      *
5136      * @param array   the array to remove the element from, may not be {@code null}
5137      * @param indices the positions of the elements to be removed
5138      * @return A new array containing the existing elements except those
5139      *         at the specified positions.
5140      * @throws IndexOutOfBoundsException if any index is out of range
5141      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5142      * @since 3.0.1
5143      */
5144     public static int[] removeAll(final int[] array, final int... indices) {
5145         return (int[]) removeAll((Object) array, indices);
5146     }
5147 
5148     /**
5149      * <p>Removes the elements at the specified positions from the specified array.
5150      * All remaining elements are shifted to the left.
5151      *
5152      * <p>This method returns a new array with the same elements of the input
5153      * array except those at the specified positions. The component
5154      * type of the returned array is always the same as that of the input
5155      * array.
5156      *
5157      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5158      * will be thrown, because in that case no valid index can be specified.
5159      *
5160      * <pre>
5161      * ArrayUtils.removeAll([1], 0)             = []
5162      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5163      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5164      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5165      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5166      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5167      * </pre>
5168      *
5169      * @param array   the array to remove the element from, may not be {@code null}
5170      * @param indices the positions of the elements to be removed
5171      * @return A new array containing the existing elements except those
5172      *         at the specified positions.
5173      * @throws IndexOutOfBoundsException if any index is out of range
5174      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5175      * @since 3.0.1
5176      */
5177     public static long[] removeAll(final long[] array, final int... indices) {
5178         return (long[]) removeAll((Object) array, indices);
5179     }
5180 
5181     /**
5182      * Removes multiple array elements specified by indices.
5183      *
5184      * @param array source
5185      * @param indices to remove
5186      * @return new array of same type minus elements specified by the set bits in {@code indices}
5187      * @since 3.2
5188      */
5189     // package protected for access by unit tests
5190     static Object removeAll(final Object array, final BitSet indices) {
5191         if (array == null) {
5192             return null;
5193         }
5194 
5195         final int srcLength = getLength(array);
5196         // No need to check maxIndex here, because method only currently called from removeElements()
5197         // which guarantee to generate only valid bit entries.
5198 //        final int maxIndex = indices.length();
5199 //        if (maxIndex > srcLength) {
5200 //            throw new IndexOutOfBoundsException("Index: " + (maxIndex-1) + ", Length: " + srcLength);
5201 //        }
5202         final int removals = indices.cardinality(); // true bits are items to remove
5203         final Object result = Array.newInstance(array.getClass().getComponentType(), srcLength - removals);
5204         int srcIndex = 0;
5205         int destIndex = 0;
5206         int count;
5207         int set;
5208         while ((set = indices.nextSetBit(srcIndex)) != -1) {
5209             count = set - srcIndex;
5210             if (count > 0) {
5211                 System.arraycopy(array, srcIndex, result, destIndex, count);
5212                 destIndex += count;
5213             }
5214             srcIndex = indices.nextClearBit(set);
5215         }
5216         count = srcLength - srcIndex;
5217         if (count > 0) {
5218             System.arraycopy(array, srcIndex, result, destIndex, count);
5219         }
5220         return result;
5221     }
5222 
5223     /**
5224      * Removes multiple array elements specified by index.
5225      * @param array source
5226      * @param indices to remove
5227      * @return new array of same type minus elements specified by unique values of {@code indices}
5228      * @since 3.0.1
5229      */
5230     // package protected for access by unit tests
5231     static Object removeAll(final Object array, final int... indices) {
5232         final int length = getLength(array);
5233         int diff = 0; // number of distinct indexes, i.e. number of entries that will be removed
5234         final int[] clonedIndices = ArraySorter.sort(clone(indices));
5235 
5236         // identify length of result array
5237         if (isNotEmpty(clonedIndices)) {
5238             int i = clonedIndices.length;
5239             int prevIndex = length;
5240             while (--i >= 0) {
5241                 final int index = clonedIndices[i];
5242                 if (index < 0 || index >= length) {
5243                     throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
5244                 }
5245                 if (index >= prevIndex) {
5246                     continue;
5247                 }
5248                 diff++;
5249                 prevIndex = index;
5250             }
5251         }
5252 
5253         // create result array
5254         final Object result = Array.newInstance(array.getClass().getComponentType(), length - diff);
5255         if (diff < length) {
5256             int end = length; // index just after last copy
5257             int dest = length - diff; // number of entries so far not copied
5258             for (int i = clonedIndices.length - 1; i >= 0; i--) {
5259                 final int index = clonedIndices[i];
5260                 if (end - index > 1) { // same as (cp > 0)
5261                     final int cp = end - index - 1;
5262                     dest -= cp;
5263                     System.arraycopy(array, index + 1, result, dest, cp);
5264                     // After this copy, we still have room for dest items.
5265                 }
5266                 end = index;
5267             }
5268             if (end > 0) {
5269                 System.arraycopy(array, 0, result, 0, end);
5270             }
5271         }
5272         return result;
5273     }
5274 
5275     /**
5276      * <p>Removes the elements at the specified positions from the specified array.
5277      * All remaining elements are shifted to the left.
5278      *
5279      * <p>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      *
5284      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5285      * will be thrown, because in that case no valid index can be specified.
5286      *
5287      * <pre>
5288      * ArrayUtils.removeAll([1], 0)             = []
5289      * ArrayUtils.removeAll([2, 6], 0)          = [6]
5290      * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5291      * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5292      * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5293      * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5294      * </pre>
5295      *
5296      * @param array   the array to remove the element from, may not be {@code null}
5297      * @param indices the positions of the elements to be removed
5298      * @return A new array containing the existing elements except those
5299      *         at the specified positions.
5300      * @throws IndexOutOfBoundsException if any index is out of range
5301      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5302      * @since 3.0.1
5303      */
5304     public static short[] removeAll(final short[] array, final int... indices) {
5305         return (short[]) removeAll((Object) array, indices);
5306     }
5307 
5308     /**
5309      * <p>Removes the elements at the specified positions from the specified array.
5310      * All remaining elements are shifted to the left.
5311      *
5312      * <p>This method returns a new array with the same elements of the input
5313      * array except those at the specified positions. The component
5314      * type of the returned array is always the same as that of the input
5315      * array.
5316      *
5317      * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5318      * will be thrown, because in that case no valid index can be specified.
5319      *
5320      * <pre>
5321      * ArrayUtils.removeAll(["a", "b", "c"], 0, 2) = ["b"]
5322      * ArrayUtils.removeAll(["a", "b", "c"], 1, 2) = ["a"]
5323      * </pre>
5324      *
5325      * @param <T> the component type of the array
5326      * @param array   the array to remove the element from, may not be {@code null}
5327      * @param indices the positions of the elements to be removed
5328      * @return A new array containing the existing elements except those
5329      *         at the specified positions.
5330      * @throws IndexOutOfBoundsException if any index is out of range
5331      * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5332      * @since 3.0.1
5333      */
5334     @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
5335     public static <T> T[] removeAll(final T[] array, final int... indices) {
5336         return (T[]) removeAll((Object) array, indices);
5337     }
5338 
5339     /**
5340      * Removes the occurrences of the specified element from the specified boolean array.
5341      *
5342      * <p>
5343      * All subsequent elements are shifted to the left (subtracts one from their indices).
5344      * If the array doesn't contains such an element, no elements are removed from the array.
5345      * {@code null} will be returned if the input array is {@code null}.
5346      * </p>
5347      *
5348      * @param element the element to remove
5349      * @param array the input array
5350      *
5351      * @return A new array containing the existing elements except the occurrences of the specified element.
5352      * @since 3.5
5353      * @deprecated Use {@link #removeAllOccurrences(boolean[], boolean)}
5354      */
5355     @Deprecated
5356     public static boolean[] removeAllOccurences(final boolean[] array, final boolean element) {
5357         return (boolean[]) removeAll((Object) array, indexesOf(array, element));
5358     }
5359 
5360     /**
5361      * Removes the occurrences of the specified element from the specified byte array.
5362      *
5363      * <p>
5364      * All subsequent elements are shifted to the left (subtracts one from their indices).
5365      * If the array doesn't contains such an element, no elements are removed from the array.
5366      * {@code null} will be returned if the input array is {@code null}.
5367      * </p>
5368      *
5369      * @param element the element to remove
5370      * @param array the input array
5371      *
5372      * @return A new array containing the existing elements except the occurrences of the specified element.
5373      * @since 3.5
5374      * @deprecated Use {@link #removeAllOccurrences(byte[], byte)}
5375      */
5376     @Deprecated
5377     public static byte[] removeAllOccurences(final byte[] array, final byte element) {
5378         return (byte[]) removeAll((Object) array, indexesOf(array, element));
5379     }
5380 
5381     /**
5382      * Removes the occurrences of the specified element from the specified char array.
5383      *
5384      * <p>
5385      * All subsequent elements are shifted to the left (subtracts one from their indices).
5386      * If the array doesn't contains such an element, no elements are removed from the array.
5387      * {@code null} will be returned if the input array is {@code null}.
5388      * </p>
5389      *
5390      * @param element the element to remove
5391      * @param array the input array
5392      *
5393      * @return A new array containing the existing elements except the occurrences of the specified element.
5394      * @since 3.5
5395      * @deprecated Use {@link #removeAllOccurrences(char[], char)}
5396      */
5397     @Deprecated
5398     public static char[] removeAllOccurences(final char[] array, final char element) {
5399         return (char[]) removeAll((Object) array, indexesOf(array, element));
5400     }
5401 
5402     /**
5403      * Removes the occurrences of the specified element from the specified double array.
5404      *
5405      * <p>
5406      * All subsequent elements are shifted to the left (subtracts one from their indices).
5407      * If the array doesn't contains such an element, no elements are removed from the array.
5408      * {@code null} will be returned if the input array is {@code null}.
5409      * </p>
5410      *
5411      * @param element the element to remove
5412      * @param array the input array
5413      *
5414      * @return A new array containing the existing elements except the occurrences of the specified element.
5415      * @since 3.5
5416      * @deprecated Use {@link #removeAllOccurrences(double[], double)}
5417      */
5418     @Deprecated
5419     public static double[] removeAllOccurences(final double[] array, final double element) {
5420         return (double[]) removeAll((Object) array, indexesOf(array, element));
5421     }
5422 
5423     /**
5424      * Removes the occurrences of the specified element from the specified float array.
5425      *
5426      * <p>
5427      * All subsequent elements are shifted to the left (subtracts one from their indices).
5428      * If the array doesn't contains such an element, no elements are removed from the array.
5429      * {@code null} will be returned if the input array is {@code null}.
5430      * </p>
5431      *
5432      * @param element the element to remove
5433      * @param array the input array
5434      *
5435      * @return A new array containing the existing elements except the occurrences of the specified element.
5436      * @since 3.5
5437      * @deprecated Use {@link #removeAllOccurrences(float[], float)}
5438      */
5439     @Deprecated
5440     public static float[] removeAllOccurences(final float[] array, final float element) {
5441         return (float[]) removeAll((Object) array, indexesOf(array, element));
5442     }
5443 
5444     /**
5445      * Removes the occurrences of the specified element from the specified int array.
5446      *
5447      * <p>
5448      * All subsequent elements are shifted to the left (subtracts one from their indices).
5449      * If the array doesn't contains such an element, no elements are removed from the array.
5450      * {@code null} will be returned if the input array is {@code null}.
5451      * </p>
5452      *
5453      * @param element the element to remove
5454      * @param array the input array
5455      *
5456      * @return A new array containing the existing elements except the occurrences of the specified element.
5457      * @since 3.5
5458      * @deprecated Use {@link #removeAllOccurrences(int[], int)}
5459      */
5460     @Deprecated
5461     public static int[] removeAllOccurences(final int[] array, final int element) {
5462         return (int[]) removeAll((Object) array, indexesOf(array, element));
5463     }
5464 
5465     /**
5466      * Removes the occurrences of the specified element from the specified long array.
5467      *
5468      * <p>
5469      * All subsequent elements are shifted to the left (subtracts one from their indices).
5470      * If the array doesn't contains 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 element the element to remove
5475      * @param array the input array
5476      *
5477      * @return A new array containing the existing elements except the occurrences of the specified element.
5478      * @since 3.5
5479      * @deprecated Use {@link #removeAllOccurrences(long[], long)}
5480      */
5481     @Deprecated
5482     public static long[] removeAllOccurences(final long[] array, final long element) {
5483         return (long[]) removeAll((Object) array, indexesOf(array, element));
5484     }
5485 
5486     /**
5487      * Removes the occurrences of the specified element from the specified short array.
5488      *
5489      * <p>
5490      * All subsequent elements are shifted to the left (subtracts one from their indices).
5491      * If the array doesn't contains such an element, no elements are removed from the array.
5492      * {@code null} will be returned if the input array is {@code null}.
5493      * </p>
5494      *
5495      * @param element the element to remove
5496      * @param array the input array
5497      *
5498      * @return A new array containing the existing elements except the occurrences of the specified element.
5499      * @since 3.5
5500      * @deprecated Use {@link #removeAllOccurrences(short[], short)}
5501      */
5502     @Deprecated
5503     public static short[] removeAllOccurences(final short[] array, final short element) {
5504         return (short[]) removeAll((Object) array, indexesOf(array, element));
5505     }
5506 
5507     /**
5508      * Removes the occurrences of the specified element from the specified array.
5509      *
5510      * <p>
5511      * All subsequent elements are shifted to the left (subtracts one from their indices).
5512      * If the array doesn't contains such an element, no elements are removed from the array.
5513      * {@code null} will be returned if the input array is {@code null}.
5514      * </p>
5515      *
5516      * @param <T> the type of object in the array
5517      * @param element the element to remove
5518      * @param array the input array
5519      *
5520      * @return A new array containing the existing elements except the occurrences of the specified element.
5521      * @since 3.5
5522      * @deprecated Use {@link #removeAllOccurrences(Object[], Object)}
5523      */
5524     @Deprecated
5525     public static <T> T[] removeAllOccurences(final T[] array, final T element) {
5526         return (T[]) removeAll((Object) array, indexesOf(array, element));
5527     }
5528 
5529     /**
5530      * Removes the occurrences of the specified element from the specified boolean array.
5531      *
5532      * <p>
5533      * All subsequent elements are shifted to the left (subtracts one from their indices).
5534      * If the array doesn't contains such an element, no elements are removed from the array.
5535      * {@code null} will be returned if the input array is {@code null}.
5536      * </p>
5537      *
5538      * @param element the element to remove
5539      * @param array the input array
5540      *
5541      * @return A new array containing the existing elements except the occurrences of the specified element.
5542      * @since 3.10
5543      */
5544     public static boolean[] removeAllOccurrences(final boolean[] array, final boolean element) {
5545         return (boolean[]) removeAll((Object) array, indexesOf(array, element));
5546     }
5547 
5548     /**
5549      * Removes the occurrences of the specified element from the specified byte array.
5550      *
5551      * <p>
5552      * All subsequent elements are shifted to the left (subtracts one from their indices).
5553      * If the array doesn't contains such an element, no elements are removed from the array.
5554      * {@code null} will be returned if the input array is {@code null}.
5555      * </p>
5556      *
5557      * @param element the element to remove
5558      * @param array the input array
5559      *
5560      * @return A new array containing the existing elements except the occurrences of the specified element.
5561      * @since 3.10
5562      */
5563     public static byte[] removeAllOccurrences(final byte[] array, final byte element) {
5564         return (byte[]) removeAll((Object) array, indexesOf(array, element));
5565     }
5566 
5567     /**
5568      * Removes the occurrences of the specified element from the specified char array.
5569      *
5570      * <p>
5571      * All subsequent elements are shifted to the left (subtracts one from their indices).
5572      * If the array doesn't contains such an element, no elements are removed from the array.
5573      * {@code null} will be returned if the input array is {@code null}.
5574      * </p>
5575      *
5576      * @param element the element to remove
5577      * @param array the input array
5578      *
5579      * @return A new array containing the existing elements except the occurrences of the specified element.
5580      * @since 3.10
5581      */
5582     public static char[] removeAllOccurrences(final char[] array, final char element) {
5583         return (char[]) removeAll((Object) array, indexesOf(array, element));
5584     }
5585 
5586     /**
5587      * Removes the occurrences of the specified element from the specified double array.
5588      *
5589      * <p>
5590      * All subsequent elements are shifted to the left (subtracts one from their indices).
5591      * If the array doesn't contains such an element, no elements are removed from the array.
5592      * {@code null} will be returned if the input array is {@code null}.
5593      * </p>
5594      *
5595      * @param element the element to remove
5596      * @param array the input array
5597      *
5598      * @return A new array containing the existing elements except the occurrences of the specified element.
5599      * @since 3.10
5600      */
5601     public static double[] removeAllOccurrences(final double[] array, final double element) {
5602         return (double[]) removeAll((Object) array, indexesOf(array, element));
5603     }
5604 
5605     /**
5606      * Removes the occurrences of the specified element from the specified float array.
5607      *
5608      * <p>
5609      * All subsequent elements are shifted to the left (subtracts one from their indices).
5610      * If the array doesn't contains such an element, no elements are removed from the array.
5611      * {@code null} will be returned if the input array is {@code null}.
5612      * </p>
5613      *
5614      * @param element the element to remove
5615      * @param array the input array
5616      *
5617      * @return A new array containing the existing elements except the occurrences of the specified element.
5618      * @since 3.10
5619      */
5620     public static float[] removeAllOccurrences(final float[] array, final float element) {
5621         return (float[]) removeAll((Object) array, indexesOf(array, element));
5622     }
5623 
5624     /**
5625      * Removes the occurrences of the specified element from the specified int array.
5626      *
5627      * <p>
5628      * All subsequent elements are shifted to the left (subtracts one from their indices).
5629      * If the array doesn't contains such an element, no elements are removed from the array.
5630      * {@code null} will be returned if the input array is {@code null}.
5631      * </p>
5632      *
5633      * @param element the element to remove
5634      * @param array the input array
5635      *
5636      * @return A new array containing the existing elements except the occurrences of the specified element.
5637      * @since 3.10
5638      */
5639     public static int[] removeAllOccurrences(final int[] array, final int element) {
5640         return (int[]) removeAll((Object) array, indexesOf(array, element));
5641     }
5642 
5643     /**
5644      * Removes the occurrences of the specified element from the specified long array.
5645      *
5646      * <p>
5647      * All subsequent elements are shifted to the left (subtracts one from their indices).
5648      * If the array doesn't contains such an element, no elements are removed from the array.
5649      * {@code null} will be returned if the input array is {@code null}.
5650      * </p>
5651      *
5652      * @param element the element to remove
5653      * @param array the input array
5654      *
5655      * @return A new array containing the existing elements except the occurrences of the specified element.
5656      * @since 3.10
5657      */
5658     public static long[] removeAllOccurrences(final long[] array, final long element) {
5659         return (long[]) removeAll((Object) array, indexesOf(array, element));
5660     }
5661 
5662     /**
5663      * Removes the occurrences of the specified element from the specified short array.
5664      *
5665      * <p>
5666      * All subsequent elements are shifted to the left (subtracts one from their indices).
5667      * If the array doesn't contains such an element, no elements are removed from the array.
5668      * {@code null} will be returned if the input array is {@code null}.
5669      * </p>
5670      *
5671      * @param element the element to remove
5672      * @param array the input array
5673      *
5674      * @return A new array containing the existing elements except the occurrences of the specified element.
5675      * @since 3.10
5676      */
5677     public static short[] removeAllOccurrences(final short[] array, final short element) {
5678         return (short[]) removeAll((Object) array, indexesOf(array, element));
5679     }
5680 
5681     /**
5682      * Removes the occurrences of the specified element from the specified array.
5683      *
5684      * <p>
5685      * All subsequent elements are shifted to the left (subtracts one from their indices).
5686      * If the array doesn't contains such an element, no elements are removed from the array.
5687      * {@code null} will be returned if the input array is {@code null}.
5688      * </p>
5689      *
5690      * @param <T> the type of object in the array
5691      * @param element the element to remove
5692      * @param array the input array
5693      *
5694      * @return A new array containing the existing elements except the occurrences of the specified element.
5695      * @since 3.10
5696      */
5697     public static <T> T[] removeAllOccurrences(final T[] array, final T element) {
5698         return (T[]) removeAll((Object) array, indexesOf(array, element));
5699     }
5700 
5701     /**
5702      * <p>Removes the first occurrence of the specified element from the
5703      * specified array. All subsequent elements are shifted to the left
5704      * (subtracts one from their indices). If the array doesn't contains
5705      * such an element, no elements are removed from the array.
5706      *
5707      * <p>This method returns a new array with the same elements of the input
5708      * array except the first occurrence of the specified element. The component
5709      * type of the returned array is always the same as that of the input
5710      * array.
5711      *
5712      * <pre>
5713      * ArrayUtils.removeElement(null, true)                = null
5714      * ArrayUtils.removeElement([], true)                  = []
5715      * ArrayUtils.removeElement([true], false)             = [true]
5716      * ArrayUtils.removeElement([true, false], false)      = [true]
5717      * ArrayUtils.removeElement([true, false, true], true) = [false, true]
5718      * </pre>
5719      *
5720      * @param array  the array to remove the element from, may be {@code null}
5721      * @param element  the element to be removed
5722      * @return A new array containing the existing elements except the first
5723      *         occurrence of the specified element.
5724      * @since 2.1
5725      */
5726     public static boolean[] removeElement(final boolean[] array, final boolean element) {
5727         final int index = indexOf(array, element);
5728         if (index == INDEX_NOT_FOUND) {
5729             return clone(array);
5730         }
5731         return remove(array, index);
5732     }
5733 
5734     /**
5735      * <p>Removes the first occurrence of the specified element from the
5736      * specified array. All subsequent elements are shifted to the left
5737      * (subtracts one from their indices). If the array doesn't contains
5738      * such an element, no elements are removed from the array.
5739      *
5740      * <p>This method returns a new array with the same elements of the input
5741      * array except the first occurrence of the specified element. The component
5742      * type of the returned array is always the same as that of the input
5743      * array.
5744      *
5745      * <pre>
5746      * ArrayUtils.removeElement(null, 1)        = null
5747      * ArrayUtils.removeElement([], 1)          = []
5748      * ArrayUtils.removeElement([1], 0)         = [1]
5749      * ArrayUtils.removeElement([1, 0], 0)      = [1]
5750      * ArrayUtils.removeElement([1, 0, 1], 1)   = [0, 1]
5751      * </pre>
5752      *
5753      * @param array  the array to remove the element from, may be {@code null}
5754      * @param element  the element to be removed
5755      * @return A new array containing the existing elements except the first
5756      *         occurrence of the specified element.
5757      * @since 2.1
5758      */
5759     public static byte[] removeElement(final byte[] array, final byte element) {
5760         final int index = indexOf(array, element);
5761         if (index == INDEX_NOT_FOUND) {
5762             return clone(array);
5763         }
5764         return remove(array, index);
5765     }
5766 
5767     /**
5768      * <p>Removes the first occurrence of the specified element from the
5769      * specified array. All subsequent elements are shifted to the left
5770      * (subtracts one from their indices). If the array doesn't contains
5771      * such an element, no elements are removed from the array.
5772      *
5773      * <p>This method returns a new array with the same elements of the input
5774      * array except the first occurrence of the specified element. The component
5775      * type of the returned array is always the same as that of the input
5776      * array.
5777      *
5778      * <pre>
5779      * ArrayUtils.removeElement(null, 'a')            = null
5780      * ArrayUtils.removeElement([], 'a')              = []
5781      * ArrayUtils.removeElement(['a'], 'b')           = ['a']
5782      * ArrayUtils.removeElement(['a', 'b'], 'a')      = ['b']
5783      * ArrayUtils.removeElement(['a', 'b', 'a'], 'a') = ['b', 'a']
5784      * </pre>
5785      *
5786      * @param array  the array to remove the element from, may be {@code null}
5787      * @param element  the element to be removed
5788      * @return A new array containing the existing elements except the first
5789      *         occurrence of the specified element.
5790      * @since 2.1
5791      */
5792     public static char[] removeElement(final char[] array, final char element) {
5793         final int index = indexOf(array, element);
5794         if (index == INDEX_NOT_FOUND) {
5795             return clone(array);
5796         }
5797         return remove(array, index);
5798     }
5799 
5800     /**
5801      * <p>Removes the first occurrence of the specified element from the
5802      * specified array. All subsequent elements are shifted to the left
5803      * (subtracts one from their indices). If the array doesn't contains
5804      * such an element, no elements are removed from the array.
5805      *
5806      * <p>This method returns a new array with the same elements of the input
5807      * array except the first occurrence of the specified element. The component
5808      * type of the returned array is always the same as that of the input
5809      * array.
5810      *
5811      * <pre>
5812      * ArrayUtils.removeElement(null, 1.1)            = null
5813      * ArrayUtils.removeElement([], 1.1)              = []
5814      * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
5815      * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
5816      * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
5817      * </pre>
5818      *
5819      * @param array  the array to remove the element from, may be {@code null}
5820      * @param element  the element to be removed
5821      * @return A new array containing the existing elements except the first
5822      *         occurrence of the specified element.
5823      * @since 2.1
5824      */
5825     public static double[] removeElement(final double[] array, final double element) {
5826         final int index = indexOf(array, element);
5827         if (index == INDEX_NOT_FOUND) {
5828             return clone(array);
5829         }
5830         return remove(array, index);
5831     }
5832 
5833     /**
5834      * <p>Removes the first occurrence of the specified element from the
5835      * specified array. All subsequent elements are shifted to the left
5836      * (subtracts one from their indices). If the array doesn't contains
5837      * such an element, no elements are removed from the array.
5838      *
5839      * <p>This method returns a new array with the same elements of the input
5840      * array except the first occurrence of the specified element. The component
5841      * type of the returned array is always the same as that of the input
5842      * array.
5843      *
5844      * <pre>
5845      * ArrayUtils.removeElement(null, 1.1)            = null
5846      * ArrayUtils.removeElement([], 1.1)              = []
5847      * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
5848      * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
5849      * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
5850      * </pre>
5851      *
5852      * @param array  the array to remove the element from, may be {@code null}
5853      * @param element  the element to be removed
5854      * @return A new array containing the existing elements except the first
5855      *         occurrence of the specified element.
5856      * @since 2.1
5857      */
5858     public static float[] removeElement(final float[] array, final float element) {
5859         final int index = indexOf(array, element);
5860         if (index == INDEX_NOT_FOUND) {
5861             return clone(array);
5862         }
5863         return remove(array, index);
5864     }
5865 
5866     /**
5867      * <p>Removes the first occurrence of the specified element from the
5868      * specified array. All subsequent elements are shifted to the left
5869      * (subtracts one from their indices). If the array doesn't contains
5870      * such an element, no elements are removed from the array.
5871      *
5872      * <p>This method returns a new array with the same elements of the input
5873      * array except the first occurrence of the specified element. The component
5874      * type of the returned array is always the same as that of the input
5875      * array.
5876      *
5877      * <pre>
5878      * ArrayUtils.removeElement(null, 1)      = null
5879      * ArrayUtils.removeElement([], 1)        = []
5880      * ArrayUtils.removeElement([1], 2)       = [1]
5881      * ArrayUtils.removeElement([1, 3], 1)    = [3]
5882      * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
5883      * </pre>
5884      *
5885      * @param array  the array to remove the element from, may be {@code null}
5886      * @param element  the element to be removed
5887      * @return A new array containing the existing elements except the first
5888      *         occurrence of the specified element.
5889      * @since 2.1
5890      */
5891     public static int[] removeElement(final int[] array, final int element) {
5892         final int index = indexOf(array, element);
5893         if (index == INDEX_NOT_FOUND) {
5894             return clone(array);
5895         }
5896         return remove(array, index);
5897     }
5898 
5899     /**
5900      * <p>Removes the first occurrence of the specified element from the
5901      * specified array. All subsequent elements are shifted to the left
5902      * (subtracts one from their indices). If the array doesn't contains
5903      * such an element, no elements are removed from the array.
5904      *
5905      * <p>This method returns a new array with the same elements of the input
5906      * array except the first occurrence of the specified element. The component
5907      * type of the returned array is always the same as that of the input
5908      * array.
5909      *
5910      * <pre>
5911      * ArrayUtils.removeElement(null, 1)      = null
5912      * ArrayUtils.removeElement([], 1)        = []
5913      * ArrayUtils.removeElement([1], 2)       = [1]
5914      * ArrayUtils.removeElement([1, 3], 1)    = [3]
5915      * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
5916      * </pre>
5917      *
5918      * @param array  the array to remove the element from, may be {@code null}
5919      * @param element  the element to be removed
5920      * @return A new array containing the existing elements except the first
5921      *         occurrence of the specified element.
5922      * @since 2.1
5923      */
5924     public static long[] removeElement(final long[] array, final long element) {
5925         final int index = indexOf(array, element);
5926         if (index == INDEX_NOT_FOUND) {
5927             return clone(array);
5928         }
5929         return remove(array, index);
5930     }
5931 
5932     /**
5933      * <p>Removes the first occurrence of the specified element from the
5934      * specified array. All subsequent elements are shifted to the left
5935      * (subtracts one from their indices). If the array doesn't contains
5936      * such an element, no elements are removed from the array.
5937      *
5938      * <p>This method returns a new array with the same elements of the input
5939      * array except the first occurrence of the specified element. The component
5940      * type of the returned array is always the same as that of the input
5941      * array.
5942      *
5943      * <pre>
5944      * ArrayUtils.removeElement(null, 1)      = null
5945      * ArrayUtils.removeElement([], 1)        = []
5946      * ArrayUtils.removeElement([1], 2)       = [1]
5947      * ArrayUtils.removeElement([1, 3], 1)    = [3]
5948      * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
5949      * </pre>
5950      *
5951      * @param array  the array to remove the element from, may be {@code null}
5952      * @param element  the element to be removed
5953      * @return A new array containing the existing elements except the first
5954      *         occurrence of the specified element.
5955      * @since 2.1
5956      */
5957     public static short[] removeElement(final short[] array, final short element) {
5958         final int index = indexOf(array, element);
5959         if (index == INDEX_NOT_FOUND) {
5960             return clone(array);
5961         }
5962         return remove(array, index);
5963     }
5964 
5965     /**
5966      * <p>Removes the first occurrence of the specified element from the
5967      * specified array. All subsequent elements are shifted to the left
5968      * (subtracts one from their indices). If the array doesn't contains
5969      * such an element, no elements are removed from the array.
5970      *
5971      * <p>This method returns a new array with the same elements of the input
5972      * array except the first occurrence of the specified element. The component
5973      * type of the returned array is always the same as that of the input
5974      * array.
5975      *
5976      * <pre>
5977      * ArrayUtils.removeElement(null, "a")            = null
5978      * ArrayUtils.removeElement([], "a")              = []
5979      * ArrayUtils.removeElement(["a"], "b")           = ["a"]
5980      * ArrayUtils.removeElement(["a", "b"], "a")      = ["b"]
5981      * ArrayUtils.removeElement(["a", "b", "a"], "a") = ["b", "a"]
5982      * </pre>
5983      *
5984      * @param <T> the component type of the array
5985      * @param array  the array to remove the element from, may be {@code null}
5986      * @param element  the element to be removed
5987      * @return A new array containing the existing elements except the first
5988      *         occurrence of the specified element.
5989      * @since 2.1
5990      */
5991     public static <T> T[] removeElement(final T[] array, final Object element) {
5992         final int index = indexOf(array, element);
5993         if (index == INDEX_NOT_FOUND) {
5994             return clone(array);
5995         }
5996         return remove(array, index);
5997     }
5998 
5999     /**
6000      * <p>Removes occurrences of specified elements, in specified quantities,
6001      * from the specified array. All subsequent elements are shifted left.
6002      * For any element-to-be-removed specified in greater quantities than
6003      * contained in the original array, no change occurs beyond the
6004      * removal of the existing matching items.
6005      *
6006      * <p>This method returns a new array with the same elements of the input
6007      * array except for the earliest-encountered occurrences of the specified
6008      * elements. The component type of the returned array is always the same
6009      * as that of the input array.
6010      *
6011      * <pre>
6012      * ArrayUtils.removeElements(null, true, false)               = null
6013      * ArrayUtils.removeElements([], true, false)                 = []
6014      * ArrayUtils.removeElements([true], false, false)            = [true]
6015      * ArrayUtils.removeElements([true, false], true, true)       = [false]
6016      * ArrayUtils.removeElements([true, false, true], true)       = [false, true]
6017      * ArrayUtils.removeElements([true, false, true], true, true) = [false]
6018      * </pre>
6019      *
6020      * @param array  the array to remove the element from, may be {@code null}
6021      * @param values the elements to be removed
6022      * @return A new array containing the existing elements except the
6023      *         earliest-encountered occurrences of the specified elements.
6024      * @since 3.0.1
6025      */
6026     public static boolean[] removeElements(final boolean[] array, final boolean... values) {
6027         if (isEmpty(array) || isEmpty(values)) {
6028             return clone(array);
6029         }
6030         final HashMap<Boolean, MutableInt> occurrences = new HashMap<>(2); // only two possible values here
6031         for (final boolean v : values) {
6032             final Boolean boxed = Boolean.valueOf(v);
6033             final MutableInt count = occurrences.get(boxed);
6034             if (count == null) {
6035                 occurrences.put(boxed, new MutableInt(1));
6036             } else {
6037                 count.increment();
6038             }
6039         }
6040         final BitSet toRemove = new BitSet();
6041         for (int i = 0; i < array.length; i++) {
6042             final boolean key = array[i];
6043             final MutableInt count = occurrences.get(key);
6044             if (count != null) {
6045                 if (count.decrementAndGet() == 0) {
6046                     occurrences.remove(key);
6047                 }
6048                 toRemove.set(i);
6049             }
6050         }
6051         return (boolean[]) removeAll(array, toRemove);
6052     }
6053 
6054     /**
6055      * <p>Removes occurrences of specified elements, in specified quantities,
6056      * from the specified array. All subsequent elements are shifted left.
6057      * For any element-to-be-removed specified in greater quantities than
6058      * contained in the original array, no change occurs beyond the
6059      * removal of the existing matching items.
6060      *
6061      * <p>This method returns a new array with the same elements of the input
6062      * array except for the earliest-encountered occurrences of the specified
6063      * elements. The component type of the returned array is always the same
6064      * as that of the input array.
6065      *
6066      * <pre>
6067      * ArrayUtils.removeElements(null, 1, 2)      = null
6068      * ArrayUtils.removeElements([], 1, 2)        = []
6069      * ArrayUtils.removeElements([1], 2, 3)       = [1]
6070      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6071      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6072      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6073      * </pre>
6074      *
6075      * @param array  the array to remove the element from, may be {@code null}
6076      * @param values the elements to be removed
6077      * @return A new array containing the existing elements except the
6078      *         earliest-encountered occurrences of the specified elements.
6079      * @since 3.0.1
6080      */
6081     public static byte[] removeElements(final byte[] array, final byte... values) {
6082         if (isEmpty(array) || isEmpty(values)) {
6083             return clone(array);
6084         }
6085         final Map<Byte, MutableInt> occurrences = new HashMap<>(values.length);
6086         for (final byte v : values) {
6087             final Byte boxed = Byte.valueOf(v);
6088             final MutableInt count = occurrences.get(boxed);
6089             if (count == null) {
6090                 occurrences.put(boxed, new MutableInt(1));
6091             } else {
6092                 count.increment();
6093             }
6094         }
6095         final BitSet toRemove = new BitSet();
6096         for (int i = 0; i < array.length; i++) {
6097             final byte key = array[i];
6098             final MutableInt count = occurrences.get(key);
6099             if (count != null) {
6100                 if (count.decrementAndGet() == 0) {
6101                     occurrences.remove(key);
6102                 }
6103                 toRemove.set(i);
6104             }
6105         }
6106         return (byte[]) removeAll(array, toRemove);
6107     }
6108 
6109     /**
6110      * <p>Removes occurrences of specified elements, in specified quantities,
6111      * from the specified array. All subsequent elements are shifted left.
6112      * For any element-to-be-removed specified in greater quantities than
6113      * contained in the original array, no change occurs beyond the
6114      * removal of the existing matching items.
6115      *
6116      * <p>This method returns a new array with the same elements of the input
6117      * array except for the earliest-encountered occurrences of the specified
6118      * elements. The component type of the returned array is always the same
6119      * as that of the input array.
6120      *
6121      * <pre>
6122      * ArrayUtils.removeElements(null, 1, 2)      = null
6123      * ArrayUtils.removeElements([], 1, 2)        = []
6124      * ArrayUtils.removeElements([1], 2, 3)       = [1]
6125      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6126      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6127      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6128      * </pre>
6129      *
6130      * @param array  the array to remove the element from, may be {@code null}
6131      * @param values the elements to be removed
6132      * @return A new array containing the existing elements except the
6133      *         earliest-encountered occurrences of the specified elements.
6134      * @since 3.0.1
6135      */
6136     public static char[] removeElements(final char[] array, final char... values) {
6137         if (isEmpty(array) || isEmpty(values)) {
6138             return clone(array);
6139         }
6140         final HashMap<Character, MutableInt> occurrences = new HashMap<>(values.length);
6141         for (final char v : values) {
6142             final Character boxed = Character.valueOf(v);
6143             final MutableInt count = occurrences.get(boxed);
6144             if (count == null) {
6145                 occurrences.put(boxed, new MutableInt(1));
6146             } else {
6147                 count.increment();
6148             }
6149         }
6150         final BitSet toRemove = new BitSet();
6151         for (int i = 0; i < array.length; i++) {
6152             final char key = array[i];
6153             final MutableInt count = occurrences.get(key);
6154             if (count != null) {
6155                 if (count.decrementAndGet() == 0) {
6156                     occurrences.remove(key);
6157                 }
6158                 toRemove.set(i);
6159             }
6160         }
6161         return (char[]) removeAll(array, toRemove);
6162     }
6163 
6164     /**
6165      * <p>Removes occurrences of specified elements, in specified quantities,
6166      * from the specified array. All subsequent elements are shifted left.
6167      * For any element-to-be-removed specified in greater quantities than
6168      * contained in the original array, no change occurs beyond the
6169      * removal of the existing matching items.
6170      *
6171      * <p>This method returns a new array with the same elements of the input
6172      * array except for the earliest-encountered occurrences of the specified
6173      * elements. The component type of the returned array is always the same
6174      * as that of the input array.
6175      *
6176      * <pre>
6177      * ArrayUtils.removeElements(null, 1, 2)      = null
6178      * ArrayUtils.removeElements([], 1, 2)        = []
6179      * ArrayUtils.removeElements([1], 2, 3)       = [1]
6180      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6181      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6182      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6183      * </pre>
6184      *
6185      * @param array  the array to remove the element from, may be {@code null}
6186      * @param values the elements to be removed
6187      * @return A new array containing the existing elements except the
6188      *         earliest-encountered occurrences of the specified elements.
6189      * @since 3.0.1
6190      */
6191     public static double[] removeElements(final double[] array, final double... values) {
6192         if (isEmpty(array) || isEmpty(values)) {
6193             return clone(array);
6194         }
6195         final HashMap<Double, MutableInt> occurrences = new HashMap<>(values.length);
6196         for (final double v : values) {
6197             final Double boxed = Double.valueOf(v);
6198             final MutableInt count = occurrences.get(boxed);
6199             if (count == null) {
6200                 occurrences.put(boxed, new MutableInt(1));
6201             } else {
6202                 count.increment();
6203             }
6204         }
6205         final BitSet toRemove = new BitSet();
6206         for (int i = 0; i < array.length; i++) {
6207             final double key = array[i];
6208             final MutableInt count = occurrences.get(key);
6209             if (count != null) {
6210                 if (count.decrementAndGet() == 0) {
6211                     occurrences.remove(key);
6212                 }
6213                 toRemove.set(i);
6214             }
6215         }
6216         return (double[]) removeAll(array, toRemove);
6217     }
6218 
6219     /**
6220      * <p>Removes occurrences of specified elements, in specified quantities,
6221      * from the specified array. All subsequent elements are shifted left.
6222      * For any element-to-be-removed specified in greater quantities than
6223      * contained in the original array, no change occurs beyond the
6224      * removal of the existing matching items.
6225      *
6226      * <p>This method returns a new array with the same elements of the input
6227      * array except for the earliest-encountered occurrences of the specified
6228      * elements. The component type of the returned array is always the same
6229      * as that of the input array.
6230      *
6231      * <pre>
6232      * ArrayUtils.removeElements(null, 1, 2)      = null
6233      * ArrayUtils.removeElements([], 1, 2)        = []
6234      * ArrayUtils.removeElements([1], 2, 3)       = [1]
6235      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6236      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6237      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6238      * </pre>
6239      *
6240      * @param array  the array to remove the element from, may be {@code null}
6241      * @param values the elements to be removed
6242      * @return A new array containing the existing elements except the
6243      *         earliest-encountered occurrences of the specified elements.
6244      * @since 3.0.1
6245      */
6246     public static float[] removeElements(final float[] array, final float... values) {
6247         if (isEmpty(array) || isEmpty(values)) {
6248             return clone(array);
6249         }
6250         final HashMap<Float, MutableInt> occurrences = new HashMap<>(values.length);
6251         for (final float v : values) {
6252             final Float boxed = Float.valueOf(v);
6253             final MutableInt count = occurrences.get(boxed);
6254             if (count == null) {
6255                 occurrences.put(boxed, new MutableInt(1));
6256             } else {
6257                 count.increment();
6258             }
6259         }
6260         final BitSet toRemove = new BitSet();
6261         for (int i = 0; i < array.length; i++) {
6262             final float key = array[i];
6263             final MutableInt count = occurrences.get(key);
6264             if (count != null) {
6265                 if (count.decrementAndGet() == 0) {
6266                     occurrences.remove(key);
6267                 }
6268                 toRemove.set(i);
6269             }
6270         }
6271         return (float[]) removeAll(array, toRemove);
6272     }
6273 
6274     /**
6275      * <p>Removes occurrences of specified elements, in specified quantities,
6276      * from the specified array. All subsequent elements are shifted left.
6277      * For any element-to-be-removed specified in greater quantities than
6278      * contained in the original array, no change occurs beyond the
6279      * removal of the existing matching items.
6280      *
6281      * <p>This method returns a new array with the same elements of the input
6282      * array except for the earliest-encountered occurrences of the specified
6283      * elements. The component type of the returned array is always the same
6284      * as that of the input array.
6285      *
6286      * <pre>
6287      * ArrayUtils.removeElements(null, 1, 2)      = null
6288      * ArrayUtils.removeElements([], 1, 2)        = []
6289      * ArrayUtils.removeElements([1], 2, 3)       = [1]
6290      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6291      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6292      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6293      * </pre>
6294      *
6295      * @param array  the array to remove the element from, may be {@code null}
6296      * @param values the elements to be removed
6297      * @return A new array containing the existing elements except the
6298      *         earliest-encountered occurrences of the specified elements.
6299      * @since 3.0.1
6300      */
6301     public static int[] removeElements(final int[] array, final int... values) {
6302         if (isEmpty(array) || isEmpty(values)) {
6303             return clone(array);
6304         }
6305         final HashMap<Integer, MutableInt> occurrences = new HashMap<>(values.length);
6306         for (final int v : values) {
6307             final Integer boxed = Integer.valueOf(v);
6308             final MutableInt count = occurrences.get(boxed);
6309             if (count == null) {
6310                 occurrences.put(boxed, new MutableInt(1));
6311             } else {
6312                 count.increment();
6313             }
6314         }
6315         final BitSet toRemove = new BitSet();
6316         for (int i = 0; i < array.length; i++) {
6317             final int key = array[i];
6318             final MutableInt count = occurrences.get(key);
6319             if (count != null) {
6320                 if (count.decrementAndGet() == 0) {
6321                     occurrences.remove(key);
6322                 }
6323                 toRemove.set(i);
6324             }
6325         }
6326         return (int[]) removeAll(array, toRemove);
6327     }
6328 
6329     /**
6330      * <p>Removes occurrences of specified elements, in specified quantities,
6331      * from the specified array. All subsequent elements are shifted left.
6332      * For any element-to-be-removed specified in greater quantities than
6333      * contained in the original array, no change occurs beyond the
6334      * removal of the existing matching items.
6335      *
6336      * <p>This method returns a new array with the same elements of the input
6337      * array except for the earliest-encountered occurrences of the specified
6338      * elements. The component type of the returned array is always the same
6339      * as that of the input array.
6340      *
6341      * <pre>
6342      * ArrayUtils.removeElements(null, 1, 2)      = null
6343      * ArrayUtils.removeElements([], 1, 2)        = []
6344      * ArrayUtils.removeElements([1], 2, 3)       = [1]
6345      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6346      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6347      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6348      * </pre>
6349      *
6350      * @param array  the array to remove the element from, may be {@code null}
6351      * @param values the elements to be removed
6352      * @return A new array containing the existing elements except the
6353      *         earliest-encountered occurrences of the specified elements.
6354      * @since 3.0.1
6355      */
6356     public static long[] removeElements(final long[] array, final long... values) {
6357         if (isEmpty(array) || isEmpty(values)) {
6358             return clone(array);
6359         }
6360         final HashMap<Long, MutableInt> occurrences = new HashMap<>(values.length);
6361         for (final long v : values) {
6362             final Long boxed = Long.valueOf(v);
6363             final MutableInt count = occurrences.get(boxed);
6364             if (count == null) {
6365                 occurrences.put(boxed, new MutableInt(1));
6366             } else {
6367                 count.increment();
6368             }
6369         }
6370         final BitSet toRemove = new BitSet();
6371         for (int i = 0; i < array.length; i++) {
6372             final long key = array[i];
6373             final MutableInt count = occurrences.get(key);
6374             if (count != null) {
6375                 if (count.decrementAndGet() == 0) {
6376                     occurrences.remove(key);
6377                 }
6378                 toRemove.set(i);
6379             }
6380         }
6381         return (long[]) removeAll(array, toRemove);
6382     }
6383 
6384     /**
6385      * <p>Removes occurrences of specified elements, in specified quantities,
6386      * from the specified array. All subsequent elements are shifted left.
6387      * For any element-to-be-removed specified in greater quantities than
6388      * contained in the original array, no change occurs beyond the
6389      * removal of the existing matching items.
6390      *
6391      * <p>This method returns a new array with the same elements of the input
6392      * array except for the earliest-encountered occurrences of the specified
6393      * elements. The component type of the returned array is always the same
6394      * as that of the input array.
6395      *
6396      * <pre>
6397      * ArrayUtils.removeElements(null, 1, 2)      = null
6398      * ArrayUtils.removeElements([], 1, 2)        = []
6399      * ArrayUtils.removeElements([1], 2, 3)       = [1]
6400      * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6401      * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6402      * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6403      * </pre>
6404      *
6405      * @param array  the array to remove the element from, may be {@code null}
6406      * @param values the elements to be removed
6407      * @return A new array containing the existing elements except the
6408      *         earliest-encountered occurrences of the specified elements.
6409      * @since 3.0.1
6410      */
6411     public static short[] removeElements(final short[] array, final short... values) {
6412         if (isEmpty(array) || isEmpty(values)) {
6413             return clone(array);
6414         }
6415         final HashMap<Short, MutableInt> occurrences = new HashMap<>(values.length);
6416         for (final short v : values) {
6417             final Short boxed = Short.valueOf(v);
6418             final MutableInt count = occurrences.get(boxed);
6419             if (count == null) {
6420                 occurrences.put(boxed, new MutableInt(1));
6421             } else {
6422                 count.increment();
6423             }
6424         }
6425         final BitSet toRemove = new BitSet();
6426         for (int i = 0; i < array.length; i++) {
6427             final short key = array[i];
6428             final MutableInt count = occurrences.get(key);
6429             if (count != null) {
6430                 if (count.decrementAndGet() == 0) {
6431                     occurrences.remove(key);
6432                 }
6433                 toRemove.set(i);
6434             }
6435         }
6436         return (short[]) removeAll(array, toRemove);
6437     }
6438 
6439     /**
6440      * <p>Removes occurrences of specified elements, in specified quantities,
6441      * from the specified array. All subsequent elements are shifted left.
6442      * For any element-to-be-removed specified in greater quantities than
6443      * contained in the original array, no change occurs beyond the
6444      * removal of the existing matching items.
6445      *
6446      * <p>This method returns a new array with the same elements of the input
6447      * array except for the earliest-encountered occurrences of the specified
6448      * elements. The component type of the returned array is always the same
6449      * as that of the input array.
6450      *
6451      * <pre>
6452      * ArrayUtils.removeElements(null, "a", "b")            = null
6453      * ArrayUtils.removeElements([], "a", "b")              = []
6454      * ArrayUtils.removeElements(["a"], "b", "c")           = ["a"]
6455      * ArrayUtils.removeElements(["a", "b"], "a", "c")      = ["b"]
6456      * ArrayUtils.removeElements(["a", "b", "a"], "a")      = ["b", "a"]
6457      * ArrayUtils.removeElements(["a", "b", "a"], "a", "a") = ["b"]
6458      * </pre>
6459      *
6460      * @param <T> the component type of the array
6461      * @param array  the array to remove the element from, may be {@code null}
6462      * @param values the elements to be removed
6463      * @return A new array containing the existing elements except the
6464      *         earliest-encountered occurrences of the specified elements.
6465      * @since 3.0.1
6466      */
6467     @SafeVarargs
6468     public static <T> T[] removeElements(final T[] array, final T... values) {
6469         if (isEmpty(array) || isEmpty(values)) {
6470             return clone(array);
6471         }
6472         final HashMap<T, MutableInt> occurrences = new HashMap<>(values.length);
6473         for (final T v : values) {
6474             final MutableInt count = occurrences.get(v);
6475             if (count == null) {
6476                 occurrences.put(v, new MutableInt(1));
6477             } else {
6478                 count.increment();
6479             }
6480         }
6481         final BitSet toRemove = new BitSet();
6482         for (int i = 0; i < array.length; i++) {
6483             final T key = array[i];
6484             final MutableInt count = occurrences.get(key);
6485             if (count != null) {
6486                 if (count.decrementAndGet() == 0) {
6487                     occurrences.remove(key);
6488                 }
6489                 toRemove.set(i);
6490             }
6491         }
6492         @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
6493         final T[] result = (T[]) removeAll(array, toRemove);
6494         return result;
6495     }
6496 
6497     /**
6498      * <p>Reverses the order of the given array.
6499      *
6500      * <p>This method does nothing for a {@code null} input array.
6501      *
6502      * @param array  the array to reverse, may be {@code null}
6503      */
6504     public static void reverse(final boolean[] array) {
6505         if (array == null) {
6506             return;
6507         }
6508         reverse(array, 0, array.length);
6509     }
6510 
6511     /**
6512      * <p>
6513      * Reverses the order of the given array in the given range.
6514      *
6515      * <p>
6516      * This method does nothing for a {@code null} input array.
6517      *
6518      * @param array
6519      *            the array to reverse, may be {@code null}
6520      * @param startIndexInclusive
6521      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6522      *            change.
6523      * @param endIndexExclusive
6524      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6525      *            change. Overvalue (&gt;array.length) is demoted to array length.
6526      * @since 3.2
6527      */
6528     public static void reverse(final boolean[] array, final int startIndexInclusive, final int endIndexExclusive) {
6529         if (array == null) {
6530             return;
6531         }
6532         int i = Math.max(startIndexInclusive, 0);
6533         int j = Math.min(array.length, endIndexExclusive) - 1;
6534         boolean tmp;
6535         while (j > i) {
6536             tmp = array[j];
6537             array[j] = array[i];
6538             array[i] = tmp;
6539             j--;
6540             i++;
6541         }
6542     }
6543 
6544     /**
6545      * <p>Reverses the order of the given array.
6546      *
6547      * <p>This method does nothing for a {@code null} input array.
6548      *
6549      * @param array  the array to reverse, may be {@code null}
6550      */
6551     public static void reverse(final byte[] array) {
6552         if (array == null) {
6553             return;
6554         }
6555         reverse(array, 0, array.length);
6556     }
6557 
6558     /**
6559      * <p>
6560      * Reverses the order of the given array in the given range.
6561      *
6562      * <p>
6563      * This method does nothing for a {@code null} input array.
6564      *
6565      * @param array
6566      *            the array to reverse, may be {@code null}
6567      * @param startIndexInclusive
6568      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6569      *            change.
6570      * @param endIndexExclusive
6571      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6572      *            change. Overvalue (&gt;array.length) is demoted to array length.
6573      * @since 3.2
6574      */
6575     public static void reverse(final byte[] array, final int startIndexInclusive, final int endIndexExclusive) {
6576         if (array == null) {
6577             return;
6578         }
6579         int i = Math.max(startIndexInclusive, 0);
6580         int j = Math.min(array.length, endIndexExclusive) - 1;
6581         byte tmp;
6582         while (j > i) {
6583             tmp = array[j];
6584             array[j] = array[i];
6585             array[i] = tmp;
6586             j--;
6587             i++;
6588         }
6589     }
6590 
6591     /**
6592      * <p>Reverses the order of the given array.
6593      *
6594      * <p>This method does nothing for a {@code null} input array.
6595      *
6596      * @param array  the array to reverse, may be {@code null}
6597      */
6598     public static void reverse(final char[] array) {
6599         if (array == null) {
6600             return;
6601         }
6602         reverse(array, 0, array.length);
6603     }
6604 
6605     /**
6606      * <p>
6607      * Reverses the order of the given array in the given range.
6608      *
6609      * <p>
6610      * This method does nothing for a {@code null} input array.
6611      *
6612      * @param array
6613      *            the array to reverse, may be {@code null}
6614      * @param startIndexInclusive
6615      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6616      *            change.
6617      * @param endIndexExclusive
6618      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6619      *            change. Overvalue (&gt;array.length) is demoted to array length.
6620      * @since 3.2
6621      */
6622     public static void reverse(final char[] array, final int startIndexInclusive, final int endIndexExclusive) {
6623         if (array == null) {
6624             return;
6625         }
6626         int i = Math.max(startIndexInclusive, 0);
6627         int j = Math.min(array.length, endIndexExclusive) - 1;
6628         char tmp;
6629         while (j > i) {
6630             tmp = array[j];
6631             array[j] = array[i];
6632             array[i] = tmp;
6633             j--;
6634             i++;
6635         }
6636     }
6637 
6638     /**
6639      * <p>Reverses the order of the given array.
6640      *
6641      * <p>This method does nothing for a {@code null} input array.
6642      *
6643      * @param array  the array to reverse, may be {@code null}
6644      */
6645     public static void reverse(final double[] array) {
6646         if (array == null) {
6647             return;
6648         }
6649         reverse(array, 0, array.length);
6650     }
6651 
6652     /**
6653      * <p>
6654      * Reverses the order of the given array in the given range.
6655      *
6656      * <p>
6657      * This method does nothing for a {@code null} input array.
6658      *
6659      * @param array
6660      *            the array to reverse, may be {@code null}
6661      * @param startIndexInclusive
6662      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6663      *            change.
6664      * @param endIndexExclusive
6665      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6666      *            change. Overvalue (&gt;array.length) is demoted to array length.
6667      * @since 3.2
6668      */
6669     public static void reverse(final double[] array, final int startIndexInclusive, final int endIndexExclusive) {
6670         if (array == null) {
6671             return;
6672         }
6673         int i = Math.max(startIndexInclusive, 0);
6674         int j = Math.min(array.length, endIndexExclusive) - 1;
6675         double tmp;
6676         while (j > i) {
6677             tmp = array[j];
6678             array[j] = array[i];
6679             array[i] = tmp;
6680             j--;
6681             i++;
6682         }
6683     }
6684 
6685     /**
6686      * <p>Reverses the order of the given array.
6687      *
6688      * <p>This method does nothing for a {@code null} input array.
6689      *
6690      * @param array  the array to reverse, may be {@code null}
6691      */
6692     public static void reverse(final float[] array) {
6693         if (array == null) {
6694             return;
6695         }
6696         reverse(array, 0, array.length);
6697     }
6698 
6699     /**
6700      * <p>
6701      * Reverses the order of the given array in the given range.
6702      *
6703      * <p>
6704      * This method does nothing for a {@code null} input array.
6705      *
6706      * @param array
6707      *            the array to reverse, may be {@code null}
6708      * @param startIndexInclusive
6709      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6710      *            change.
6711      * @param endIndexExclusive
6712      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6713      *            change. Overvalue (&gt;array.length) is demoted to array length.
6714      * @since 3.2
6715      */
6716     public static void reverse(final float[] array, final int startIndexInclusive, final int endIndexExclusive) {
6717         if (array == null) {
6718             return;
6719         }
6720         int i = Math.max(startIndexInclusive, 0);
6721         int j = Math.min(array.length, endIndexExclusive) - 1;
6722         float tmp;
6723         while (j > i) {
6724             tmp = array[j];
6725             array[j] = array[i];
6726             array[i] = tmp;
6727             j--;
6728             i++;
6729         }
6730     }
6731 
6732     /**
6733      * <p>Reverses the order of the given array.
6734      *
6735      * <p>This method does nothing for a {@code null} input array.
6736      *
6737      * @param array  the array to reverse, may be {@code null}
6738      */
6739     public static void reverse(final int[] array) {
6740         if (array == null) {
6741             return;
6742         }
6743         reverse(array, 0, array.length);
6744     }
6745 
6746     /**
6747      * <p>
6748      * Reverses the order of the given array in the given range.
6749      *
6750      * <p>
6751      * This method does nothing for a {@code null} input array.
6752      *
6753      * @param array
6754      *            the array to reverse, may be {@code null}
6755      * @param startIndexInclusive
6756      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6757      *            change.
6758      * @param endIndexExclusive
6759      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6760      *            change. Overvalue (&gt;array.length) is demoted to array length.
6761      * @since 3.2
6762      */
6763     public static void reverse(final int[] array, final int startIndexInclusive, final int endIndexExclusive) {
6764         if (array == null) {
6765             return;
6766         }
6767         int i = Math.max(startIndexInclusive, 0);
6768         int j = Math.min(array.length, endIndexExclusive) - 1;
6769         int tmp;
6770         while (j > i) {
6771             tmp = array[j];
6772             array[j] = array[i];
6773             array[i] = tmp;
6774             j--;
6775             i++;
6776         }
6777     }
6778 
6779     /**
6780      * <p>Reverses the order of the given array.
6781      *
6782      * <p>This method does nothing for a {@code null} input array.
6783      *
6784      * @param array  the array to reverse, may be {@code null}
6785      */
6786     public static void reverse(final long[] array) {
6787         if (array == null) {
6788             return;
6789         }
6790         reverse(array, 0, array.length);
6791     }
6792 
6793     /**
6794      * <p>
6795      * Reverses the order of the given array in the given range.
6796      *
6797      * <p>
6798      * This method does nothing for a {@code null} input array.
6799      *
6800      * @param array
6801      *            the array to reverse, may be {@code null}
6802      * @param startIndexInclusive
6803      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6804      *            change.
6805      * @param endIndexExclusive
6806      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6807      *            change. Overvalue (&gt;array.length) is demoted to array length.
6808      * @since 3.2
6809      */
6810     public static void reverse(final long[] array, final int startIndexInclusive, final int endIndexExclusive) {
6811         if (array == null) {
6812             return;
6813         }
6814         int i = Math.max(startIndexInclusive, 0);
6815         int j = Math.min(array.length, endIndexExclusive) - 1;
6816         long tmp;
6817         while (j > i) {
6818             tmp = array[j];
6819             array[j] = array[i];
6820             array[i] = tmp;
6821             j--;
6822             i++;
6823         }
6824     }
6825 
6826     /**
6827      * <p>Reverses the order of the given array.
6828      *
6829      * <p>There is no special handling for multi-dimensional arrays.
6830      *
6831      * <p>This method does nothing for a {@code null} input array.
6832      *
6833      * @param array  the array to reverse, may be {@code null}
6834      */
6835     public static void reverse(final Object[] array) {
6836         if (array == null) {
6837             return;
6838         }
6839         reverse(array, 0, array.length);
6840     }
6841 
6842     /**
6843      * <p>
6844      * Reverses the order of the given array in the given range.
6845      *
6846      * <p>
6847      * This method does nothing for a {@code null} input array.
6848      *
6849      * @param array
6850      *            the array to reverse, may be {@code null}
6851      * @param startIndexInclusive
6852      *            the starting index. Under value (&lt;0) is promoted to 0, over value (&gt;array.length) results in no
6853      *            change.
6854      * @param endIndexExclusive
6855      *            elements up to endIndex-1 are reversed in the array. Under value (&lt; start index) results in no
6856      *            change. Over value (&gt;array.length) is demoted to array length.
6857      * @since 3.2
6858      */
6859     public static void reverse(final Object[] array, final int startIndexInclusive, final int endIndexExclusive) {
6860         if (array == null) {
6861             return;
6862         }
6863         int i = Math.max(startIndexInclusive, 0);
6864         int j = Math.min(array.length, endIndexExclusive) - 1;
6865         Object tmp;
6866         while (j > i) {
6867             tmp = array[j];
6868             array[j] = array[i];
6869             array[i] = tmp;
6870             j--;
6871             i++;
6872         }
6873     }
6874 
6875     /**
6876      * <p>Reverses the order of the given array.
6877      *
6878      * <p>This method does nothing for a {@code null} input array.
6879      *
6880      * @param array  the array to reverse, may be {@code null}
6881      */
6882     public static void reverse(final short[] array) {
6883         if (array == null) {
6884             return;
6885         }
6886         reverse(array, 0, array.length);
6887     }
6888 
6889     /**
6890      * <p>
6891      * Reverses the order of the given array in the given range.
6892      *
6893      * <p>
6894      * This method does nothing for a {@code null} input array.
6895      *
6896      * @param array
6897      *            the array to reverse, may be {@code null}
6898      * @param startIndexInclusive
6899      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6900      *            change.
6901      * @param endIndexExclusive
6902      *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
6903      *            change. Overvalue (&gt;array.length) is demoted to array length.
6904      * @since 3.2
6905      */
6906     public static void reverse(final short[] array, final int startIndexInclusive, final int endIndexExclusive) {
6907         if (array == null) {
6908             return;
6909         }
6910         int i = Math.max(startIndexInclusive, 0);
6911         int j = Math.min(array.length, endIndexExclusive) - 1;
6912         short tmp;
6913         while (j > i) {
6914             tmp = array[j];
6915             array[j] = array[i];
6916             array[i] = tmp;
6917             j--;
6918             i++;
6919         }
6920     }
6921 
6922     /**
6923      * Shifts the order of the given boolean array.
6924      *
6925      * <p>There is no special handling for multi-dimensional arrays. This method
6926      * does nothing for {@code null} or empty input arrays.</p>
6927      *
6928      * @param array  the array to shift, may be {@code null}
6929      * @param offset
6930      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
6931      *          rotate, than the effective offset is modulo the number of elements to rotate.
6932      * @since 3.5
6933      */
6934     public static void shift(final boolean[] array, final int offset) {
6935         if (array == null) {
6936             return;
6937         }
6938         shift(array, 0, array.length, offset);
6939     }
6940 
6941     /**
6942      * Shifts the order of a series of elements in the given boolean array.
6943      *
6944      * <p>There is no special handling for multi-dimensional arrays. This method
6945      * does nothing for {@code null} or empty input arrays.</p>
6946      *
6947      * @param array
6948      *            the array to shift, may be {@code null}
6949      * @param startIndexInclusive
6950      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
6951      *            change.
6952      * @param endIndexExclusive
6953      *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
6954      *            change. Overvalue (&gt;array.length) is demoted to array length.
6955      * @param offset
6956      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
6957      *          rotate, than the effective offset is modulo the number of elements to rotate.
6958      * @since 3.5
6959      */
6960     public static void shift(final boolean[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
6961         if (array == null) {
6962             return;
6963         }
6964         if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
6965             return;
6966         }
6967         if (startIndexInclusive < 0) {
6968             startIndexInclusive = 0;
6969         }
6970         if (endIndexExclusive >= array.length) {
6971             endIndexExclusive = array.length;
6972         }
6973         int n = endIndexExclusive - startIndexInclusive;
6974         if (n <= 1) {
6975             return;
6976         }
6977         offset %= n;
6978         if (offset < 0) {
6979             offset += n;
6980         }
6981         // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
6982         // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
6983         while (n > 1 && offset > 0) {
6984             final int n_offset = n - offset;
6985 
6986             if (offset > n_offset) {
6987                 swap(array, startIndexInclusive, startIndexInclusive + n - n_offset,  n_offset);
6988                 n = offset;
6989                 offset -= n_offset;
6990             } else if (offset < n_offset) {
6991                 swap(array, startIndexInclusive, startIndexInclusive + n_offset,  offset);
6992                 startIndexInclusive += offset;
6993                 n = n_offset;
6994             } else {
6995                 swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
6996                 break;
6997             }
6998         }
6999     }
7000 
7001     /**
7002      * Shifts the order of the given byte array.
7003      *
7004      * <p>There is no special handling for multi-dimensional arrays. This method
7005      * does nothing for {@code null} or empty input arrays.</p>
7006      *
7007      * @param array  the array to shift, may be {@code null}
7008      * @param offset
7009      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7010      *          rotate, than the effective offset is modulo the number of elements to rotate.
7011      * @since 3.5
7012      */
7013     public static void shift(final byte[] array, final int offset) {
7014         if (array == null) {
7015             return;
7016         }
7017         shift(array, 0, array.length, offset);
7018     }
7019 
7020     /**
7021      * Shifts the order of a series of elements in the given byte array.
7022      *
7023      * <p>There is no special handling for multi-dimensional arrays. This method
7024      * does nothing for {@code null} or empty input arrays.</p>
7025      *
7026      * @param array
7027      *            the array to shift, may be {@code null}
7028      * @param startIndexInclusive
7029      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7030      *            change.
7031      * @param endIndexExclusive
7032      *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7033      *            change. Overvalue (&gt;array.length) is demoted to array length.
7034      * @param offset
7035      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7036      *          rotate, than the effective offset is modulo the number of elements to rotate.
7037      * @since 3.5
7038      */
7039     public static void shift(final byte[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7040         if (array == null) {
7041             return;
7042         }
7043         if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7044             return;
7045         }
7046         if (startIndexInclusive < 0) {
7047             startIndexInclusive = 0;
7048         }
7049         if (endIndexExclusive >= array.length) {
7050             endIndexExclusive = array.length;
7051         }
7052         int n = endIndexExclusive - startIndexInclusive;
7053         if (n <= 1) {
7054             return;
7055         }
7056         offset %= n;
7057         if (offset < 0) {
7058             offset += n;
7059         }
7060         // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7061         // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7062         while (n > 1 && offset > 0) {
7063             final int n_offset = n - offset;
7064 
7065             if (offset > n_offset) {
7066                 swap(array, startIndexInclusive, startIndexInclusive + n - n_offset,  n_offset);
7067                 n = offset;
7068                 offset -= n_offset;
7069             } else if (offset < n_offset) {
7070                 swap(array, startIndexInclusive, startIndexInclusive + n_offset,  offset);
7071                 startIndexInclusive += offset;
7072                 n = n_offset;
7073             } else {
7074                 swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
7075                 break;
7076             }
7077         }
7078     }
7079 
7080     /**
7081      * Shifts the order of the given char array.
7082      *
7083      * <p>There is no special handling for multi-dimensional arrays. This method
7084      * does nothing for {@code null} or empty input arrays.</p>
7085      *
7086      * @param array  the array to shift, may be {@code null}
7087      * @param offset
7088      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7089      *          rotate, than the effective offset is modulo the number of elements to rotate.
7090      * @since 3.5
7091      */
7092     public static void shift(final char[] array, final int offset) {
7093         if (array == null) {
7094             return;
7095         }
7096         shift(array, 0, array.length, offset);
7097     }
7098 
7099     /**
7100      * Shifts the order of a series of elements in the given char array.
7101      *
7102      * <p>There is no special handling for multi-dimensional arrays. This method
7103      * does nothing for {@code null} or empty input arrays.</p>
7104      *
7105      * @param array
7106      *            the array to shift, may be {@code null}
7107      * @param startIndexInclusive
7108      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7109      *            change.
7110      * @param endIndexExclusive
7111      *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7112      *            change. Overvalue (&gt;array.length) is demoted to array length.
7113      * @param offset
7114      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7115      *          rotate, than the effective offset is modulo the number of elements to rotate.
7116      * @since 3.5
7117      */
7118     public static void shift(final char[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7119         if (array == null) {
7120             return;
7121         }
7122         if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7123             return;
7124         }
7125         if (startIndexInclusive < 0) {
7126             startIndexInclusive = 0;
7127         }
7128         if (endIndexExclusive >= array.length) {
7129             endIndexExclusive = array.length;
7130         }
7131         int n = endIndexExclusive - startIndexInclusive;
7132         if (n <= 1) {
7133             return;
7134         }
7135         offset %= n;
7136         if (offset < 0) {
7137             offset += n;
7138         }
7139         // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7140         // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7141         while (n > 1 && offset > 0) {
7142             final int n_offset = n - offset;
7143 
7144             if (offset > n_offset) {
7145                 swap(array, startIndexInclusive, startIndexInclusive + n - n_offset,  n_offset);
7146                 n = offset;
7147                 offset -= n_offset;
7148             } else if (offset < n_offset) {
7149                 swap(array, startIndexInclusive, startIndexInclusive + n_offset,  offset);
7150                 startIndexInclusive += offset;
7151                 n = n_offset;
7152             } else {
7153                 swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
7154                 break;
7155             }
7156         }
7157     }
7158 
7159     /**
7160      * Shifts the order of the given double array.
7161      *
7162      * <p>There is no special handling for multi-dimensional arrays. This method
7163      * does nothing for {@code null} or empty input arrays.</p>
7164      *
7165      * @param array  the array to shift, may be {@code null}
7166      * @param offset
7167      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7168      *          rotate, than the effective offset is modulo the number of elements to rotate.
7169      * @since 3.5
7170      */
7171     public static void shift(final double[] array, final int offset) {
7172         if (array == null) {
7173             return;
7174         }
7175         shift(array, 0, array.length, offset);
7176     }
7177 
7178     /**
7179      * Shifts the order of a series of elements in the given double array.
7180      *
7181      * <p>There is no special handling for multi-dimensional arrays. This method
7182      * does nothing for {@code null} or empty input arrays.</p>
7183      *
7184      * @param array
7185      *            the array to shift, may be {@code null}
7186      * @param startIndexInclusive
7187      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7188      *            change.
7189      * @param endIndexExclusive
7190      *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7191      *            change. Overvalue (&gt;array.length) is demoted to array length.
7192      * @param offset
7193      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7194      *          rotate, than the effective offset is modulo the number of elements to rotate.
7195      * @since 3.5
7196      */
7197     public static void shift(final double[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7198         if (array == null) {
7199             return;
7200         }
7201         if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7202             return;
7203         }
7204         if (startIndexInclusive < 0) {
7205             startIndexInclusive = 0;
7206         }
7207         if (endIndexExclusive >= array.length) {
7208             endIndexExclusive = array.length;
7209         }
7210         int n = endIndexExclusive - startIndexInclusive;
7211         if (n <= 1) {
7212             return;
7213         }
7214         offset %= n;
7215         if (offset < 0) {
7216             offset += n;
7217         }
7218         // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7219         // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7220         while (n > 1 && offset > 0) {
7221             final int n_offset = n - offset;
7222 
7223             if (offset > n_offset) {
7224                 swap(array, startIndexInclusive, startIndexInclusive + n - n_offset,  n_offset);
7225                 n = offset;
7226                 offset -= n_offset;
7227             } else if (offset < n_offset) {
7228                 swap(array, startIndexInclusive, startIndexInclusive + n_offset,  offset);
7229                 startIndexInclusive += offset;
7230                 n = n_offset;
7231             } else {
7232                 swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
7233                 break;
7234             }
7235         }
7236     }
7237 
7238     /**
7239      * Shifts the order of the given float array.
7240      *
7241      * <p>There is no special handling for multi-dimensional arrays. This method
7242      * does nothing for {@code null} or empty input arrays.</p>
7243      *
7244      * @param array  the array to shift, may be {@code null}
7245      * @param offset
7246      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7247      *          rotate, than the effective offset is modulo the number of elements to rotate.
7248      * @since 3.5
7249      */
7250     public static void shift(final float[] array, final int offset) {
7251         if (array == null) {
7252             return;
7253         }
7254         shift(array, 0, array.length, offset);
7255     }
7256 
7257     /**
7258      * Shifts the order of a series of elements in the given float array.
7259      *
7260      * <p>There is no special handling for multi-dimensional arrays. This method
7261      * does nothing for {@code null} or empty input arrays.</p>
7262      *
7263      * @param array
7264      *            the array to shift, may be {@code null}
7265      * @param startIndexInclusive
7266      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7267      *            change.
7268      * @param endIndexExclusive
7269      *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7270      *            change. Overvalue (&gt;array.length) is demoted to array length.
7271      * @param offset
7272      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7273      *          rotate, than the effective offset is modulo the number of elements to rotate.
7274      * @since 3.5
7275      */
7276     public static void shift(final float[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7277         if (array == null) {
7278             return;
7279         }
7280         if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
7281             return;
7282         }
7283         if (startIndexInclusive < 0) {
7284             startIndexInclusive = 0;
7285         }
7286         if (endIndexExclusive >= array.length) {
7287             endIndexExclusive = array.length;
7288         }
7289         int n = endIndexExclusive - startIndexInclusive;
7290         if (n <= 1) {
7291             return;
7292         }
7293         offset %= n;
7294         if (offset < 0) {
7295             offset += n;
7296         }
7297         // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
7298         // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
7299         while (n > 1 && offset > 0) {
7300             final int n_offset = n - offset;
7301 
7302             if (offset > n_offset) {
7303                 swap(array, startIndexInclusive, startIndexInclusive + n - n_offset,  n_offset);
7304                 n = offset;
7305                 offset -= n_offset;
7306             } else if (offset < n_offset) {
7307                 swap(array, startIndexInclusive, startIndexInclusive + n_offset,  offset);
7308                 startIndexInclusive += offset;
7309                 n = n_offset;
7310             } else {
7311                 swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
7312                 break;
7313             }
7314         }
7315     }
7316 
7317     /**
7318      * Shifts the order of the given int array.
7319      *
7320      * <p>There is no special handling for multi-dimensional arrays. This method
7321      * does nothing for {@code null} or empty input arrays.</p>
7322      *
7323      * @param array  the array to shift, may be {@code null}
7324      * @param offset
7325      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7326      *          rotate, than the effective offset is modulo the number of elements to rotate.
7327      * @since 3.5
7328      */
7329     public static void shift(final int[] array, final int offset) {
7330         if (array == null) {
7331             return;
7332         }
7333         shift(array, 0, array.length, offset);
7334     }
7335 
7336     /**
7337      * Shifts the order of a series of elements in the given int array.
7338      *
7339      * <p>There is no special handling for multi-dimensional arrays. This method
7340      * does nothing for {@code null} or empty input arrays.</p>
7341      *
7342      * @param array
7343      *            the array to shift, may be {@code null}
7344      * @param startIndexInclusive
7345      *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
7346      *            change.
7347      * @param endIndexExclusive
7348      *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
7349      *            change. Overvalue (&gt;array.length) is demoted to array length.
7350      * @param offset
7351      *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
7352      *          rotate, than the effective offset is modulo the number of elements to rotate.
7353      * @since 3.5
7354      */
7355     public static void shift(final int[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
7356         if (array == null) {
7357             return;
7358         }
7359         if (startIndexInclusive >= array.length - 1 || endIndexExclusive <=