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