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