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