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 1553927 2013-12-28 21:17:57Z 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
4284     * (index < 0 || index > array.length).
4285     * @throws IllegalArgumentException if both array and element are null
4286     */
4287    public static <T> T[] add(final T[] array, final int index, final T element) {
4288        Class<?> clss = null;
4289        if (array != null) {
4290            clss = array.getClass().getComponentType();
4291        } else if (element != null) {
4292            clss = element.getClass();
4293        } else {
4294            throw new IllegalArgumentException("Array and element cannot both be null");
4295        }
4296        @SuppressWarnings("unchecked") // the add method creates an array of type clss, which is type T
4297        final T[] newArray = (T[]) add(array, index, element, clss);
4298        return newArray;
4299    }
4300
4301    /**
4302     * <p>Inserts the specified element at the specified position in the array.
4303     * Shifts the element currently at that position (if any) and any subsequent
4304     * elements to the right (adds one to their indices).</p>
4305     *
4306     * <p>This method returns a new array with the same elements of the input
4307     * array plus the given element on the specified position. The component
4308     * type of the returned array is always the same as that of the input
4309     * array.</p>
4310     *
4311     * <p>If the input array is {@code null}, a new one element array is returned
4312     *  whose component type is the same as the element.</p>
4313     *
4314     * <pre>
4315     * ArrayUtils.add(null, 0, true)          = [true]
4316     * ArrayUtils.add([true], 0, false)       = [false, true]
4317     * ArrayUtils.add([false], 1, true)       = [false, true]
4318     * ArrayUtils.add([true, false], 1, true) = [true, true, false]
4319     * </pre>
4320     *
4321     * @param array  the array to add the element to, may be {@code null}
4322     * @param index  the position of the new object
4323     * @param element  the object to add
4324     * @return A new array containing the existing elements and the new element
4325     * @throws IndexOutOfBoundsException if the index is out of range
4326     * (index < 0 || index > array.length).
4327     */
4328    public static boolean[] add(final boolean[] array, final int index, final boolean element) {
4329        return (boolean[]) add(array, index, Boolean.valueOf(element), Boolean.TYPE);
4330    }
4331
4332    /**
4333     * <p>Inserts the specified element at the specified position in the array.
4334     * Shifts the element currently at that position (if any) and any subsequent
4335     * elements to the right (adds one to their indices).</p>
4336     *
4337     * <p>This method returns a new array with the same elements of the input
4338     * array plus the given element on the specified position. The component
4339     * type of the returned array is always the same as that of the input
4340     * array.</p>
4341     *
4342     * <p>If the input array is {@code null}, a new one element array is returned
4343     *  whose component type is the same as the element.</p>
4344     *
4345     * <pre>
4346     * ArrayUtils.add(null, 0, 'a')            = ['a']
4347     * ArrayUtils.add(['a'], 0, 'b')           = ['b', 'a']
4348     * ArrayUtils.add(['a', 'b'], 0, 'c')      = ['c', 'a', 'b']
4349     * ArrayUtils.add(['a', 'b'], 1, 'k')      = ['a', 'k', 'b']
4350     * ArrayUtils.add(['a', 'b', 'c'], 1, 't') = ['a', 't', 'b', 'c']
4351     * </pre>
4352     *
4353     * @param array  the array to add the element to, may be {@code null}
4354     * @param index  the position of the new object
4355     * @param element  the object to add
4356     * @return A new array containing the existing elements and the new element
4357     * @throws IndexOutOfBoundsException if the index is out of range
4358     * (index < 0 || index > array.length).
4359     */
4360    public static char[] add(final char[] array, final int index, final char element) {
4361        return (char[]) add(array, index, Character.valueOf(element), Character.TYPE);
4362    }
4363
4364    /**
4365     * <p>Inserts the specified element at the specified position in the array.
4366     * Shifts the element currently at that position (if any) and any subsequent
4367     * elements to the right (adds one to their indices).</p>
4368     *
4369     * <p>This method returns a new array with the same elements of the input
4370     * array plus the given element on the specified position. The component
4371     * type of the returned array is always the same as that of the input
4372     * array.</p>
4373     *
4374     * <p>If the input array is {@code null}, a new one element array is returned
4375     *  whose component type is the same as the element.</p>
4376     *
4377     * <pre>
4378     * ArrayUtils.add([1], 0, 2)         = [2, 1]
4379     * ArrayUtils.add([2, 6], 2, 3)      = [2, 6, 3]
4380     * ArrayUtils.add([2, 6], 0, 1)      = [1, 2, 6]
4381     * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
4382     * </pre>
4383     *
4384     * @param array  the array to add the element to, may be {@code null}
4385     * @param index  the position of the new object
4386     * @param element  the object to add
4387     * @return A new array containing the existing elements and the new element
4388     * @throws IndexOutOfBoundsException if the index is out of range
4389     * (index < 0 || index > array.length).
4390     */
4391    public static byte[] add(final byte[] array, final int index, final byte element) {
4392        return (byte[]) add(array, index, Byte.valueOf(element), Byte.TYPE);
4393    }
4394
4395    /**
4396     * <p>Inserts the specified element at the specified position in the array.
4397     * Shifts the element currently at that position (if any) and any subsequent
4398     * elements to the right (adds one to their indices).</p>
4399     *
4400     * <p>This method returns a new array with the same elements of the input
4401     * array plus the given element on the specified position. The component
4402     * type of the returned array is always the same as that of the input
4403     * array.</p>
4404     *
4405     * <p>If the input array is {@code null}, a new one element array is returned
4406     *  whose component type is the same as the element.</p>
4407     *
4408     * <pre>
4409     * ArrayUtils.add([1], 0, 2)         = [2, 1]
4410     * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
4411     * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
4412     * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
4413     * </pre>
4414     *
4415     * @param array  the array to add the element to, may be {@code null}
4416     * @param index  the position of the new object
4417     * @param element  the object to add
4418     * @return A new array containing the existing elements and the new element
4419     * @throws IndexOutOfBoundsException if the index is out of range
4420     * (index < 0 || index > array.length).
4421     */
4422    public static short[] add(final short[] array, final int index, final short element) {
4423        return (short[]) add(array, index, Short.valueOf(element), Short.TYPE);
4424    }
4425
4426    /**
4427     * <p>Inserts the specified element at the specified position in the array.
4428     * Shifts the element currently at that position (if any) and any subsequent
4429     * elements to the right (adds one to their indices).</p>
4430     *
4431     * <p>This method returns a new array with the same elements of the input
4432     * array plus the given element on the specified position. The component
4433     * type of the returned array is always the same as that of the input
4434     * array.</p>
4435     *
4436     * <p>If the input array is {@code null}, a new one element array is returned
4437     *  whose component type is the same as the element.</p>
4438     *
4439     * <pre>
4440     * ArrayUtils.add([1], 0, 2)         = [2, 1]
4441     * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
4442     * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
4443     * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
4444     * </pre>
4445     *
4446     * @param array  the array to add the element to, may be {@code null}
4447     * @param index  the position of the new object
4448     * @param element  the object to add
4449     * @return A new array containing the existing elements and the new element
4450     * @throws IndexOutOfBoundsException if the index is out of range
4451     * (index < 0 || index > array.length).
4452     */
4453    public static int[] add(final int[] array, final int index, final int element) {
4454        return (int[]) add(array, index, Integer.valueOf(element), Integer.TYPE);
4455    }
4456
4457    /**
4458     * <p>Inserts the specified element at the specified position in the array.
4459     * Shifts the element currently at that position (if any) and any subsequent
4460     * elements to the right (adds one to their indices).</p>
4461     *
4462     * <p>This method returns a new array with the same elements of the input
4463     * array plus the given element on the specified position. The component
4464     * type of the returned array is always the same as that of the input
4465     * array.</p>
4466     *
4467     * <p>If the input array is {@code null}, a new one element array is returned
4468     *  whose component type is the same as the element.</p>
4469     *
4470     * <pre>
4471     * ArrayUtils.add([1L], 0, 2L)           = [2L, 1L]
4472     * ArrayUtils.add([2L, 6L], 2, 10L)      = [2L, 6L, 10L]
4473     * ArrayUtils.add([2L, 6L], 0, -4L)      = [-4L, 2L, 6L]
4474     * ArrayUtils.add([2L, 6L, 3L], 2, 1L)   = [2L, 6L, 1L, 3L]
4475     * </pre>
4476     *
4477     * @param array  the array to add the element to, may be {@code null}
4478     * @param index  the position of the new object
4479     * @param element  the object to add
4480     * @return A new array containing the existing elements and the new element
4481     * @throws IndexOutOfBoundsException if the index is out of range
4482     * (index < 0 || index > array.length).
4483     */
4484    public static long[] add(final long[] array, final int index, final long element) {
4485        return (long[]) add(array, index, Long.valueOf(element), Long.TYPE);
4486    }
4487
4488    /**
4489     * <p>Inserts the specified element at the specified position in the array.
4490     * Shifts the element currently at that position (if any) and any subsequent
4491     * elements to the right (adds one to their indices).</p>
4492     *
4493     * <p>This method returns a new array with the same elements of the input
4494     * array plus the given element on the specified position. The component
4495     * type of the returned array is always the same as that of the input
4496     * array.</p>
4497     *
4498     * <p>If the input array is {@code null}, a new one element array is returned
4499     *  whose component type is the same as the element.</p>
4500     *
4501     * <pre>
4502     * ArrayUtils.add([1.1f], 0, 2.2f)               = [2.2f, 1.1f]
4503     * ArrayUtils.add([2.3f, 6.4f], 2, 10.5f)        = [2.3f, 6.4f, 10.5f]
4504     * ArrayUtils.add([2.6f, 6.7f], 0, -4.8f)        = [-4.8f, 2.6f, 6.7f]
4505     * ArrayUtils.add([2.9f, 6.0f, 0.3f], 2, 1.0f)   = [2.9f, 6.0f, 1.0f, 0.3f]
4506     * </pre>
4507     *
4508     * @param array  the array to add the element to, may be {@code null}
4509     * @param index  the position of the new object
4510     * @param element  the object to add
4511     * @return A new array containing the existing elements and the new element
4512     * @throws IndexOutOfBoundsException if the index is out of range
4513     * (index < 0 || index > array.length).
4514     */
4515    public static float[] add(final float[] array, final int index, final float element) {
4516        return (float[]) add(array, index, Float.valueOf(element), Float.TYPE);
4517    }
4518
4519    /**
4520     * <p>Inserts the specified element at the specified position in the array.
4521     * Shifts the element currently at that position (if any) and any subsequent
4522     * elements to the right (adds one to their indices).</p>
4523     *
4524     * <p>This method returns a new array with the same elements of the input
4525     * array plus the given element on the specified position. The component
4526     * type of the returned array is always the same as that of the input
4527     * array.</p>
4528     *
4529     * <p>If the input array is {@code null}, a new one element array is returned
4530     *  whose component type is the same as the element.</p>
4531     *
4532     * <pre>
4533     * ArrayUtils.add([1.1], 0, 2.2)              = [2.2, 1.1]
4534     * ArrayUtils.add([2.3, 6.4], 2, 10.5)        = [2.3, 6.4, 10.5]
4535     * ArrayUtils.add([2.6, 6.7], 0, -4.8)        = [-4.8, 2.6, 6.7]
4536     * ArrayUtils.add([2.9, 6.0, 0.3], 2, 1.0)    = [2.9, 6.0, 1.0, 0.3]
4537     * </pre>
4538     *
4539     * @param array  the array to add the element to, may be {@code null}
4540     * @param index  the position of the new object
4541     * @param element  the object to add
4542     * @return A new array containing the existing elements and the new element
4543     * @throws IndexOutOfBoundsException if the index is out of range
4544     * (index < 0 || index > array.length).
4545     */
4546    public static double[] add(final double[] array, final int index, final double element) {
4547        return (double[]) add(array, index, Double.valueOf(element), Double.TYPE);
4548    }
4549
4550    /**
4551     * Underlying implementation of add(array, index, element) methods.
4552     * The last parameter is the class, which may not equal element.getClass
4553     * for primitives.
4554     *
4555     * @param array  the array to add the element to, may be {@code null}
4556     * @param index  the position of the new object
4557     * @param element  the object to add
4558     * @param clss the type of the element being added
4559     * @return A new array containing the existing elements and the new element
4560     */
4561    private static Object add(final Object array, final int index, final Object element, final Class<?> clss) {
4562        if (array == null) {
4563            if (index != 0) {
4564                throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
4565            }
4566            final Object joinedArray = Array.newInstance(clss, 1);
4567            Array.set(joinedArray, 0, element);
4568            return joinedArray;
4569        }
4570        final int length = Array.getLength(array);
4571        if (index > length || index < 0) {
4572            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
4573        }
4574        final Object result = Array.newInstance(clss, length + 1);
4575        System.arraycopy(array, 0, result, 0, index);
4576        Array.set(result, index, element);
4577        if (index < length) {
4578            System.arraycopy(array, index, result, index + 1, length - index);
4579        }
4580        return result;
4581    }
4582
4583    /**
4584     * <p>Removes the element at the specified position from the specified array.
4585     * All subsequent elements are shifted to the left (subtracts one from
4586     * their indices).</p>
4587     *
4588     * <p>This method returns a new array with the same elements of the input
4589     * array except the element on the specified position. The component
4590     * type of the returned array is always the same as that of the input
4591     * array.</p>
4592     *
4593     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4594     * will be thrown, because in that case no valid index can be specified.</p>
4595     *
4596     * <pre>
4597     * ArrayUtils.remove(["a"], 0)           = []
4598     * ArrayUtils.remove(["a", "b"], 0)      = ["b"]
4599     * ArrayUtils.remove(["a", "b"], 1)      = ["a"]
4600     * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"]
4601     * </pre>
4602     *
4603     * @param <T> the component type of the array
4604     * @param array  the array to remove the element from, may not be {@code null}
4605     * @param index  the position of the element to be removed
4606     * @return A new array containing the existing elements except the element
4607     *         at the specified position.
4608     * @throws IndexOutOfBoundsException if the index is out of range
4609     * (index < 0 || index >= array.length), or if the array is {@code null}.
4610     * @since 2.1
4611     */
4612    @SuppressWarnings("unchecked") // remove() always creates an array of the same type as its input
4613    public static <T> T[] remove(final T[] array, final int index) {
4614        return (T[]) remove((Object) array, index);
4615    }
4616
4617    /**
4618     * <p>Removes the first occurrence of the specified element from the
4619     * specified array. All subsequent elements are shifted to the left
4620     * (subtracts one from their indices). If the array doesn't contains
4621     * such an element, no elements are removed from the array.</p>
4622     *
4623     * <p>This method returns a new array with the same elements of the input
4624     * array except the first occurrence of the specified element. The component
4625     * type of the returned array is always the same as that of the input
4626     * array.</p>
4627     *
4628     * <pre>
4629     * ArrayUtils.removeElement(null, "a")            = null
4630     * ArrayUtils.removeElement([], "a")              = []
4631     * ArrayUtils.removeElement(["a"], "b")           = ["a"]
4632     * ArrayUtils.removeElement(["a", "b"], "a")      = ["b"]
4633     * ArrayUtils.removeElement(["a", "b", "a"], "a") = ["b", "a"]
4634     * </pre>
4635     *
4636     * @param <T> the component type of the array
4637     * @param array  the array to remove the element from, may be {@code null}
4638     * @param element  the element to be removed
4639     * @return A new array containing the existing elements except the first
4640     *         occurrence of the specified element.
4641     * @since 2.1
4642     */
4643    public static <T> T[] removeElement(final T[] array, final Object element) {
4644        final int index = indexOf(array, element);
4645        if (index == INDEX_NOT_FOUND) {
4646            return clone(array);
4647        }
4648        return remove(array, index);
4649    }
4650
4651    /**
4652     * <p>Removes the element at the specified position from the specified array.
4653     * All subsequent elements are shifted to the left (subtracts one from
4654     * their indices).</p>
4655     *
4656     * <p>This method returns a new array with the same elements of the input
4657     * array except the element on the specified position. The component
4658     * type of the returned array is always the same as that of the input
4659     * array.</p>
4660     *
4661     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4662     * will be thrown, because in that case no valid index can be specified.</p>
4663     *
4664     * <pre>
4665     * ArrayUtils.remove([true], 0)              = []
4666     * ArrayUtils.remove([true, false], 0)       = [false]
4667     * ArrayUtils.remove([true, false], 1)       = [true]
4668     * ArrayUtils.remove([true, true, false], 1) = [true, false]
4669     * </pre>
4670     *
4671     * @param array  the array to remove the element from, may not be {@code null}
4672     * @param index  the position of the element to be removed
4673     * @return A new array containing the existing elements except the element
4674     *         at the specified position.
4675     * @throws IndexOutOfBoundsException if the index is out of range
4676     * (index < 0 || index >= array.length), or if the array is {@code null}.
4677     * @since 2.1
4678     */
4679    public static boolean[] remove(final boolean[] array, final int index) {
4680        return (boolean[]) remove((Object) array, index);
4681    }
4682
4683    /**
4684     * <p>Removes the first occurrence of the specified element from the
4685     * specified array. All subsequent elements are shifted to the left
4686     * (subtracts one from their indices). If the array doesn't contains
4687     * such an element, no elements are removed from the array.</p>
4688     *
4689     * <p>This method returns a new array with the same elements of the input
4690     * array except the first occurrence of the specified element. The component
4691     * type of the returned array is always the same as that of the input
4692     * array.</p>
4693     *
4694     * <pre>
4695     * ArrayUtils.removeElement(null, true)                = null
4696     * ArrayUtils.removeElement([], true)                  = []
4697     * ArrayUtils.removeElement([true], false)             = [true]
4698     * ArrayUtils.removeElement([true, false], false)      = [true]
4699     * ArrayUtils.removeElement([true, false, true], true) = [false, true]
4700     * </pre>
4701     *
4702     * @param array  the array to remove the element from, may be {@code null}
4703     * @param element  the element to be removed
4704     * @return A new array containing the existing elements except the first
4705     *         occurrence of the specified element.
4706     * @since 2.1
4707     */
4708    public static boolean[] removeElement(final boolean[] array, final boolean element) {
4709        final int index = indexOf(array, element);
4710        if (index == INDEX_NOT_FOUND) {
4711            return clone(array);
4712        }
4713        return remove(array, index);
4714    }
4715
4716    /**
4717     * <p>Removes the element at the specified position from the specified array.
4718     * All subsequent elements are shifted to the left (subtracts one from
4719     * their indices).</p>
4720     *
4721     * <p>This method returns a new array with the same elements of the input
4722     * array except the element on the specified position. The component
4723     * type of the returned array is always the same as that of the input
4724     * array.</p>
4725     *
4726     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4727     * will be thrown, because in that case no valid index can be specified.</p>
4728     *
4729     * <pre>
4730     * ArrayUtils.remove([1], 0)          = []
4731     * ArrayUtils.remove([1, 0], 0)       = [0]
4732     * ArrayUtils.remove([1, 0], 1)       = [1]
4733     * ArrayUtils.remove([1, 0, 1], 1)    = [1, 1]
4734     * </pre>
4735     *
4736     * @param array  the array to remove the element from, may not be {@code null}
4737     * @param index  the position of the element to be removed
4738     * @return A new array containing the existing elements except the element
4739     *         at the specified position.
4740     * @throws IndexOutOfBoundsException if the index is out of range
4741     * (index < 0 || index >= array.length), or if the array is {@code null}.
4742     * @since 2.1
4743     */
4744    public static byte[] remove(final byte[] array, final int index) {
4745        return (byte[]) remove((Object) array, index);
4746    }
4747
4748    /**
4749     * <p>Removes the first occurrence of the specified element from the
4750     * specified array. All subsequent elements are shifted to the left
4751     * (subtracts one from their indices). If the array doesn't contains
4752     * such an element, no elements are removed from the array.</p>
4753     *
4754     * <p>This method returns a new array with the same elements of the input
4755     * array except the first occurrence of the specified element. The component
4756     * type of the returned array is always the same as that of the input
4757     * array.</p>
4758     *
4759     * <pre>
4760     * ArrayUtils.removeElement(null, 1)        = null
4761     * ArrayUtils.removeElement([], 1)          = []
4762     * ArrayUtils.removeElement([1], 0)         = [1]
4763     * ArrayUtils.removeElement([1, 0], 0)      = [1]
4764     * ArrayUtils.removeElement([1, 0, 1], 1)   = [0, 1]
4765     * </pre>
4766     *
4767     * @param array  the array to remove the element from, may be {@code null}
4768     * @param element  the element to be removed
4769     * @return A new array containing the existing elements except the first
4770     *         occurrence of the specified element.
4771     * @since 2.1
4772     */
4773    public static byte[] removeElement(final byte[] array, final byte element) {
4774        final int index = indexOf(array, element);
4775        if (index == INDEX_NOT_FOUND) {
4776            return clone(array);
4777        }
4778        return remove(array, index);
4779    }
4780
4781    /**
4782     * <p>Removes the element at the specified position from the specified array.
4783     * All subsequent elements are shifted to the left (subtracts one from
4784     * their indices).</p>
4785     *
4786     * <p>This method returns a new array with the same elements of the input
4787     * array except the element on the specified position. The component
4788     * type of the returned array is always the same as that of the input
4789     * array.</p>
4790     *
4791     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4792     * will be thrown, because in that case no valid index can be specified.</p>
4793     *
4794     * <pre>
4795     * ArrayUtils.remove(['a'], 0)           = []
4796     * ArrayUtils.remove(['a', 'b'], 0)      = ['b']
4797     * ArrayUtils.remove(['a', 'b'], 1)      = ['a']
4798     * ArrayUtils.remove(['a', 'b', 'c'], 1) = ['a', 'c']
4799     * </pre>
4800     *
4801     * @param array  the array to remove the element from, may not be {@code null}
4802     * @param index  the position of the element to be removed
4803     * @return A new array containing the existing elements except the element
4804     *         at the specified position.
4805     * @throws IndexOutOfBoundsException if the index is out of range
4806     * (index < 0 || index >= array.length), or if the array is {@code null}.
4807     * @since 2.1
4808     */
4809    public static char[] remove(final char[] array, final int index) {
4810        return (char[]) remove((Object) array, index);
4811    }
4812
4813    /**
4814     * <p>Removes the first occurrence of the specified element from the
4815     * specified array. All subsequent elements are shifted to the left
4816     * (subtracts one from their indices). If the array doesn't contains
4817     * such an element, no elements are removed from the array.</p>
4818     *
4819     * <p>This method returns a new array with the same elements of the input
4820     * array except the first occurrence of the specified element. The component
4821     * type of the returned array is always the same as that of the input
4822     * array.</p>
4823     *
4824     * <pre>
4825     * ArrayUtils.removeElement(null, 'a')            = null
4826     * ArrayUtils.removeElement([], 'a')              = []
4827     * ArrayUtils.removeElement(['a'], 'b')           = ['a']
4828     * ArrayUtils.removeElement(['a', 'b'], 'a')      = ['b']
4829     * ArrayUtils.removeElement(['a', 'b', 'a'], 'a') = ['b', 'a']
4830     * </pre>
4831     *
4832     * @param array  the array to remove the element from, may be {@code null}
4833     * @param element  the element to be removed
4834     * @return A new array containing the existing elements except the first
4835     *         occurrence of the specified element.
4836     * @since 2.1
4837     */
4838    public static char[] removeElement(final char[] array, final char element) {
4839        final int index = indexOf(array, element);
4840        if (index == INDEX_NOT_FOUND) {
4841            return clone(array);
4842        }
4843        return remove(array, index);
4844    }
4845
4846    /**
4847     * <p>Removes the element at the specified position from the specified array.
4848     * All subsequent elements are shifted to the left (subtracts one from
4849     * their indices).</p>
4850     *
4851     * <p>This method returns a new array with the same elements of the input
4852     * array except the element on the specified position. The component
4853     * type of the returned array is always the same as that of the input
4854     * array.</p>
4855     *
4856     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4857     * will be thrown, because in that case no valid index can be specified.</p>
4858     *
4859     * <pre>
4860     * ArrayUtils.remove([1.1], 0)           = []
4861     * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
4862     * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
4863     * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
4864     * </pre>
4865     *
4866     * @param array  the array to remove the element from, may not be {@code null}
4867     * @param index  the position of the element to be removed
4868     * @return A new array containing the existing elements except the element
4869     *         at the specified position.
4870     * @throws IndexOutOfBoundsException if the index is out of range
4871     * (index < 0 || index >= array.length), or if the array is {@code null}.
4872     * @since 2.1
4873     */
4874    public static double[] remove(final double[] array, final int index) {
4875        return (double[]) remove((Object) array, index);
4876    }
4877
4878    /**
4879     * <p>Removes the first occurrence of the specified element from the
4880     * specified array. All subsequent elements are shifted to the left
4881     * (subtracts one from their indices). If the array doesn't contains
4882     * such an element, no elements are removed from the array.</p>
4883     *
4884     * <p>This method returns a new array with the same elements of the input
4885     * array except the first occurrence of the specified element. The component
4886     * type of the returned array is always the same as that of the input
4887     * array.</p>
4888     *
4889     * <pre>
4890     * ArrayUtils.removeElement(null, 1.1)            = null
4891     * ArrayUtils.removeElement([], 1.1)              = []
4892     * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
4893     * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
4894     * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
4895     * </pre>
4896     *
4897     * @param array  the array to remove the element from, may be {@code null}
4898     * @param element  the element to be removed
4899     * @return A new array containing the existing elements except the first
4900     *         occurrence of the specified element.
4901     * @since 2.1
4902     */
4903    public static double[] removeElement(final double[] array, final double element) {
4904        final int index = indexOf(array, element);
4905        if (index == INDEX_NOT_FOUND) {
4906            return clone(array);
4907        }
4908        return remove(array, index);
4909    }
4910
4911    /**
4912     * <p>Removes the element at the specified position from the specified array.
4913     * All subsequent elements are shifted to the left (subtracts one from
4914     * their indices).</p>
4915     *
4916     * <p>This method returns a new array with the same elements of the input
4917     * array except the element on the specified position. The component
4918     * type of the returned array is always the same as that of the input
4919     * array.</p>
4920     *
4921     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4922     * will be thrown, because in that case no valid index can be specified.</p>
4923     *
4924     * <pre>
4925     * ArrayUtils.remove([1.1], 0)           = []
4926     * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
4927     * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
4928     * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
4929     * </pre>
4930     *
4931     * @param array  the array to remove the element from, may not be {@code null}
4932     * @param index  the position of the element to be removed
4933     * @return A new array containing the existing elements except the element
4934     *         at the specified position.
4935     * @throws IndexOutOfBoundsException if the index is out of range
4936     * (index < 0 || index >= array.length), or if the array is {@code null}.
4937     * @since 2.1
4938     */
4939    public static float[] remove(final float[] array, final int index) {
4940        return (float[]) remove((Object) array, index);
4941    }
4942
4943    /**
4944     * <p>Removes the first occurrence of the specified element from the
4945     * specified array. All subsequent elements are shifted to the left
4946     * (subtracts one from their indices). If the array doesn't contains
4947     * such an element, no elements are removed from the array.</p>
4948     *
4949     * <p>This method returns a new array with the same elements of the input
4950     * array except the first occurrence of the specified element. The component
4951     * type of the returned array is always the same as that of the input
4952     * array.</p>
4953     *
4954     * <pre>
4955     * ArrayUtils.removeElement(null, 1.1)            = null
4956     * ArrayUtils.removeElement([], 1.1)              = []
4957     * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
4958     * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
4959     * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
4960     * </pre>
4961     *
4962     * @param array  the array to remove the element from, may be {@code null}
4963     * @param element  the element to be removed
4964     * @return A new array containing the existing elements except the first
4965     *         occurrence of the specified element.
4966     * @since 2.1
4967     */
4968    public static float[] removeElement(final float[] array, final float element) {
4969        final int index = indexOf(array, element);
4970        if (index == INDEX_NOT_FOUND) {
4971            return clone(array);
4972        }
4973        return remove(array, index);
4974    }
4975
4976    /**
4977     * <p>Removes the element at the specified position from the specified array.
4978     * All subsequent elements are shifted to the left (subtracts one from
4979     * their indices).</p>
4980     *
4981     * <p>This method returns a new array with the same elements of the input
4982     * array except the element on the specified position. The component
4983     * type of the returned array is always the same as that of the input
4984     * array.</p>
4985     *
4986     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4987     * will be thrown, because in that case no valid index can be specified.</p>
4988     *
4989     * <pre>
4990     * ArrayUtils.remove([1], 0)         = []
4991     * ArrayUtils.remove([2, 6], 0)      = [6]
4992     * ArrayUtils.remove([2, 6], 1)      = [2]
4993     * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
4994     * </pre>
4995     *
4996     * @param array  the array to remove the element from, may not be {@code null}
4997     * @param index  the position of the element to be removed
4998     * @return A new array containing the existing elements except the element
4999     *         at the specified position.
5000     * @throws IndexOutOfBoundsException if the index is out of range
5001     * (index < 0 || index >= array.length), or if the array is {@code null}.
5002     * @since 2.1
5003     */
5004    public static int[] remove(final int[] array, final int index) {
5005        return (int[]) remove((Object) array, index);
5006    }
5007
5008    /**
5009     * <p>Removes the first occurrence of the specified element from the
5010     * specified array. All subsequent elements are shifted to the left
5011     * (subtracts one from their indices). If the array doesn't contains
5012     * such an element, no elements are removed from the array.</p>
5013     *
5014     * <p>This method returns a new array with the same elements of the input
5015     * array except the first occurrence of the specified element. The component
5016     * type of the returned array is always the same as that of the input
5017     * array.</p>
5018     *
5019     * <pre>
5020     * ArrayUtils.removeElement(null, 1)      = null
5021     * ArrayUtils.removeElement([], 1)        = []
5022     * ArrayUtils.removeElement([1], 2)       = [1]
5023     * ArrayUtils.removeElement([1, 3], 1)    = [3]
5024     * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
5025     * </pre>
5026     *
5027     * @param array  the array to remove the element from, may be {@code null}
5028     * @param element  the element to be removed
5029     * @return A new array containing the existing elements except the first
5030     *         occurrence of the specified element.
5031     * @since 2.1
5032     */
5033    public static int[] removeElement(final int[] array, final int element) {
5034        final int index = indexOf(array, element);
5035        if (index == INDEX_NOT_FOUND) {
5036            return clone(array);
5037        }
5038        return remove(array, index);
5039    }
5040
5041    /**
5042     * <p>Removes the element at the specified position from the specified array.
5043     * All subsequent elements are shifted to the left (subtracts one from
5044     * their indices).</p>
5045     *
5046     * <p>This method returns a new array with the same elements of the input
5047     * array except the element on the specified position. The component
5048     * type of the returned array is always the same as that of the input
5049     * array.</p>
5050     *
5051     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5052     * will be thrown, because in that case no valid index can be specified.</p>
5053     *
5054     * <pre>
5055     * ArrayUtils.remove([1], 0)         = []
5056     * ArrayUtils.remove([2, 6], 0)      = [6]
5057     * ArrayUtils.remove([2, 6], 1)      = [2]
5058     * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
5059     * </pre>
5060     *
5061     * @param array  the array to remove the element from, may not be {@code null}
5062     * @param index  the position of the element to be removed
5063     * @return A new array containing the existing elements except the element
5064     *         at the specified position.
5065     * @throws IndexOutOfBoundsException if the index is out of range
5066     * (index < 0 || index >= array.length), or if the array is {@code null}.
5067     * @since 2.1
5068     */
5069    public static long[] remove(final long[] array, final int index) {
5070        return (long[]) remove((Object) array, index);
5071    }
5072
5073    /**
5074     * <p>Removes the first occurrence of the specified element from the
5075     * specified array. All subsequent elements are shifted to the left
5076     * (subtracts one from their indices). If the array doesn't contains
5077     * such an element, no elements are removed from the array.</p>
5078     *
5079     * <p>This method returns a new array with the same elements of the input
5080     * array except the first occurrence of the specified element. The component
5081     * type of the returned array is always the same as that of the input
5082     * array.</p>
5083     *
5084     * <pre>
5085     * ArrayUtils.removeElement(null, 1)      = null
5086     * ArrayUtils.removeElement([], 1)        = []
5087     * ArrayUtils.removeElement([1], 2)       = [1]
5088     * ArrayUtils.removeElement([1, 3], 1)    = [3]
5089     * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
5090     * </pre>
5091     *
5092     * @param array  the array to remove the element from, may be {@code null}
5093     * @param element  the element to be removed
5094     * @return A new array containing the existing elements except the first
5095     *         occurrence of the specified element.
5096     * @since 2.1
5097     */
5098    public static long[] removeElement(final long[] array, final long element) {
5099        final int index = indexOf(array, element);
5100        if (index == INDEX_NOT_FOUND) {
5101            return clone(array);
5102        }
5103        return remove(array, index);
5104    }
5105
5106    /**
5107     * <p>Removes the element at the specified position from the specified array.
5108     * All subsequent elements are shifted to the left (subtracts one from
5109     * their indices).</p>
5110     *
5111     * <p>This method returns a new array with the same elements of the input
5112     * array except the element on the specified position. The component
5113     * type of the returned array is always the same as that of the input
5114     * array.</p>
5115     *
5116     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5117     * will be thrown, because in that case no valid index can be specified.</p>
5118     *
5119     * <pre>
5120     * ArrayUtils.remove([1], 0)         = []
5121     * ArrayUtils.remove([2, 6], 0)      = [6]
5122     * ArrayUtils.remove([2, 6], 1)      = [2]
5123     * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
5124     * </pre>
5125     *
5126     * @param array  the array to remove the element from, may not be {@code null}
5127     * @param index  the position of the element to be removed
5128     * @return A new array containing the existing elements except the element
5129     *         at the specified position.
5130     * @throws IndexOutOfBoundsException if the index is out of range
5131     * (index < 0 || index >= array.length), or if the array is {@code null}.
5132     * @since 2.1
5133     */
5134    public static short[] remove(final short[] array, final int index) {
5135        return (short[]) remove((Object) array, index);
5136    }
5137
5138    /**
5139     * <p>Removes the first occurrence of the specified element from the
5140     * specified array. All subsequent elements are shifted to the left
5141     * (subtracts one from their indices). If the array doesn't contains
5142     * such an element, no elements are removed from the array.</p>
5143     *
5144     * <p>This method returns a new array with the same elements of the input
5145     * array except the first occurrence of the specified element. The component
5146     * type of the returned array is always the same as that of the input
5147     * array.</p>
5148     *
5149     * <pre>
5150     * ArrayUtils.removeElement(null, 1)      = null
5151     * ArrayUtils.removeElement([], 1)        = []
5152     * ArrayUtils.removeElement([1], 2)       = [1]
5153     * ArrayUtils.removeElement([1, 3], 1)    = [3]
5154     * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
5155     * </pre>
5156     *
5157     * @param array  the array to remove the element from, may be {@code null}
5158     * @param element  the element to be removed
5159     * @return A new array containing the existing elements except the first
5160     *         occurrence of the specified element.
5161     * @since 2.1
5162     */
5163    public static short[] removeElement(final short[] array, final short element) {
5164        final int index = indexOf(array, element);
5165        if (index == INDEX_NOT_FOUND) {
5166            return clone(array);
5167        }
5168        return remove(array, index);
5169    }
5170
5171    /**
5172     * <p>Removes the element at the specified position from the specified array.
5173     * All subsequent elements are shifted to the left (subtracts one from
5174     * their indices).</p>
5175     *
5176     * <p>This method returns a new array with the same elements of the input
5177     * array except the element on the specified position. The component
5178     * type of the returned array is always the same as that of the input
5179     * array.</p>
5180     *
5181     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5182     * will be thrown, because in that case no valid index can be specified.</p>
5183     *
5184     * @param array  the array to remove the element from, may not be {@code null}
5185     * @param index  the position of the element to be removed
5186     * @return A new array containing the existing elements except the element
5187     *         at the specified position.
5188     * @throws IndexOutOfBoundsException if the index is out of range
5189     * (index < 0 || index >= array.length), or if the array is {@code null}.
5190     * @since 2.1
5191     */
5192    private static Object remove(final Object array, final int index) {
5193        final int length = getLength(array);
5194        if (index < 0 || index >= length) {
5195            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
5196        }
5197
5198        final Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
5199        System.arraycopy(array, 0, result, 0, index);
5200        if (index < length - 1) {
5201            System.arraycopy(array, index + 1, result, index, length - index - 1);
5202        }
5203
5204        return result;
5205    }
5206
5207    /**
5208     * <p>Removes the elements at the specified positions from the specified array.
5209     * All remaining elements are shifted to the left.</p>
5210     *
5211     * <p>This method returns a new array with the same elements of the input
5212     * array except those at the specified positions. The component
5213     * type of the returned array is always the same as that of the input
5214     * array.</p>
5215     *
5216     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5217     * will be thrown, because in that case no valid index can be specified.</p>
5218     *
5219     * <pre>
5220     * ArrayUtils.removeAll(["a", "b", "c"], 0, 2) = ["b"]
5221     * ArrayUtils.removeAll(["a", "b", "c"], 1, 2) = ["a"]
5222     * </pre>
5223     *
5224     * @param <T> the component type of the array
5225     * @param array   the array to remove the element from, may not be {@code null}
5226     * @param indices the positions of the elements to be removed
5227     * @return A new array containing the existing elements except those
5228     *         at the specified positions.
5229     * @throws IndexOutOfBoundsException if any index is out of range
5230     * (index < 0 || index >= array.length), or if the array is {@code null}.
5231     * @since 3.0.1
5232     */
5233    @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
5234    public static <T> T[] removeAll(final T[] array, final int... indices) {
5235        return (T[]) removeAll((Object) array, clone(indices));
5236    }
5237
5238    /**
5239     * <p>Removes occurrences of specified elements, in specified quantities,
5240     * from the specified array. All subsequent elements are shifted left.
5241     * For any element-to-be-removed specified in greater quantities than
5242     * contained in the original array, no change occurs beyond the
5243     * removal of the existing matching items.</p>
5244     *
5245     * <p>This method returns a new array with the same elements of the input
5246     * array except for the earliest-encountered occurrences of the specified
5247     * elements. The component type of the returned array is always the same
5248     * as that of the input array.</p>
5249     *
5250     * <pre>
5251     * ArrayUtils.removeElements(null, "a", "b")            = null
5252     * ArrayUtils.removeElements([], "a", "b")              = []
5253     * ArrayUtils.removeElements(["a"], "b", "c")           = ["a"]
5254     * ArrayUtils.removeElements(["a", "b"], "a", "c")      = ["b"]
5255     * ArrayUtils.removeElements(["a", "b", "a"], "a")      = ["b", "a"]
5256     * ArrayUtils.removeElements(["a", "b", "a"], "a", "a") = ["b"]
5257     * </pre>
5258     *
5259     * @param <T> the component type of the array
5260     * @param array  the array to remove the element from, may be {@code null}
5261     * @param values the elements to be removed
5262     * @return A new array containing the existing elements except the
5263     *         earliest-encountered occurrences of the specified elements.
5264     * @since 3.0.1
5265     */
5266    public static <T> T[] removeElements(final T[] array, final T... values) {
5267        if (isEmpty(array) || isEmpty(values)) {
5268            return clone(array);
5269        }
5270        final HashMap<T, MutableInt> occurrences = new HashMap<T, MutableInt>(values.length);
5271        for (final T v : values) {
5272            final MutableInt count = occurrences.get(v);
5273            if (count == null) {
5274                occurrences.put(v, new MutableInt(1));
5275            } else {
5276                count.increment();
5277            }
5278        }
5279        final BitSet toRemove = new BitSet();
5280        for (final Map.Entry<T, MutableInt> e : occurrences.entrySet()) {
5281            final T v = e.getKey();
5282            int found = 0;
5283            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5284                found = indexOf(array, v, found);
5285                if (found < 0) {
5286                    break;
5287                }
5288                toRemove.set(found++);
5289            }
5290        }
5291        @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
5292        final
5293        T[] result = (T[]) removeAll(array, toRemove);
5294        return result;
5295    }
5296
5297    /**
5298     * <p>Removes the elements at the specified positions from the specified array.
5299     * All remaining elements are shifted to the left.</p>
5300     *
5301     * <p>This method returns a new array with the same elements of the input
5302     * array except those at the specified positions. The component
5303     * type of the returned array is always the same as that of the input
5304     * array.</p>
5305     *
5306     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5307     * will be thrown, because in that case no valid index can be specified.</p>
5308     *
5309     * <pre>
5310     * ArrayUtils.removeAll([1], 0)             = []
5311     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5312     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5313     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5314     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5315     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5316     * </pre>
5317     *
5318     * @param array   the array to remove the element from, may not be {@code null}
5319     * @param indices the positions of the elements to be removed
5320     * @return A new array containing the existing elements except those
5321     *         at the specified positions.
5322     * @throws IndexOutOfBoundsException if any index is out of range
5323     * (index < 0 || index >= array.length), or if the array is {@code null}.
5324     * @since 3.0.1
5325     */
5326    public static byte[] removeAll(final byte[] array, final int... indices) {
5327        return (byte[]) removeAll((Object) array, clone(indices));
5328    }
5329
5330    /**
5331     * <p>Removes occurrences of specified elements, in specified quantities,
5332     * from the specified array. All subsequent elements are shifted left.
5333     * For any element-to-be-removed specified in greater quantities than
5334     * contained in the original array, no change occurs beyond the
5335     * removal of the existing matching items.</p>
5336     *
5337     * <p>This method returns a new array with the same elements of the input
5338     * array except for the earliest-encountered occurrences of the specified
5339     * elements. The component type of the returned array is always the same
5340     * as that of the input array.</p>
5341     *
5342     * <pre>
5343     * ArrayUtils.removeElements(null, 1, 2)      = null
5344     * ArrayUtils.removeElements([], 1, 2)        = []
5345     * ArrayUtils.removeElements([1], 2, 3)       = [1]
5346     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5347     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5348     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5349     * </pre>
5350     *
5351     * @param array  the array to remove the element from, may be {@code null}
5352     * @param values the elements to be removed
5353     * @return A new array containing the existing elements except the
5354     *         earliest-encountered occurrences of the specified elements.
5355     * @since 3.0.1
5356     */
5357    public static byte[] removeElements(final byte[] array, final byte... values) {
5358        if (isEmpty(array) || isEmpty(values)) {
5359            return clone(array);
5360        }
5361        final HashMap<Byte, MutableInt> occurrences = new HashMap<Byte, MutableInt>(values.length);
5362        for (final byte v : values) {
5363            final Byte boxed = Byte.valueOf(v);
5364            final MutableInt count = occurrences.get(boxed);
5365            if (count == null) {
5366                occurrences.put(boxed, new MutableInt(1));
5367            } else {
5368                count.increment();
5369            }
5370        }
5371        final BitSet toRemove = new BitSet();
5372        for (final Map.Entry<Byte, MutableInt> e : occurrences.entrySet()) {
5373            final Byte v = e.getKey();
5374            int found = 0;
5375            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5376                found = indexOf(array, v.byteValue(), found);
5377                if (found < 0) {
5378                    break;
5379                }
5380                toRemove.set(found++);
5381            }
5382        }
5383        return (byte[]) removeAll(array, toRemove);
5384    }
5385
5386    /**
5387     * <p>Removes the elements at the specified positions from the specified array.
5388     * All remaining elements are shifted to the left.</p>
5389     *
5390     * <p>This method returns a new array with the same elements of the input
5391     * array except those at the specified positions. The component
5392     * type of the returned array is always the same as that of the input
5393     * array.</p>
5394     *
5395     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5396     * will be thrown, because in that case no valid index can be specified.</p>
5397     *
5398     * <pre>
5399     * ArrayUtils.removeAll([1], 0)             = []
5400     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5401     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5402     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5403     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5404     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5405     * </pre>
5406     *
5407     * @param array   the array to remove the element from, may not be {@code null}
5408     * @param indices the positions of the elements to be removed
5409     * @return A new array containing the existing elements except those
5410     *         at the specified positions.
5411     * @throws IndexOutOfBoundsException if any index is out of range
5412     * (index < 0 || index >= array.length), or if the array is {@code null}.
5413     * @since 3.0.1
5414     */
5415    public static short[] removeAll(final short[] array, final int... indices) {
5416        return (short[]) removeAll((Object) array, clone(indices));
5417    }
5418
5419    /**
5420     * <p>Removes occurrences of specified elements, in specified quantities,
5421     * from the specified array. All subsequent elements are shifted left.
5422     * For any element-to-be-removed specified in greater quantities than
5423     * contained in the original array, no change occurs beyond the
5424     * removal of the existing matching items.</p>
5425     *
5426     * <p>This method returns a new array with the same elements of the input
5427     * array except for the earliest-encountered occurrences of the specified
5428     * elements. The component type of the returned array is always the same
5429     * as that of the input array.</p>
5430     *
5431     * <pre>
5432     * ArrayUtils.removeElements(null, 1, 2)      = null
5433     * ArrayUtils.removeElements([], 1, 2)        = []
5434     * ArrayUtils.removeElements([1], 2, 3)       = [1]
5435     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5436     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5437     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5438     * </pre>
5439     *
5440     * @param array  the array to remove the element from, may be {@code null}
5441     * @param values the elements to be removed
5442     * @return A new array containing the existing elements except the
5443     *         earliest-encountered occurrences of the specified elements.
5444     * @since 3.0.1
5445     */
5446    public static short[] removeElements(final short[] array, final short... values) {
5447        if (isEmpty(array) || isEmpty(values)) {
5448            return clone(array);
5449        }
5450        final HashMap<Short, MutableInt> occurrences = new HashMap<Short, MutableInt>(values.length);
5451        for (final short v : values) {
5452            final Short boxed = Short.valueOf(v);
5453            final MutableInt count = occurrences.get(boxed);
5454            if (count == null) {
5455                occurrences.put(boxed, new MutableInt(1));
5456            } else {
5457                count.increment();
5458            }
5459        }
5460        final BitSet toRemove = new BitSet();
5461        for (final Map.Entry<Short, MutableInt> e : occurrences.entrySet()) {
5462            final Short v = e.getKey();
5463            int found = 0;
5464            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5465                found = indexOf(array, v.shortValue(), found);
5466                if (found < 0) {
5467                    break;
5468                }
5469                toRemove.set(found++);
5470            }
5471        }
5472        return (short[]) removeAll(array, toRemove);
5473    }
5474
5475    /**
5476     * <p>Removes the elements at the specified positions from the specified array.
5477     * All remaining elements are shifted to the left.</p>
5478     *
5479     * <p>This method returns a new array with the same elements of the input
5480     * array except those at the specified positions. The component
5481     * type of the returned array is always the same as that of the input
5482     * array.</p>
5483     *
5484     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5485     * will be thrown, because in that case no valid index can be specified.</p>
5486     *
5487     * <pre>
5488     * ArrayUtils.removeAll([1], 0)             = []
5489     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5490     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5491     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5492     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5493     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5494     * </pre>
5495     *
5496     * @param array   the array to remove the element from, may not be {@code null}
5497     * @param indices the positions of the elements to be removed
5498     * @return A new array containing the existing elements except those
5499     *         at the specified positions.
5500     * @throws IndexOutOfBoundsException if any index is out of range
5501     * (index < 0 || index >= array.length), or if the array is {@code null}.
5502     * @since 3.0.1
5503     */
5504    public static int[] removeAll(final int[] array, final int... indices) {
5505        return (int[]) removeAll((Object) array, clone(indices));
5506    }
5507
5508    /**
5509     * <p>Removes occurrences of specified elements, in specified quantities,
5510     * from the specified array. All subsequent elements are shifted left.
5511     * For any element-to-be-removed specified in greater quantities than
5512     * contained in the original array, no change occurs beyond the
5513     * removal of the existing matching items.</p>
5514     *
5515     * <p>This method returns a new array with the same elements of the input
5516     * array except for the earliest-encountered occurrences of the specified
5517     * elements. The component type of the returned array is always the same
5518     * as that of the input array.</p>
5519     *
5520     * <pre>
5521     * ArrayUtils.removeElements(null, 1, 2)      = null
5522     * ArrayUtils.removeElements([], 1, 2)        = []
5523     * ArrayUtils.removeElements([1], 2, 3)       = [1]
5524     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5525     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5526     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5527     * </pre>
5528     *
5529     * @param array  the array to remove the element from, may be {@code null}
5530     * @param values the elements to be removed
5531     * @return A new array containing the existing elements except the
5532     *         earliest-encountered occurrences of the specified elements.
5533     * @since 3.0.1
5534     */
5535    public static int[] removeElements(final int[] array, final int... values) {
5536        if (isEmpty(array) || isEmpty(values)) {
5537            return clone(array);
5538        }
5539        final HashMap<Integer, MutableInt> occurrences = new HashMap<Integer, MutableInt>(values.length);
5540        for (final int v : values) {
5541            final Integer boxed = Integer.valueOf(v);
5542            final MutableInt count = occurrences.get(boxed);
5543            if (count == null) {
5544                occurrences.put(boxed, new MutableInt(1));
5545            } else {
5546                count.increment();
5547            }
5548        }
5549        final BitSet toRemove = new BitSet();
5550        for (final Map.Entry<Integer, MutableInt> e : occurrences.entrySet()) {
5551            final Integer v = e.getKey();
5552            int found = 0;
5553            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5554                found = indexOf(array, v.intValue(), found);
5555                if (found < 0) {
5556                    break;
5557                }
5558                toRemove.set(found++);
5559            }
5560        }
5561        return (int[]) removeAll(array, toRemove);
5562    }
5563
5564    /**
5565     * <p>Removes the elements at the specified positions from the specified array.
5566     * All remaining elements are shifted to the left.</p>
5567     *
5568     * <p>This method returns a new array with the same elements of the input
5569     * array except those at the specified positions. The component
5570     * type of the returned array is always the same as that of the input
5571     * array.</p>
5572     *
5573     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5574     * will be thrown, because in that case no valid index can be specified.</p>
5575     *
5576     * <pre>
5577     * ArrayUtils.removeAll([1], 0)             = []
5578     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5579     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5580     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5581     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5582     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5583     * </pre>
5584     *
5585     * @param array   the array to remove the element from, may not be {@code null}
5586     * @param indices the positions of the elements to be removed
5587     * @return A new array containing the existing elements except those
5588     *         at the specified positions.
5589     * @throws IndexOutOfBoundsException if any index is out of range
5590     * (index < 0 || index >= array.length), or if the array is {@code null}.
5591     * @since 3.0.1
5592     */
5593    public static char[] removeAll(final char[] array, final int... indices) {
5594        return (char[]) removeAll((Object) array, clone(indices));
5595    }
5596
5597    /**
5598     * <p>Removes occurrences of specified elements, in specified quantities,
5599     * from the specified array. All subsequent elements are shifted left.
5600     * For any element-to-be-removed specified in greater quantities than
5601     * contained in the original array, no change occurs beyond the
5602     * removal of the existing matching items.</p>
5603     *
5604     * <p>This method returns a new array with the same elements of the input
5605     * array except for the earliest-encountered occurrences of the specified
5606     * elements. The component type of the returned array is always the same
5607     * as that of the input array.</p>
5608     *
5609     * <pre>
5610     * ArrayUtils.removeElements(null, 1, 2)      = null
5611     * ArrayUtils.removeElements([], 1, 2)        = []
5612     * ArrayUtils.removeElements([1], 2, 3)       = [1]
5613     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5614     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5615     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5616     * </pre>
5617     *
5618     * @param array  the array to remove the element from, may be {@code null}
5619     * @param values the elements to be removed
5620     * @return A new array containing the existing elements except the
5621     *         earliest-encountered occurrences of the specified elements.
5622     * @since 3.0.1
5623     */
5624    public static char[] removeElements(final char[] array, final char... values) {
5625        if (isEmpty(array) || isEmpty(values)) {
5626            return clone(array);
5627        }
5628        final HashMap<Character, MutableInt> occurrences = new HashMap<Character, MutableInt>(values.length);
5629        for (final char v : values) {
5630            final Character boxed = Character.valueOf(v);
5631            final MutableInt count = occurrences.get(boxed);
5632            if (count == null) {
5633                occurrences.put(boxed, new MutableInt(1));
5634            } else {
5635                count.increment();
5636            }
5637        }
5638        final BitSet toRemove = new BitSet();
5639        for (final Map.Entry<Character, MutableInt> e : occurrences.entrySet()) {
5640            final Character v = e.getKey();
5641            int found = 0;
5642            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5643                found = indexOf(array, v.charValue(), found);
5644                if (found < 0) {
5645                    break;
5646                }
5647                toRemove.set(found++);
5648            }
5649        }
5650        return (char[]) removeAll(array, toRemove);
5651    }
5652
5653    /**
5654     * <p>Removes the elements at the specified positions from the specified array.
5655     * All remaining elements are shifted to the left.</p>
5656     *
5657     * <p>This method returns a new array with the same elements of the input
5658     * array except those at the specified positions. The component
5659     * type of the returned array is always the same as that of the input
5660     * array.</p>
5661     *
5662     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5663     * will be thrown, because in that case no valid index can be specified.</p>
5664     *
5665     * <pre>
5666     * ArrayUtils.removeAll([1], 0)             = []
5667     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5668     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5669     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5670     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5671     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5672     * </pre>
5673     *
5674     * @param array   the array to remove the element from, may not be {@code null}
5675     * @param indices the positions of the elements to be removed
5676     * @return A new array containing the existing elements except those
5677     *         at the specified positions.
5678     * @throws IndexOutOfBoundsException if any index is out of range
5679     * (index < 0 || index >= array.length), or if the array is {@code null}.
5680     * @since 3.0.1
5681     */
5682    public static long[] removeAll(final long[] array, final int... indices) {
5683        return (long[]) removeAll((Object) array, clone(indices));
5684    }
5685
5686    /**
5687     * <p>Removes occurrences of specified elements, in specified quantities,
5688     * from the specified array. All subsequent elements are shifted left.
5689     * For any element-to-be-removed specified in greater quantities than
5690     * contained in the original array, no change occurs beyond the
5691     * removal of the existing matching items.</p>
5692     *
5693     * <p>This method returns a new array with the same elements of the input
5694     * array except for the earliest-encountered occurrences of the specified
5695     * elements. The component type of the returned array is always the same
5696     * as that of the input array.</p>
5697     *
5698     * <pre>
5699     * ArrayUtils.removeElements(null, 1, 2)      = null
5700     * ArrayUtils.removeElements([], 1, 2)        = []
5701     * ArrayUtils.removeElements([1], 2, 3)       = [1]
5702     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5703     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5704     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5705     * </pre>
5706     *
5707     * @param array  the array to remove the element from, may be {@code null}
5708     * @param values the elements to be removed
5709     * @return A new array containing the existing elements except the
5710     *         earliest-encountered occurrences of the specified elements.
5711     * @since 3.0.1
5712     */
5713    public static long[] removeElements(final long[] array, final long... values) {
5714        if (isEmpty(array) || isEmpty(values)) {
5715            return clone(array);
5716        }
5717        final HashMap<Long, MutableInt> occurrences = new HashMap<Long, MutableInt>(values.length);
5718        for (final long v : values) {
5719            final Long boxed = Long.valueOf(v);
5720            final MutableInt count = occurrences.get(boxed);
5721            if (count == null) {
5722                occurrences.put(boxed, new MutableInt(1));
5723            } else {
5724                count.increment();
5725            }
5726        }
5727        final BitSet toRemove = new BitSet();
5728        for (final Map.Entry<Long, MutableInt> e : occurrences.entrySet()) {
5729            final Long v = e.getKey();
5730            int found = 0;
5731            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5732                found = indexOf(array, v.longValue(), found);
5733                if (found < 0) {
5734                    break;
5735                }
5736                toRemove.set(found++);
5737            }
5738        }
5739        return (long[]) removeAll(array, toRemove);
5740    }
5741
5742    /**
5743     * <p>Removes the elements at the specified positions from the specified array.
5744     * All remaining elements are shifted to the left.</p>
5745     *
5746     * <p>This method returns a new array with the same elements of the input
5747     * array except those at the specified positions. The component
5748     * type of the returned array is always the same as that of the input
5749     * array.</p>
5750     *
5751     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5752     * will be thrown, because in that case no valid index can be specified.</p>
5753     *
5754     * <pre>
5755     * ArrayUtils.removeAll([1], 0)             = []
5756     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5757     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5758     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5759     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5760     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5761     * </pre>
5762     *
5763     * @param array   the array to remove the element from, may not be {@code null}
5764     * @param indices the positions of the elements to be removed
5765     * @return A new array containing the existing elements except those
5766     *         at the specified positions.
5767     * @throws IndexOutOfBoundsException if any index is out of range
5768     * (index < 0 || index >= array.length), or if the array is {@code null}.
5769     * @since 3.0.1
5770     */
5771    public static float[] removeAll(final float[] array, final int... indices) {
5772        return (float[]) removeAll((Object) array, clone(indices));
5773    }
5774
5775    /**
5776     * <p>Removes occurrences of specified elements, in specified quantities,
5777     * from the specified array. All subsequent elements are shifted left.
5778     * For any element-to-be-removed specified in greater quantities than
5779     * contained in the original array, no change occurs beyond the
5780     * removal of the existing matching items.</p>
5781     *
5782     * <p>This method returns a new array with the same elements of the input
5783     * array except for the earliest-encountered occurrences of the specified
5784     * elements. The component type of the returned array is always the same
5785     * as that of the input array.</p>
5786     *
5787     * <pre>
5788     * ArrayUtils.removeElements(null, 1, 2)      = null
5789     * ArrayUtils.removeElements([], 1, 2)        = []
5790     * ArrayUtils.removeElements([1], 2, 3)       = [1]
5791     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5792     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5793     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5794     * </pre>
5795     *
5796     * @param array  the array to remove the element from, may be {@code null}
5797     * @param values the elements to be removed
5798     * @return A new array containing the existing elements except the
5799     *         earliest-encountered occurrences of the specified elements.
5800     * @since 3.0.1
5801     */
5802    public static float[] removeElements(final float[] array, final float... values) {
5803        if (isEmpty(array) || isEmpty(values)) {
5804            return clone(array);
5805        }
5806        final HashMap<Float, MutableInt> occurrences = new HashMap<Float, MutableInt>(values.length);
5807        for (final float v : values) {
5808            final Float boxed = Float.valueOf(v);
5809            final MutableInt count = occurrences.get(boxed);
5810            if (count == null) {
5811                occurrences.put(boxed, new MutableInt(1));
5812            } else {
5813                count.increment();
5814            }
5815        }
5816        final BitSet toRemove = new BitSet();
5817        for (final Map.Entry<Float, MutableInt> e : occurrences.entrySet()) {
5818            final Float v = e.getKey();
5819            int found = 0;
5820            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5821                found = indexOf(array, v.floatValue(), found);
5822                if (found < 0) {
5823                    break;
5824                }
5825                toRemove.set(found++);
5826            }
5827        }
5828        return (float[]) removeAll(array, toRemove);
5829    }
5830
5831    /**
5832     * <p>Removes the elements at the specified positions from the specified array.
5833     * All remaining elements are shifted to the left.</p>
5834     *
5835     * <p>This method returns a new array with the same elements of the input
5836     * array except those at the specified positions. The component
5837     * type of the returned array is always the same as that of the input
5838     * array.</p>
5839     *
5840     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5841     * will be thrown, because in that case no valid index can be specified.</p>
5842     *
5843     * <pre>
5844     * ArrayUtils.removeAll([1], 0)             = []
5845     * ArrayUtils.removeAll([2, 6], 0)          = [6]
5846     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5847     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5848     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5849     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5850     * </pre>
5851     *
5852     * @param array   the array to remove the element from, may not be {@code null}
5853     * @param indices the positions of the elements to be removed
5854     * @return A new array containing the existing elements except those
5855     *         at the specified positions.
5856     * @throws IndexOutOfBoundsException if any index is out of range
5857     * (index < 0 || index >= array.length), or if the array is {@code null}.
5858     * @since 3.0.1
5859     */
5860    public static double[] removeAll(final double[] array, final int... indices) {
5861        return (double[]) removeAll((Object) array, clone(indices));
5862    }
5863
5864    /**
5865     * <p>Removes occurrences of specified elements, in specified quantities,
5866     * from the specified array. All subsequent elements are shifted left.
5867     * For any element-to-be-removed specified in greater quantities than
5868     * contained in the original array, no change occurs beyond the
5869     * removal of the existing matching items.</p>
5870     *
5871     * <p>This method returns a new array with the same elements of the input
5872     * array except for the earliest-encountered occurrences of the specified
5873     * elements. The component type of the returned array is always the same
5874     * as that of the input array.</p>
5875     *
5876     * <pre>
5877     * ArrayUtils.removeElements(null, 1, 2)      = null
5878     * ArrayUtils.removeElements([], 1, 2)        = []
5879     * ArrayUtils.removeElements([1], 2, 3)       = [1]
5880     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5881     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5882     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5883     * </pre>
5884     *
5885     * @param array  the array to remove the element from, may be {@code null}
5886     * @param values the elements to be removed
5887     * @return A new array containing the existing elements except the
5888     *         earliest-encountered occurrences of the specified elements.
5889     * @since 3.0.1
5890     */
5891    public static double[] removeElements(final double[] array, final double... values) {
5892        if (isEmpty(array) || isEmpty(values)) {
5893            return clone(array);
5894        }
5895        final HashMap<Double, MutableInt> occurrences = new HashMap<Double, MutableInt>(values.length);
5896        for (final double v : values) {
5897            final Double boxed = Double.valueOf(v);
5898            final MutableInt count = occurrences.get(boxed);
5899            if (count == null) {
5900                occurrences.put(boxed, new MutableInt(1));
5901            } else {
5902                count.increment();
5903            }
5904        }
5905        final BitSet toRemove = new BitSet();
5906        for (final Map.Entry<Double, MutableInt> e : occurrences.entrySet()) {
5907            final Double v = e.getKey();
5908            int found = 0;
5909            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5910                found = indexOf(array, v.doubleValue(), found);
5911                if (found < 0) {
5912                    break;
5913                }
5914                toRemove.set(found++);
5915            }
5916        }
5917        return (double[]) removeAll(array, toRemove);
5918    }
5919
5920    /**
5921     * <p>Removes the elements at the specified positions from the specified array.
5922     * All remaining elements are shifted to the left.</p>
5923     *
5924     * <p>This method returns a new array with the same elements of the input
5925     * array except those at the specified positions. The component
5926     * type of the returned array is always the same as that of the input
5927     * array.</p>
5928     *
5929     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5930     * will be thrown, because in that case no valid index can be specified.</p>
5931     *
5932     * <pre>
5933     * ArrayUtils.removeAll([true, false, true], 0, 2) = [false]
5934     * ArrayUtils.removeAll([true, false, true], 1, 2) = [true]
5935     * </pre>
5936     *
5937     * @param array   the array to remove the element from, may not be {@code null}
5938     * @param indices the positions of the elements to be removed
5939     * @return A new array containing the existing elements except those
5940     *         at the specified positions.
5941     * @throws IndexOutOfBoundsException if any index is out of range
5942     * (index < 0 || index >= array.length), or if the array is {@code null}.
5943     * @since 3.0.1
5944     */
5945    public static boolean[] removeAll(final boolean[] array, final int... indices) {
5946        return (boolean[]) removeAll((Object) array, clone(indices));
5947    }
5948
5949    /**
5950     * <p>Removes occurrences of specified elements, in specified quantities,
5951     * from the specified array. All subsequent elements are shifted left.
5952     * For any element-to-be-removed specified in greater quantities than
5953     * contained in the original array, no change occurs beyond the
5954     * removal of the existing matching items.</p>
5955     *
5956     * <p>This method returns a new array with the same elements of the input
5957     * array except for the earliest-encountered occurrences of the specified
5958     * elements. The component type of the returned array is always the same
5959     * as that of the input array.</p>
5960     *
5961     * <pre>
5962     * ArrayUtils.removeElements(null, true, false)               = null
5963     * ArrayUtils.removeElements([], true, false)                 = []
5964     * ArrayUtils.removeElements([true], false, false)            = [true]
5965     * ArrayUtils.removeElements([true, false], true, true)       = [false]
5966     * ArrayUtils.removeElements([true, false, true], true)       = [false, true]
5967     * ArrayUtils.removeElements([true, false, true], true, true) = [false]
5968     * </pre>
5969     *
5970     * @param array  the array to remove the element from, may be {@code null}
5971     * @param values the elements to be removed
5972     * @return A new array containing the existing elements except the
5973     *         earliest-encountered occurrences of the specified elements.
5974     * @since 3.0.1
5975     */
5976    public static boolean[] removeElements(final boolean[] array, final boolean... values) {
5977        if (isEmpty(array) || isEmpty(values)) {
5978            return clone(array);
5979        }
5980        final HashMap<Boolean, MutableInt> occurrences = new HashMap<Boolean, MutableInt>(2); // only two possible values here
5981        for (final boolean v : values) {
5982            final Boolean boxed = Boolean.valueOf(v);
5983            final MutableInt count = occurrences.get(boxed);
5984            if (count == null) {
5985                occurrences.put(boxed, new MutableInt(1));
5986            } else {
5987                count.increment();
5988            }
5989        }
5990        final BitSet toRemove = new BitSet();
5991        for (final Map.Entry<Boolean, MutableInt> e : occurrences.entrySet()) {
5992            final Boolean v = e.getKey();
5993            int found = 0;
5994            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5995                found = indexOf(array, v.booleanValue(), found);
5996                if (found < 0) {
5997                    break;
5998                }
5999                toRemove.set(found++);
6000            }
6001        }
6002        return (boolean[]) removeAll(array, toRemove);
6003    }
6004
6005    /**
6006     * Removes multiple array elements specified by index.
6007     * @param array source
6008     * @param indices to remove, WILL BE SORTED--so only clones of user-owned arrays!
6009     * @return new array of same type minus elements specified by unique values of {@code indices}
6010     * @since 3.0.1
6011     */
6012    // package protected for access by unit tests
6013    static Object removeAll(final Object array, final int... indices) {
6014        final int length = getLength(array);
6015        int diff = 0; // number of distinct indexes, i.e. number of entries that will be removed
6016
6017        if (isNotEmpty(indices)) {
6018            Arrays.sort(indices);
6019
6020            int i = indices.length;
6021            int prevIndex = length;
6022            while (--i >= 0) {
6023                final int index = indices[i];
6024                if (index < 0 || index >= length) {
6025                    throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
6026                }
6027                if (index >= prevIndex) {
6028                    continue;
6029                }
6030                diff++;
6031                prevIndex = index;
6032            }
6033        }
6034        final Object result = Array.newInstance(array.getClass().getComponentType(), length - diff);
6035        if (diff < length) {
6036            int end = length; // index just after last copy
6037            int dest = length - diff; // number of entries so far not copied
6038            for (int i = indices.length - 1; i >= 0; i--) {
6039                final int index = indices[i];
6040                if (end - index > 1) { // same as (cp > 0)
6041                    final int cp = end - index - 1;
6042                    dest -= cp;
6043                    System.arraycopy(array, index + 1, result, dest, cp);
6044                    // Afer this copy, we still have room for dest items.
6045                }
6046                end = index;
6047            }
6048            if (end > 0) {
6049                System.arraycopy(array, 0, result, 0, end);
6050            }
6051        }
6052        return result;
6053    }
6054
6055    /**
6056     * Removes multiple array elements specified by indices.
6057     * 
6058     * @param array source
6059     * @param indices to remove
6060     * @return new array of same type minus elements specified by the set bits in {@code indices}
6061     * @since 3.2
6062     */
6063    // package protected for access by unit tests
6064    static Object removeAll(final Object array, final BitSet indices) {
6065        final int srcLength = ArrayUtils.getLength(array);
6066        // No need to check maxIndex here, because method only currently called from removeElements()
6067        // which guarantee to generate on;y valid bit entries.
6068//        final int maxIndex = indices.length();
6069//        if (maxIndex > srcLength) { 
6070//            throw new IndexOutOfBoundsException("Index: " + (maxIndex-1) + ", Length: " + srcLength);
6071//        }
6072        final int removals = indices.cardinality(); // true bits are items to remove
6073        final Object result = Array.newInstance(array.getClass().getComponentType(), srcLength - removals);
6074        int srcIndex=0;
6075        int destIndex=0;
6076        int count;
6077        int set;
6078        while((set = indices.nextSetBit(srcIndex)) != -1){
6079            count = set - srcIndex;
6080            if (count > 0) {
6081                System.arraycopy(array, srcIndex, result, destIndex, count);
6082                destIndex += count;
6083            }
6084            srcIndex = indices.nextClearBit(set);
6085        }
6086        count = srcLength - srcIndex;
6087        if (count > 0) {
6088            System.arraycopy(array, srcIndex, result, destIndex, count);            
6089        }
6090        return result;
6091    }
6092}