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