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