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