001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.lang3;
018
019import java.lang.reflect.Array;
020import java.util.Arrays;
021import java.util.BitSet;
022import java.util.Comparator;
023import java.util.HashMap;
024import java.util.Map;
025
026import org.apache.commons.lang3.builder.EqualsBuilder;
027import org.apache.commons.lang3.builder.HashCodeBuilder;
028import org.apache.commons.lang3.builder.ToStringBuilder;
029import org.apache.commons.lang3.builder.ToStringStyle;
030import org.apache.commons.lang3.math.NumberUtils;
031import org.apache.commons.lang3.mutable.MutableInt;
032
033/**
034 * <p>Operations on arrays, primitive arrays (like {@code int[]}) and
035 * primitive wrapper arrays (like {@code Integer[]}).
036 *
037 * <p>This class tries to handle {@code null} input gracefully.
038 * An exception will not be thrown for a {@code null}
039 * array input. However, an Object array that contains a {@code null}
040 * element may throw an exception. Each method documents its behaviour.
041 *
042 * <p>#ThreadSafe#
043 * @since 2.0
044 */
045public class ArrayUtils {
046
047    /**
048     * An empty immutable {@code Object} array.
049     */
050    public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
051    /**
052     * An empty immutable {@code Class} array.
053     */
054    public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class[0];
055    /**
056     * An empty immutable {@code String} array.
057     */
058    public static final String[] EMPTY_STRING_ARRAY = new String[0];
059    /**
060     * An empty immutable {@code long} array.
061     */
062    public static final long[] EMPTY_LONG_ARRAY = new long[0];
063    /**
064     * An empty immutable {@code Long} array.
065     */
066    public static final Long[] EMPTY_LONG_OBJECT_ARRAY = new Long[0];
067    /**
068     * An empty immutable {@code int} array.
069     */
070    public static final int[] EMPTY_INT_ARRAY = new int[0];
071    /**
072     * An empty immutable {@code Integer} array.
073     */
074    public static final Integer[] EMPTY_INTEGER_OBJECT_ARRAY = new Integer[0];
075    /**
076     * An empty immutable {@code short} array.
077     */
078    public static final short[] EMPTY_SHORT_ARRAY = new short[0];
079    /**
080     * An empty immutable {@code Short} array.
081     */
082    public static final Short[] EMPTY_SHORT_OBJECT_ARRAY = new Short[0];
083    /**
084     * An empty immutable {@code byte} array.
085     */
086    public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
087    /**
088     * An empty immutable {@code Byte} array.
089     */
090    public static final Byte[] EMPTY_BYTE_OBJECT_ARRAY = new Byte[0];
091    /**
092     * An empty immutable {@code double} array.
093     */
094    public static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
095    /**
096     * An empty immutable {@code Double} array.
097     */
098    public static final Double[] EMPTY_DOUBLE_OBJECT_ARRAY = new Double[0];
099    /**
100     * An empty immutable {@code float} array.
101     */
102    public static final float[] EMPTY_FLOAT_ARRAY = new float[0];
103    /**
104     * An empty immutable {@code Float} array.
105     */
106    public static final Float[] EMPTY_FLOAT_OBJECT_ARRAY = new Float[0];
107    /**
108     * An empty immutable {@code boolean} array.
109     */
110    public static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
111    /**
112     * An empty immutable {@code Boolean} array.
113     */
114    public static final Boolean[] EMPTY_BOOLEAN_OBJECT_ARRAY = new Boolean[0];
115    /**
116     * An empty immutable {@code char} array.
117     */
118    public static final char[] EMPTY_CHAR_ARRAY = new char[0];
119    /**
120     * An empty immutable {@code Character} array.
121     */
122    public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = new Character[0];
123
124    /**
125     * The index value when an element is not found in a list or array: {@code -1}.
126     * This value is returned by methods in this class and can also be used in comparisons with values returned by
127     * various method from {@link java.util.List}.
128     */
129    public static final int INDEX_NOT_FOUND = -1;
130
131    /**
132     * <p>ArrayUtils instances should NOT be constructed in standard programming.
133     * Instead, the class should be used as <code>ArrayUtils.clone(new int[] {2})</code>.
134     *
135     * <p>This constructor is public to permit tools that require a JavaBean instance
136     * to operate.
137     */
138    public ArrayUtils() {
139      super();
140    }
141
142
143    // NOTE: Cannot use {@code} to enclose text which includes {}, but <code></code> is OK
144
145
146    // Basic methods handling multi-dimensional arrays
147    //-----------------------------------------------------------------------
148    /**
149     * <p>Outputs an array as a String, treating {@code null} as an empty array.
150     *
151     * <p>Multi-dimensional arrays are handled correctly, including
152     * multi-dimensional primitive arrays.
153     *
154     * <p>The format is that of Java source code, for example <code>{a,b}</code>.
155     *
156     * @param array  the array to get a toString for, may be {@code null}
157     * @return a String representation of the array, '{}' if null array input
158     */
159    public static String toString(final Object array) {
160        return toString(array, "{}");
161    }
162
163    /**
164     * <p>Outputs an array as a String handling {@code null}s.
165     *
166     * <p>Multi-dimensional arrays are handled correctly, including
167     * multi-dimensional primitive arrays.
168     *
169     * <p>The format is that of Java source code, for example <code>{a,b}</code>.
170     *
171     * @param array  the array to get a toString for, may be {@code null}
172     * @param stringIfNull  the String to return if the array is {@code null}
173     * @return a String representation of the array
174     */
175    public static String toString(final Object array, final String stringIfNull) {
176        if (array == null) {
177            return stringIfNull;
178        }
179        return new ToStringBuilder(array, ToStringStyle.SIMPLE_STYLE).append(array).toString();
180    }
181
182    /**
183     * <p>Get a hash code for an array handling multi-dimensional arrays correctly.
184     *
185     * <p>Multi-dimensional primitive arrays are also handled correctly by this method.
186     *
187     * @param array  the array to get a hash code for, {@code null} returns zero
188     * @return a hash code for the array
189     */
190    public static int hashCode(final Object array) {
191        return new HashCodeBuilder().append(array).toHashCode();
192    }
193
194    /**
195     * <p>Compares two arrays, using equals(), handling multi-dimensional arrays
196     * correctly.
197     *
198     * <p>Multi-dimensional primitive arrays are also handled correctly by this method.
199     *
200     * @param array1  the left hand array to compare, may be {@code null}
201     * @param array2  the right hand array to compare, may be {@code null}
202     * @return {@code true} if the arrays are equal
203     * @deprecated this method has been replaced by {@code java.util.Objects.deepEquals(Object, Object)} and will be
204     * removed from future releases.
205     */
206    @Deprecated
207    public static boolean isEquals(final Object array1, final Object array2) {
208        return new EqualsBuilder().append(array1, array2).isEquals();
209    }
210
211    // To map
212    //-----------------------------------------------------------------------
213    /**
214     * <p>Converts the given array into a {@link java.util.Map}. Each element of the array
215     * must be either a {@link java.util.Map.Entry} or an Array, containing at least two
216     * elements, where the first element is used as key and the second as
217     * value.
218     *
219     * <p>This method can be used to initialize:
220     * <pre>
221     * // Create a Map mapping colors.
222     * Map colorMap = ArrayUtils.toMap(new String[][] {
223     *     {"RED", "#FF0000"},
224     *     {"GREEN", "#00FF00"},
225     *     {"BLUE", "#0000FF"}});
226     * </pre>
227     *
228     * <p>This method returns {@code null} for a {@code null} input array.
229     *
230     * @param array  an array whose elements are either a {@link java.util.Map.Entry} or
231     *  an Array containing at least two elements, may be {@code null}
232     * @return a {@code Map} that was created from the array
233     * @throws IllegalArgumentException  if one element of this Array is
234     *  itself an Array containing less then two elements
235     * @throws IllegalArgumentException  if the array contains elements other
236     *  than {@link java.util.Map.Entry} and an Array
237     */
238    public static Map<Object, Object> toMap(final Object[] array) {
239        if (array == null) {
240            return null;
241        }
242        final Map<Object, Object> map = new HashMap<Object, Object>((int) (array.length * 1.5));
243        for (int i = 0; i < array.length; i++) {
244            final Object object = array[i];
245            if (object instanceof Map.Entry<?, ?>) {
246                final Map.Entry<?,?> entry = (Map.Entry<?,?>) object;
247                map.put(entry.getKey(), entry.getValue());
248            } else if (object instanceof Object[]) {
249                final Object[] entry = (Object[]) object;
250                if (entry.length < 2) {
251                    throw new IllegalArgumentException("Array element " + i + ", '"
252                        + object
253                        + "', has a length less than 2");
254                }
255                map.put(entry[0], entry[1]);
256            } else {
257                throw new IllegalArgumentException("Array element " + i + ", '"
258                        + object
259                        + "', is neither of type Map.Entry nor an Array");
260            }
261        }
262        return map;
263    }
264
265    // Generic array
266    //-----------------------------------------------------------------------
267    /**
268     * <p>Create a type-safe generic array.
269     *
270     * <p>The Java language does not allow an array to be created from a generic type:
271     *
272     * <pre>
273    public static &lt;T&gt; T[] createAnArray(int size) {
274        return new T[size]; // compiler error here
275    }
276    public static &lt;T&gt; T[] createAnArray(int size) {
277        return (T[])new Object[size]; // ClassCastException at runtime
278    }
279     * </pre>
280     *
281     * <p>Therefore new arrays of generic types can be created with this method.
282     * For example, an array of Strings can be created:
283     *
284     * <pre>
285    String[] array = ArrayUtils.toArray("1", "2");
286    String[] emptyArray = ArrayUtils.&lt;String&gt;toArray();
287     * </pre>
288     *
289     * <p>The method is typically used in scenarios, where the caller itself uses generic types
290     * that have to be combined into an array.
291     *
292     * <p>Note, this method makes only sense to provide arguments of the same type so that the
293     * compiler can deduce the type of the array itself. While it is possible to select the
294     * type explicitly like in
295     * <code>Number[] array = ArrayUtils.&lt;Number&gt;toArray(Integer.valueOf(42), Double.valueOf(Math.PI))</code>,
296     * there is no real advantage when compared to
297     * <code>new Number[] {Integer.valueOf(42), Double.valueOf(Math.PI)}</code>.
298     *
299     * @param  <T>   the array's element type
300     * @param  items  the varargs array items, null allowed
301     * @return the array, not null unless a null array is passed in
302     * @since  3.0
303     */
304    public static <T> T[] toArray(final T... items) {
305        return items;
306    }
307
308    // Clone
309    //-----------------------------------------------------------------------
310    /**
311     * <p>Shallow clones an array returning a typecast result and handling
312     * {@code null}.
313     *
314     * <p>The objects in the array are not cloned, thus there is no special
315     * handling for multi-dimensional arrays.
316     *
317     * <p>This method returns {@code null} for a {@code null} input array.
318     *
319     * @param <T> the component type of the array
320     * @param array  the array to shallow clone, may be {@code null}
321     * @return the cloned array, {@code null} if {@code null} input
322     */
323    public static <T> T[] clone(final T[] array) {
324        if (array == null) {
325            return null;
326        }
327        return array.clone();
328    }
329
330    /**
331     * <p>Clones an array returning a typecast result and handling
332     * {@code null}.
333     *
334     * <p>This method returns {@code null} for a {@code null} input array.
335     *
336     * @param array  the array to clone, may be {@code null}
337     * @return the cloned array, {@code null} if {@code null} input
338     */
339    public static long[] clone(final long[] array) {
340        if (array == null) {
341            return null;
342        }
343        return array.clone();
344    }
345
346    /**
347     * <p>Clones an array returning a typecast result and handling
348     * {@code null}.
349     *
350     * <p>This method returns {@code null} for a {@code null} input array.
351     *
352     * @param array  the array to clone, may be {@code null}
353     * @return the cloned array, {@code null} if {@code null} input
354     */
355    public static int[] clone(final int[] array) {
356        if (array == null) {
357            return null;
358        }
359        return array.clone();
360    }
361
362    /**
363     * <p>Clones an array returning a typecast result and handling
364     * {@code null}.
365     *
366     * <p>This method returns {@code null} for a {@code null} input array.
367     *
368     * @param array  the array to clone, may be {@code null}
369     * @return the cloned array, {@code null} if {@code null} input
370     */
371    public static short[] clone(final short[] array) {
372        if (array == null) {
373            return null;
374        }
375        return array.clone();
376    }
377
378    /**
379     * <p>Clones an array returning a typecast result and handling
380     * {@code null}.
381     *
382     * <p>This method returns {@code null} for a {@code null} input array.
383     *
384     * @param array  the array to clone, may be {@code null}
385     * @return the cloned array, {@code null} if {@code null} input
386     */
387    public static char[] clone(final char[] array) {
388        if (array == null) {
389            return null;
390        }
391        return array.clone();
392    }
393
394    /**
395     * <p>Clones an array returning a typecast result and handling
396     * {@code null}.
397     *
398     * <p>This method returns {@code null} for a {@code null} input array.
399     *
400     * @param array  the array to clone, may be {@code null}
401     * @return the cloned array, {@code null} if {@code null} input
402     */
403    public static byte[] clone(final byte[] array) {
404        if (array == null) {
405            return null;
406        }
407        return array.clone();
408    }
409
410    /**
411     * <p>Clones an array returning a typecast result and handling
412     * {@code null}.
413     *
414     * <p>This method returns {@code null} for a {@code null} input array.
415     *
416     * @param array  the array to clone, may be {@code null}
417     * @return the cloned array, {@code null} if {@code null} input
418     */
419    public static double[] clone(final double[] array) {
420        if (array == null) {
421            return null;
422        }
423        return array.clone();
424    }
425
426    /**
427     * <p>Clones an array returning a typecast result and handling
428     * {@code null}.
429     *
430     * <p>This method returns {@code null} for a {@code null} input array.
431     *
432     * @param array  the array to clone, may be {@code null}
433     * @return the cloned array, {@code null} if {@code null} input
434     */
435    public static float[] clone(final float[] array) {
436        if (array == null) {
437            return null;
438        }
439        return array.clone();
440    }
441
442    /**
443     * <p>Clones an array returning a typecast result and handling
444     * {@code null}.
445     *
446     * <p>This method returns {@code null} for a {@code null} input array.
447     *
448     * @param array  the array to clone, may be {@code null}
449     * @return the cloned array, {@code null} if {@code null} input
450     */
451    public static boolean[] clone(final boolean[] array) {
452        if (array == null) {
453            return null;
454        }
455        return array.clone();
456    }
457
458    // nullToEmpty
459    //-----------------------------------------------------------------------
460    /**
461     * <p>Defensive programming technique to change a {@code null}
462     * reference to an empty one.
463     *
464     * <p>This method returns an empty array for a {@code null} input array.
465     *
466     * @param array  the array to check for {@code null} or empty
467     * @param type   the class representation of the desired array
468     * @param <T>  the class type
469     * @return the same array, {@code public static} empty array if {@code null}
470     * @throws IllegalArgumentException if the type argument is null
471     * @since 3.5
472     */
473    public static <T> T[] nullToEmpty(final T[] array, final Class<T[]> type) {
474        if (type == null) {
475            throw new IllegalArgumentException("The type must not be null");
476        }
477
478        if (array == null) {
479            return type.cast(Array.newInstance(type.getComponentType(), 0));
480        }
481        return array;
482    }    
483    
484    
485    /**
486     * <p>Defensive programming technique to change a {@code null}
487     * reference to an empty one.
488     *
489     * <p>This method returns an empty array for a {@code null} input array.
490     *
491     * <p>As a memory optimizing technique an empty array passed in will be overridden with
492     * the empty {@code public static} references in this class.
493     *
494     * @param array  the array to check for {@code null} or empty
495     * @return the same array, {@code public static} empty array if {@code null} or empty input
496     * @since 2.5
497     */
498    public static Object[] nullToEmpty(final Object[] array) {
499        if (isEmpty(array)) {
500            return EMPTY_OBJECT_ARRAY;
501        }
502        return array;
503    }
504
505    /**
506     * <p>Defensive programming technique to change a {@code null}
507     * reference to an empty one.
508     *
509     * <p>This method returns an empty array for a {@code null} input array.
510     *
511     * <p>As a memory optimizing technique an empty array passed in will be overridden with
512     * the empty {@code public static} references in this class.
513     *
514     * @param array  the array to check for {@code null} or empty
515     * @return the same array, {@code public static} empty array if {@code null} or empty input
516     * @since 3.2
517     */
518    public static Class<?>[] nullToEmpty(final Class<?>[] array) {
519        if (isEmpty(array)) {
520            return EMPTY_CLASS_ARRAY;
521        }
522        return array;
523    }
524
525    /**
526     * <p>Defensive programming technique to change a {@code null}
527     * reference to an empty one.
528     *
529     * <p>This method returns an empty array for a {@code null} input array.
530     *
531     * <p>As a memory optimizing technique an empty array passed in will be overridden with
532     * the empty {@code public static} references in this class.
533     *
534     * @param array  the array to check for {@code null} or empty
535     * @return the same array, {@code public static} empty array if {@code null} or empty input
536     * @since 2.5
537     */
538    public static String[] nullToEmpty(final String[] array) {
539        if (isEmpty(array)) {
540            return EMPTY_STRING_ARRAY;
541        }
542        return array;
543    }
544
545    /**
546     * <p>Defensive programming technique to change a {@code null}
547     * reference to an empty one.
548     *
549     * <p>This method returns an empty array for a {@code null} input array.
550     *
551     * <p>As a memory optimizing technique an empty array passed in will be overridden with
552     * the empty {@code public static} references in this class.
553     *
554     * @param array  the array to check for {@code null} or empty
555     * @return the same array, {@code public static} empty array if {@code null} or empty input
556     * @since 2.5
557     */
558    public static long[] nullToEmpty(final long[] array) {
559        if (isEmpty(array)) {
560            return EMPTY_LONG_ARRAY;
561        }
562        return array;
563    }
564
565    /**
566     * <p>Defensive programming technique to change a {@code null}
567     * reference to an empty one.
568     *
569     * <p>This method returns an empty array for a {@code null} input array.
570     *
571     * <p>As a memory optimizing technique an empty array passed in will be overridden with
572     * the empty {@code public static} references in this class.
573     *
574     * @param array  the array to check for {@code null} or empty
575     * @return the same array, {@code public static} empty array if {@code null} or empty input
576     * @since 2.5
577     */
578    public static int[] nullToEmpty(final int[] array) {
579        if (isEmpty(array)) {
580            return EMPTY_INT_ARRAY;
581        }
582        return array;
583    }
584
585    /**
586     * <p>Defensive programming technique to change a {@code null}
587     * reference to an empty one.
588     *
589     * <p>This method returns an empty array for a {@code null} input array.
590     *
591     * <p>As a memory optimizing technique an empty array passed in will be overridden with
592     * the empty {@code public static} references in this class.
593     *
594     * @param array  the array to check for {@code null} or empty
595     * @return the same array, {@code public static} empty array if {@code null} or empty input
596     * @since 2.5
597     */
598    public static short[] nullToEmpty(final short[] array) {
599        if (isEmpty(array)) {
600            return EMPTY_SHORT_ARRAY;
601        }
602        return array;
603    }
604
605    /**
606     * <p>Defensive programming technique to change a {@code null}
607     * reference to an empty one.
608     *
609     * <p>This method returns an empty array for a {@code null} input array.
610     *
611     * <p>As a memory optimizing technique an empty array passed in will be overridden with
612     * the empty {@code public static} references in this class.
613     *
614     * @param array  the array to check for {@code null} or empty
615     * @return the same array, {@code public static} empty array if {@code null} or empty input
616     * @since 2.5
617     */
618    public static char[] nullToEmpty(final char[] array) {
619        if (isEmpty(array)) {
620            return EMPTY_CHAR_ARRAY;
621        }
622        return array;
623    }
624
625    /**
626     * <p>Defensive programming technique to change a {@code null}
627     * reference to an empty one.
628     *
629     * <p>This method returns an empty array for a {@code null} input array.
630     *
631     * <p>As a memory optimizing technique an empty array passed in will be overridden with
632     * the empty {@code public static} references in this class.
633     *
634     * @param array  the array to check for {@code null} or empty
635     * @return the same array, {@code public static} empty array if {@code null} or empty input
636     * @since 2.5
637     */
638    public static byte[] nullToEmpty(final byte[] array) {
639        if (isEmpty(array)) {
640            return EMPTY_BYTE_ARRAY;
641        }
642        return array;
643    }
644
645    /**
646     * <p>Defensive programming technique to change a {@code null}
647     * reference to an empty one.
648     *
649     * <p>This method returns an empty array for a {@code null} input array.
650     *
651     * <p>As a memory optimizing technique an empty array passed in will be overridden with
652     * the empty {@code public static} references in this class.
653     *
654     * @param array  the array to check for {@code null} or empty
655     * @return the same array, {@code public static} empty array if {@code null} or empty input
656     * @since 2.5
657     */
658    public static double[] nullToEmpty(final double[] array) {
659        if (isEmpty(array)) {
660            return EMPTY_DOUBLE_ARRAY;
661        }
662        return array;
663    }
664
665    /**
666     * <p>Defensive programming technique to change a {@code null}
667     * reference to an empty one.
668     *
669     * <p>This method returns an empty array for a {@code null} input array.
670     *
671     * <p>As a memory optimizing technique an empty array passed in will be overridden with
672     * the empty {@code public static} references in this class.
673     *
674     * @param array  the array to check for {@code null} or empty
675     * @return the same array, {@code public static} empty array if {@code null} or empty input
676     * @since 2.5
677     */
678    public static float[] nullToEmpty(final float[] array) {
679        if (isEmpty(array)) {
680            return EMPTY_FLOAT_ARRAY;
681        }
682        return array;
683    }
684
685    /**
686     * <p>Defensive programming technique to change a {@code null}
687     * reference to an empty one.
688     *
689     * <p>This method returns an empty array for a {@code null} input array.
690     *
691     * <p>As a memory optimizing technique an empty array passed in will be overridden with
692     * the empty {@code public static} references in this class.
693     *
694     * @param array  the array to check for {@code null} or empty
695     * @return the same array, {@code public static} empty array if {@code null} or empty input
696     * @since 2.5
697     */
698    public static boolean[] nullToEmpty(final boolean[] array) {
699        if (isEmpty(array)) {
700            return EMPTY_BOOLEAN_ARRAY;
701        }
702        return array;
703    }
704
705    /**
706     * <p>Defensive programming technique to change a {@code null}
707     * reference to an empty one.
708     *
709     * <p>This method returns an empty array for a {@code null} input array.
710     *
711     * <p>As a memory optimizing technique an empty array passed in will be overridden with
712     * the empty {@code public static} references in this class.
713     *
714     * @param array  the array to check for {@code null} or empty
715     * @return the same array, {@code public static} empty array if {@code null} or empty input
716     * @since 2.5
717     */
718    public static Long[] nullToEmpty(final Long[] array) {
719        if (isEmpty(array)) {
720            return EMPTY_LONG_OBJECT_ARRAY;
721        }
722        return array;
723    }
724
725    /**
726     * <p>Defensive programming technique to change a {@code null}
727     * reference to an empty one.
728     *
729     * <p>This method returns an empty array for a {@code null} input array.
730     *
731     * <p>As a memory optimizing technique an empty array passed in will be overridden with
732     * the empty {@code public static} references in this class.
733     *
734     * @param array  the array to check for {@code null} or empty
735     * @return the same array, {@code public static} empty array if {@code null} or empty input
736     * @since 2.5
737     */
738    public static Integer[] nullToEmpty(final Integer[] array) {
739        if (isEmpty(array)) {
740            return EMPTY_INTEGER_OBJECT_ARRAY;
741        }
742        return array;
743    }
744
745    /**
746     * <p>Defensive programming technique to change a {@code null}
747     * reference to an empty one.
748     *
749     * <p>This method returns an empty array for a {@code null} input array.
750     *
751     * <p>As a memory optimizing technique an empty array passed in will be overridden with
752     * the empty {@code public static} references in this class.
753     *
754     * @param array  the array to check for {@code null} or empty
755     * @return the same array, {@code public static} empty array if {@code null} or empty input
756     * @since 2.5
757     */
758    public static Short[] nullToEmpty(final Short[] array) {
759        if (isEmpty(array)) {
760            return EMPTY_SHORT_OBJECT_ARRAY;
761        }
762        return array;
763    }
764
765    /**
766     * <p>Defensive programming technique to change a {@code null}
767     * reference to an empty one.
768     *
769     * <p>This method returns an empty array for a {@code null} input array.
770     *
771     * <p>As a memory optimizing technique an empty array passed in will be overridden with
772     * the empty {@code public static} references in this class.
773     *
774     * @param array  the array to check for {@code null} or empty
775     * @return the same array, {@code public static} empty array if {@code null} or empty input
776     * @since 2.5
777     */
778    public static Character[] nullToEmpty(final Character[] array) {
779        if (isEmpty(array)) {
780            return EMPTY_CHARACTER_OBJECT_ARRAY;
781        }
782        return array;
783    }
784
785    /**
786     * <p>Defensive programming technique to change a {@code null}
787     * reference to an empty one.
788     *
789     * <p>This method returns an empty array for a {@code null} input array.
790     *
791     * <p>As a memory optimizing technique an empty array passed in will be overridden with
792     * the empty {@code public static} references in this class.
793     *
794     * @param array  the array to check for {@code null} or empty
795     * @return the same array, {@code public static} empty array if {@code null} or empty input
796     * @since 2.5
797     */
798    public static Byte[] nullToEmpty(final Byte[] array) {
799        if (isEmpty(array)) {
800            return EMPTY_BYTE_OBJECT_ARRAY;
801        }
802        return array;
803    }
804
805    /**
806     * <p>Defensive programming technique to change a {@code null}
807     * reference to an empty one.
808     *
809     * <p>This method returns an empty array for a {@code null} input array.
810     *
811     * <p>As a memory optimizing technique an empty array passed in will be overridden with
812     * the empty {@code public static} references in this class.
813     *
814     * @param array  the array to check for {@code null} or empty
815     * @return the same array, {@code public static} empty array if {@code null} or empty input
816     * @since 2.5
817     */
818    public static Double[] nullToEmpty(final Double[] array) {
819        if (isEmpty(array)) {
820            return EMPTY_DOUBLE_OBJECT_ARRAY;
821        }
822        return array;
823    }
824
825    /**
826     * <p>Defensive programming technique to change a {@code null}
827     * reference to an empty one.
828     *
829     * <p>This method returns an empty array for a {@code null} input array.
830     *
831     * <p>As a memory optimizing technique an empty array passed in will be overridden with
832     * the empty {@code public static} references in this class.
833     *
834     * @param array  the array to check for {@code null} or empty
835     * @return the same array, {@code public static} empty array if {@code null} or empty input
836     * @since 2.5
837     */
838    public static Float[] nullToEmpty(final Float[] array) {
839        if (isEmpty(array)) {
840            return EMPTY_FLOAT_OBJECT_ARRAY;
841        }
842        return array;
843    }
844
845    /**
846     * <p>Defensive programming technique to change a {@code null}
847     * reference to an empty one.
848     *
849     * <p>This method returns an empty array for a {@code null} input array.
850     *
851     * <p>As a memory optimizing technique an empty array passed in will be overridden with
852     * the empty {@code public static} references in this class.
853     *
854     * @param array  the array to check for {@code null} or empty
855     * @return the same array, {@code public static} empty array if {@code null} or empty input
856     * @since 2.5
857     */
858    public static Boolean[] nullToEmpty(final Boolean[] array) {
859        if (isEmpty(array)) {
860            return EMPTY_BOOLEAN_OBJECT_ARRAY;
861        }
862        return array;
863    }
864
865    // Subarrays
866    //-----------------------------------------------------------------------
867    /**
868     * <p>Produces a new array containing the elements between
869     * the start and end indices.
870     *
871     * <p>The start index is inclusive, the end index exclusive.
872     * Null array input produces null output.
873     *
874     * <p>The component type of the subarray is always the same as
875     * that of the input array. Thus, if the input is an array of type
876     * {@code Date}, the following usage is envisaged:
877     *
878     * <pre>
879     * Date[] someDates = (Date[])ArrayUtils.subarray(allDates, 2, 5);
880     * </pre>
881     *
882     * @param <T> the component type of the array
883     * @param array  the array
884     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
885     *      is promoted to 0, overvalue (&gt;array.length) results
886     *      in an empty array.
887     * @param endIndexExclusive  elements up to endIndex-1 are present in the
888     *      returned subarray. Undervalue (&lt; startIndex) produces
889     *      empty array, overvalue (&gt;array.length) is demoted to
890     *      array length.
891     * @return a new array containing the elements between
892     *      the start and end indices.
893     * @since 2.1
894     * @see Arrays#copyOfRange(Object[], int, int)
895     */
896    public static <T> T[] subarray(final T[] array, int startIndexInclusive, int endIndexExclusive) {
897        if (array == null) {
898            return null;
899        }
900        if (startIndexInclusive < 0) {
901            startIndexInclusive = 0;
902        }
903        if (endIndexExclusive > array.length) {
904            endIndexExclusive = array.length;
905        }
906        final int newSize = endIndexExclusive - startIndexInclusive;
907        final Class<?> type = array.getClass().getComponentType();
908        if (newSize <= 0) {
909            @SuppressWarnings("unchecked") // OK, because array is of type T
910            final T[] emptyArray = (T[]) Array.newInstance(type, 0);
911            return emptyArray;
912        }
913        @SuppressWarnings("unchecked") // OK, because array is of type T
914        final
915        T[] subarray = (T[]) Array.newInstance(type, newSize);
916        System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
917        return subarray;
918    }
919
920    /**
921     * <p>Produces a new {@code long} array containing the elements
922     * between the start and end indices.
923     *
924     * <p>The start index is inclusive, the end index exclusive.
925     * Null array input produces null output.
926     *
927     * @param array  the array
928     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
929     *      is promoted to 0, overvalue (&gt;array.length) results
930     *      in an empty array.
931     * @param endIndexExclusive  elements up to endIndex-1 are present in the
932     *      returned subarray. Undervalue (&lt; startIndex) produces
933     *      empty array, overvalue (&gt;array.length) is demoted to
934     *      array length.
935     * @return a new array containing the elements between
936     *      the start and end indices.
937     * @since 2.1
938     * @see Arrays#copyOfRange(long[], int, int)
939     */
940    public static long[] subarray(final long[] array, int startIndexInclusive, int endIndexExclusive) {
941        if (array == null) {
942            return null;
943        }
944        if (startIndexInclusive < 0) {
945            startIndexInclusive = 0;
946        }
947        if (endIndexExclusive > array.length) {
948            endIndexExclusive = array.length;
949        }
950        final int newSize = endIndexExclusive - startIndexInclusive;
951        if (newSize <= 0) {
952            return EMPTY_LONG_ARRAY;
953        }
954
955        final long[] subarray = new long[newSize];
956        System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
957        return subarray;
958    }
959
960    /**
961     * <p>Produces a new {@code int} array containing the elements
962     * between the start and end indices.
963     *
964     * <p>The start index is inclusive, the end index exclusive.
965     * Null array input produces null output.
966     *
967     * @param array  the array
968     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
969     *      is promoted to 0, overvalue (&gt;array.length) results
970     *      in an empty array.
971     * @param endIndexExclusive  elements up to endIndex-1 are present in the
972     *      returned subarray. Undervalue (&lt; startIndex) produces
973     *      empty array, overvalue (&gt;array.length) is demoted to
974     *      array length.
975     * @return a new array containing the elements between
976     *      the start and end indices.
977     * @since 2.1
978     * @see Arrays#copyOfRange(int[], int, int)
979     */
980    public static int[] subarray(final int[] array, int startIndexInclusive, int endIndexExclusive) {
981        if (array == null) {
982            return null;
983        }
984        if (startIndexInclusive < 0) {
985            startIndexInclusive = 0;
986        }
987        if (endIndexExclusive > array.length) {
988            endIndexExclusive = array.length;
989        }
990        final int newSize = endIndexExclusive - startIndexInclusive;
991        if (newSize <= 0) {
992            return EMPTY_INT_ARRAY;
993        }
994
995        final int[] subarray = new int[newSize];
996        System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
997        return subarray;
998    }
999
1000    /**
1001     * <p>Produces a new {@code short} array containing the elements
1002     * between the start and end indices.
1003     *
1004     * <p>The start index is inclusive, the end index exclusive.
1005     * Null array input produces null output.
1006     *
1007     * @param array  the array
1008     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
1009     *      is promoted to 0, overvalue (&gt;array.length) results
1010     *      in an empty array.
1011     * @param endIndexExclusive  elements up to endIndex-1 are present in the
1012     *      returned subarray. Undervalue (&lt; startIndex) produces
1013     *      empty array, overvalue (&gt;array.length) is demoted to
1014     *      array length.
1015     * @return a new array containing the elements between
1016     *      the start and end indices.
1017     * @since 2.1
1018     * @see Arrays#copyOfRange(short[], int, int)
1019     */
1020    public static short[] subarray(final short[] array, int startIndexInclusive, int endIndexExclusive) {
1021        if (array == null) {
1022            return null;
1023        }
1024        if (startIndexInclusive < 0) {
1025            startIndexInclusive = 0;
1026        }
1027        if (endIndexExclusive > array.length) {
1028            endIndexExclusive = array.length;
1029        }
1030        final int newSize = endIndexExclusive - startIndexInclusive;
1031        if (newSize <= 0) {
1032            return EMPTY_SHORT_ARRAY;
1033        }
1034
1035        final short[] subarray = new short[newSize];
1036        System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1037        return subarray;
1038    }
1039
1040    /**
1041     * <p>Produces a new {@code char} array containing the elements
1042     * between the start and end indices.
1043     *
1044     * <p>The start index is inclusive, the end index exclusive.
1045     * Null array input produces null output.
1046     *
1047     * @param array  the array
1048     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
1049     *      is promoted to 0, overvalue (&gt;array.length) results
1050     *      in an empty array.
1051     * @param endIndexExclusive  elements up to endIndex-1 are present in the
1052     *      returned subarray. Undervalue (&lt; startIndex) produces
1053     *      empty array, overvalue (&gt;array.length) is demoted to
1054     *      array length.
1055     * @return a new array containing the elements between
1056     *      the start and end indices.
1057     * @since 2.1
1058     * @see Arrays#copyOfRange(char[], int, int)
1059     */
1060    public static char[] subarray(final char[] array, int startIndexInclusive, int endIndexExclusive) {
1061        if (array == null) {
1062            return null;
1063        }
1064        if (startIndexInclusive < 0) {
1065            startIndexInclusive = 0;
1066        }
1067        if (endIndexExclusive > array.length) {
1068            endIndexExclusive = array.length;
1069        }
1070        final int newSize = endIndexExclusive - startIndexInclusive;
1071        if (newSize <= 0) {
1072            return EMPTY_CHAR_ARRAY;
1073        }
1074
1075        final char[] subarray = new char[newSize];
1076        System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1077        return subarray;
1078    }
1079
1080    /**
1081     * <p>Produces a new {@code byte} array containing the elements
1082     * between the start and end indices.
1083     *
1084     * <p>The start index is inclusive, the end index exclusive.
1085     * Null array input produces null output.
1086     *
1087     * @param array  the array
1088     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
1089     *      is promoted to 0, overvalue (&gt;array.length) results
1090     *      in an empty array.
1091     * @param endIndexExclusive  elements up to endIndex-1 are present in the
1092     *      returned subarray. Undervalue (&lt; startIndex) produces
1093     *      empty array, overvalue (&gt;array.length) is demoted to
1094     *      array length.
1095     * @return a new array containing the elements between
1096     *      the start and end indices.
1097     * @since 2.1
1098     * @see Arrays#copyOfRange(byte[], int, int)
1099     */
1100    public static byte[] subarray(final byte[] array, int startIndexInclusive, int endIndexExclusive) {
1101        if (array == null) {
1102            return null;
1103        }
1104        if (startIndexInclusive < 0) {
1105            startIndexInclusive = 0;
1106        }
1107        if (endIndexExclusive > array.length) {
1108            endIndexExclusive = array.length;
1109        }
1110        final int newSize = endIndexExclusive - startIndexInclusive;
1111        if (newSize <= 0) {
1112            return EMPTY_BYTE_ARRAY;
1113        }
1114
1115        final byte[] subarray = new byte[newSize];
1116        System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1117        return subarray;
1118    }
1119
1120    /**
1121     * <p>Produces a new {@code double} array containing the elements
1122     * between the start and end indices.
1123     *
1124     * <p>The start index is inclusive, the end index exclusive.
1125     * Null array input produces null output.
1126     *
1127     * @param array  the array
1128     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
1129     *      is promoted to 0, overvalue (&gt;array.length) results
1130     *      in an empty array.
1131     * @param endIndexExclusive  elements up to endIndex-1 are present in the
1132     *      returned subarray. Undervalue (&lt; startIndex) produces
1133     *      empty array, overvalue (&gt;array.length) is demoted to
1134     *      array length.
1135     * @return a new array containing the elements between
1136     *      the start and end indices.
1137     * @since 2.1
1138     * @see Arrays#copyOfRange(double[], int, int)
1139     */
1140    public static double[] subarray(final double[] array, int startIndexInclusive, int endIndexExclusive) {
1141        if (array == null) {
1142            return null;
1143        }
1144        if (startIndexInclusive < 0) {
1145            startIndexInclusive = 0;
1146        }
1147        if (endIndexExclusive > array.length) {
1148            endIndexExclusive = array.length;
1149        }
1150        final int newSize = endIndexExclusive - startIndexInclusive;
1151        if (newSize <= 0) {
1152            return EMPTY_DOUBLE_ARRAY;
1153        }
1154
1155        final double[] subarray = new double[newSize];
1156        System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1157        return subarray;
1158    }
1159
1160    /**
1161     * <p>Produces a new {@code float} array containing the elements
1162     * between the start and end indices.
1163     *
1164     * <p>The start index is inclusive, the end index exclusive.
1165     * Null array input produces null output.
1166     *
1167     * @param array  the array
1168     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
1169     *      is promoted to 0, overvalue (&gt;array.length) results
1170     *      in an empty array.
1171     * @param endIndexExclusive  elements up to endIndex-1 are present in the
1172     *      returned subarray. Undervalue (&lt; startIndex) produces
1173     *      empty array, overvalue (&gt;array.length) is demoted to
1174     *      array length.
1175     * @return a new array containing the elements between
1176     *      the start and end indices.
1177     * @since 2.1
1178     * @see Arrays#copyOfRange(float[], int, int)
1179     */
1180    public static float[] subarray(final float[] array, int startIndexInclusive, int endIndexExclusive) {
1181        if (array == null) {
1182            return null;
1183        }
1184        if (startIndexInclusive < 0) {
1185            startIndexInclusive = 0;
1186        }
1187        if (endIndexExclusive > array.length) {
1188            endIndexExclusive = array.length;
1189        }
1190        final int newSize = endIndexExclusive - startIndexInclusive;
1191        if (newSize <= 0) {
1192            return EMPTY_FLOAT_ARRAY;
1193        }
1194
1195        final float[] subarray = new float[newSize];
1196        System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1197        return subarray;
1198    }
1199
1200    /**
1201     * <p>Produces a new {@code boolean} array containing the elements
1202     * between the start and end indices.
1203     *
1204     * <p>The start index is inclusive, the end index exclusive.
1205     * Null array input produces null output.
1206     *
1207     * @param array  the array
1208     * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
1209     *      is promoted to 0, overvalue (&gt;array.length) results
1210     *      in an empty array.
1211     * @param endIndexExclusive  elements up to endIndex-1 are present in the
1212     *      returned subarray. Undervalue (&lt; startIndex) produces
1213     *      empty array, overvalue (&gt;array.length) is demoted to
1214     *      array length.
1215     * @return a new array containing the elements between
1216     *      the start and end indices.
1217     * @since 2.1
1218     * @see Arrays#copyOfRange(boolean[], int, int)
1219     */
1220    public static boolean[] subarray(final boolean[] array, int startIndexInclusive, int endIndexExclusive) {
1221        if (array == null) {
1222            return null;
1223        }
1224        if (startIndexInclusive < 0) {
1225            startIndexInclusive = 0;
1226        }
1227        if (endIndexExclusive > array.length) {
1228            endIndexExclusive = array.length;
1229        }
1230        final int newSize = endIndexExclusive - startIndexInclusive;
1231        if (newSize <= 0) {
1232            return EMPTY_BOOLEAN_ARRAY;
1233        }
1234
1235        final boolean[] subarray = new boolean[newSize];
1236        System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1237        return subarray;
1238    }
1239
1240    // Is same length
1241    //-----------------------------------------------------------------------
1242    /**
1243     * <p>Checks whether two arrays are the same length, treating
1244     * {@code null} arrays as length {@code 0}.
1245     *
1246     * <p>Any multi-dimensional aspects of the arrays are ignored.
1247     *
1248     * @param array1 the first array, may be {@code null}
1249     * @param array2 the second array, may be {@code null}
1250     * @return {@code true} if length of arrays matches, treating
1251     *  {@code null} as an empty array
1252     */
1253    public static boolean isSameLength(final Object[] array1, final Object[] array2) {
1254        return getLength(array1) == getLength(array2);
1255    }
1256
1257    /**
1258     * <p>Checks whether two arrays are the same length, treating
1259     * {@code null} arrays as length {@code 0}.
1260     *
1261     * @param array1 the first array, may be {@code null}
1262     * @param array2 the second array, may be {@code null}
1263     * @return {@code true} if length of arrays matches, treating
1264     *  {@code null} as an empty array
1265     */
1266    public static boolean isSameLength(final long[] array1, final long[] array2) {
1267        return getLength(array1) == getLength(array2);
1268    }
1269
1270    /**
1271     * <p>Checks whether two arrays are the same length, treating
1272     * {@code null} arrays as length {@code 0}.
1273     *
1274     * @param array1 the first array, may be {@code null}
1275     * @param array2 the second array, may be {@code null}
1276     * @return {@code true} if length of arrays matches, treating
1277     *  {@code null} as an empty array
1278     */
1279    public static boolean isSameLength(final int[] array1, final int[] array2) {
1280        return getLength(array1) == getLength(array2);
1281    }
1282
1283    /**
1284     * <p>Checks whether two arrays are the same length, treating
1285     * {@code null} arrays as length {@code 0}.
1286     *
1287     * @param array1 the first array, may be {@code null}
1288     * @param array2 the second array, may be {@code null}
1289     * @return {@code true} if length of arrays matches, treating
1290     *  {@code null} as an empty array
1291     */
1292    public static boolean isSameLength(final short[] array1, final short[] array2) {
1293        return getLength(array1) == getLength(array2);
1294    }
1295
1296    /**
1297     * <p>Checks whether two arrays are the same length, treating
1298     * {@code null} arrays as length {@code 0}.
1299     *
1300     * @param array1 the first array, may be {@code null}
1301     * @param array2 the second array, may be {@code null}
1302     * @return {@code true} if length of arrays matches, treating
1303     *  {@code null} as an empty array
1304     */
1305    public static boolean isSameLength(final char[] array1, final char[] array2) {
1306        return getLength(array1) == getLength(array2);
1307    }
1308
1309    /**
1310     * <p>Checks whether two arrays are the same length, treating
1311     * {@code null} arrays as length {@code 0}.
1312     *
1313     * @param array1 the first array, may be {@code null}
1314     * @param array2 the second array, may be {@code null}
1315     * @return {@code true} if length of arrays matches, treating
1316     *  {@code null} as an empty array
1317     */
1318    public static boolean isSameLength(final byte[] array1, final byte[] array2) {
1319        return getLength(array1) == getLength(array2);
1320    }
1321
1322    /**
1323     * <p>Checks whether two arrays are the same length, treating
1324     * {@code null} arrays as length {@code 0}.
1325     *
1326     * @param array1 the first array, may be {@code null}
1327     * @param array2 the second array, may be {@code null}
1328     * @return {@code true} if length of arrays matches, treating
1329     *  {@code null} as an empty array
1330     */
1331    public static boolean isSameLength(final double[] array1, final double[] array2) {
1332        return getLength(array1) == getLength(array2);
1333    }
1334
1335    /**
1336     * <p>Checks whether two arrays are the same length, treating
1337     * {@code null} arrays as length {@code 0}.
1338     *
1339     * @param array1 the first array, may be {@code null}
1340     * @param array2 the second array, may be {@code null}
1341     * @return {@code true} if length of arrays matches, treating
1342     *  {@code null} as an empty array
1343     */
1344    public static boolean isSameLength(final float[] array1, final float[] array2) {
1345        return getLength(array1) == getLength(array2);
1346    }
1347
1348    /**
1349     * <p>Checks whether two arrays are the same length, treating
1350     * {@code null} arrays as length {@code 0}.
1351     *
1352     * @param array1 the first array, may be {@code null}
1353     * @param array2 the second array, may be {@code null}
1354     * @return {@code true} if length of arrays matches, treating
1355     *  {@code null} as an empty array
1356     */
1357    public static boolean isSameLength(final boolean[] array1, final boolean[] array2) {
1358        return getLength(array1) == getLength(array2);
1359    }
1360
1361    //-----------------------------------------------------------------------
1362    /**
1363     * <p>Returns the length of the specified array.
1364     * This method can deal with {@code Object} arrays and with primitive arrays.
1365     *
1366     * <p>If the input array is {@code null}, {@code 0} is returned.
1367     *
1368     * <pre>
1369     * ArrayUtils.getLength(null)            = 0
1370     * ArrayUtils.getLength([])              = 0
1371     * ArrayUtils.getLength([null])          = 1
1372     * ArrayUtils.getLength([true, false])   = 2
1373     * ArrayUtils.getLength([1, 2, 3])       = 3
1374     * ArrayUtils.getLength(["a", "b", "c"]) = 3
1375     * </pre>
1376     *
1377     * @param array  the array to retrieve the length from, may be null
1378     * @return The length of the array, or {@code 0} if the array is {@code null}
1379     * @throws IllegalArgumentException if the object argument is not an array.
1380     * @since 2.1
1381     */
1382    public static int getLength(final Object array) {
1383        if (array == null) {
1384            return 0;
1385        }
1386        return Array.getLength(array);
1387    }
1388
1389    /**
1390     * <p>Checks whether two arrays are the same type taking into account
1391     * multi-dimensional arrays.
1392     *
1393     * @param array1 the first array, must not be {@code null}
1394     * @param array2 the second array, must not be {@code null}
1395     * @return {@code true} if type of arrays matches
1396     * @throws IllegalArgumentException if either array is {@code null}
1397     */
1398    public static boolean isSameType(final Object array1, final Object array2) {
1399        if (array1 == null || array2 == null) {
1400            throw new IllegalArgumentException("The Array must not be null");
1401        }
1402        return array1.getClass().getName().equals(array2.getClass().getName());
1403    }
1404
1405    // Reverse
1406    //-----------------------------------------------------------------------
1407    /**
1408     * <p>Reverses the order of the given array.
1409     *
1410     * <p>There is no special handling for multi-dimensional arrays.
1411     *
1412     * <p>This method does nothing for a {@code null} input array.
1413     *
1414     * @param array  the array to reverse, may be {@code null}
1415     */
1416    public static void reverse(final Object[] array) {
1417        if (array == null) {
1418            return;
1419        }
1420        reverse(array, 0, array.length);
1421    }
1422
1423    /**
1424     * <p>Reverses the order of the given array.
1425     *
1426     * <p>This method does nothing for a {@code null} input array.
1427     *
1428     * @param array  the array to reverse, may be {@code null}
1429     */
1430    public static void reverse(final long[] array) {
1431        if (array == null) {
1432            return;
1433        }
1434        reverse(array, 0, array.length);
1435    }
1436
1437    /**
1438     * <p>Reverses the order of the given array.
1439     *
1440     * <p>This method does nothing for a {@code null} input array.
1441     *
1442     * @param array  the array to reverse, may be {@code null}
1443     */
1444    public static void reverse(final int[] array) {
1445        if (array == null) {
1446            return;
1447        }
1448        reverse(array, 0, array.length);
1449    }
1450
1451    /**
1452     * <p>Reverses the order of the given array.
1453     *
1454     * <p>This method does nothing for a {@code null} input array.
1455     *
1456     * @param array  the array to reverse, may be {@code null}
1457     */
1458    public static void reverse(final short[] array) {
1459        if (array == null) {
1460            return;
1461        }
1462        reverse(array, 0, array.length);
1463    }
1464
1465    /**
1466     * <p>Reverses the order of the given array.
1467     *
1468     * <p>This method does nothing for a {@code null} input array.
1469     *
1470     * @param array  the array to reverse, may be {@code null}
1471     */
1472    public static void reverse(final char[] array) {
1473        if (array == null) {
1474            return;
1475        }
1476        reverse(array, 0, array.length);
1477    }
1478
1479    /**
1480     * <p>Reverses the order of the given array.
1481     *
1482     * <p>This method does nothing for a {@code null} input array.
1483     *
1484     * @param array  the array to reverse, may be {@code null}
1485     */
1486    public static void reverse(final byte[] array) {
1487        if (array == null) {
1488            return;
1489        }
1490        reverse(array, 0, array.length);
1491    }
1492
1493    /**
1494     * <p>Reverses the order of the given array.
1495     *
1496     * <p>This method does nothing for a {@code null} input array.
1497     *
1498     * @param array  the array to reverse, may be {@code null}
1499     */
1500    public static void reverse(final double[] array) {
1501        if (array == null) {
1502            return;
1503        }
1504        reverse(array, 0, array.length);
1505    }
1506
1507    /**
1508     * <p>Reverses the order of the given array.
1509     *
1510     * <p>This method does nothing for a {@code null} input array.
1511     *
1512     * @param array  the array to reverse, may be {@code null}
1513     */
1514    public static void reverse(final float[] array) {
1515        if (array == null) {
1516            return;
1517        }
1518        reverse(array, 0, array.length);
1519    }
1520
1521    /**
1522     * <p>Reverses the order of the given array.
1523     *
1524     * <p>This method does nothing for a {@code null} input array.
1525     *
1526     * @param array  the array to reverse, may be {@code null}
1527     */
1528    public static void reverse(final boolean[] array) {
1529        if (array == null) {
1530            return;
1531        }
1532        reverse(array, 0, array.length);
1533    }
1534
1535    /**
1536     * <p>
1537     * Reverses the order of the given array in the given range.
1538     * 
1539     * <p>
1540     * This method does nothing for a {@code null} input array.
1541     * 
1542     * @param array
1543     *            the array to reverse, may be {@code null}
1544     * @param startIndexInclusive
1545     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1546     *            change.
1547     * @param endIndexExclusive
1548     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1549     *            change. Overvalue (&gt;array.length) is demoted to array length.
1550     * @since 3.2
1551     */
1552    public static void reverse(final boolean[] array, final int startIndexInclusive, final int endIndexExclusive) {
1553        if (array == null) {
1554            return;
1555        }
1556        int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1557        int j = Math.min(array.length, endIndexExclusive) - 1;
1558        boolean tmp;
1559        while (j > i) {
1560            tmp = array[j];
1561            array[j] = array[i];
1562            array[i] = tmp;
1563            j--;
1564            i++;
1565        }
1566    }
1567
1568    /**
1569     * <p>
1570     * Reverses the order of the given array in the given range.
1571     * 
1572     * <p>
1573     * This method does nothing for a {@code null} input array.
1574     * 
1575     * @param array
1576     *            the array to reverse, may be {@code null}
1577     * @param startIndexInclusive
1578     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1579     *            change.
1580     * @param endIndexExclusive
1581     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1582     *            change. Overvalue (&gt;array.length) is demoted to array length.
1583     * @since 3.2
1584     */
1585    public static void reverse(final byte[] array, final int startIndexInclusive, final int endIndexExclusive) {
1586        if (array == null) {
1587            return;
1588        }
1589        int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1590        int j = Math.min(array.length, endIndexExclusive) - 1;
1591        byte tmp;
1592        while (j > i) {
1593            tmp = array[j];
1594            array[j] = array[i];
1595            array[i] = tmp;
1596            j--;
1597            i++;
1598        }
1599    }
1600
1601    /**
1602     * <p>
1603     * Reverses the order of the given array in the given range.
1604     * 
1605     * <p>
1606     * This method does nothing for a {@code null} input array.
1607     * 
1608     * @param array
1609     *            the array to reverse, may be {@code null}
1610     * @param startIndexInclusive
1611     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1612     *            change.
1613     * @param endIndexExclusive
1614     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1615     *            change. Overvalue (&gt;array.length) is demoted to array length.
1616     * @since 3.2
1617     */
1618    public static void reverse(final char[] array, final int startIndexInclusive, final int endIndexExclusive) {
1619        if (array == null) {
1620            return;
1621        }
1622        int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1623        int j = Math.min(array.length, endIndexExclusive) - 1;
1624        char tmp;
1625        while (j > i) {
1626            tmp = array[j];
1627            array[j] = array[i];
1628            array[i] = tmp;
1629            j--;
1630            i++;
1631        }
1632    }
1633
1634    /**
1635     * <p>
1636     * Reverses the order of the given array in the given range.
1637     * 
1638     * <p>
1639     * This method does nothing for a {@code null} input array.
1640     * 
1641     * @param array
1642     *            the array to reverse, may be {@code null}
1643     * @param startIndexInclusive
1644     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1645     *            change.
1646     * @param endIndexExclusive
1647     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1648     *            change. Overvalue (&gt;array.length) is demoted to array length.
1649     * @since 3.2
1650     */
1651    public static void reverse(final double[] array, final int startIndexInclusive, final int endIndexExclusive) {
1652        if (array == null) {
1653            return;
1654        }
1655        int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1656        int j = Math.min(array.length, endIndexExclusive) - 1;
1657        double tmp;
1658        while (j > i) {
1659            tmp = array[j];
1660            array[j] = array[i];
1661            array[i] = tmp;
1662            j--;
1663            i++;
1664        }
1665    }
1666
1667    /**
1668     * <p>
1669     * Reverses the order of the given array in the given range.
1670     * 
1671     * <p>
1672     * This method does nothing for a {@code null} input array.
1673     * 
1674     * @param array
1675     *            the array to reverse, may be {@code null}
1676     * @param startIndexInclusive
1677     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1678     *            change.
1679     * @param endIndexExclusive
1680     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1681     *            change. Overvalue (&gt;array.length) is demoted to array length.
1682     * @since 3.2
1683     */
1684    public static void reverse(final float[] array, final int startIndexInclusive, final int endIndexExclusive) {
1685        if (array == null) {
1686            return;
1687        }
1688        int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1689        int j = Math.min(array.length, endIndexExclusive) - 1;
1690        float tmp;
1691        while (j > i) {
1692            tmp = array[j];
1693            array[j] = array[i];
1694            array[i] = tmp;
1695            j--;
1696            i++;
1697        }
1698    }
1699
1700    /**
1701     * <p>
1702     * Reverses the order of the given array in the given range.
1703     * 
1704     * <p>
1705     * This method does nothing for a {@code null} input array.
1706     * 
1707     * @param array
1708     *            the array to reverse, may be {@code null}
1709     * @param startIndexInclusive
1710     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1711     *            change.
1712     * @param endIndexExclusive
1713     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1714     *            change. Overvalue (&gt;array.length) is demoted to array length.
1715     * @since 3.2
1716     */
1717    public static void reverse(final int[] array, final int startIndexInclusive, final int endIndexExclusive) {
1718        if (array == null) {
1719            return;
1720        }
1721        int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1722        int j = Math.min(array.length, endIndexExclusive) - 1;
1723        int tmp;
1724        while (j > i) {
1725            tmp = array[j];
1726            array[j] = array[i];
1727            array[i] = tmp;
1728            j--;
1729            i++;
1730        }
1731    }
1732
1733    /**
1734     * <p>
1735     * Reverses the order of the given array in the given range.
1736     * 
1737     * <p>
1738     * This method does nothing for a {@code null} input array.
1739     * 
1740     * @param array
1741     *            the array to reverse, may be {@code null}
1742     * @param startIndexInclusive
1743     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1744     *            change.
1745     * @param endIndexExclusive
1746     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1747     *            change. Overvalue (&gt;array.length) is demoted to array length.
1748     * @since 3.2
1749     */
1750    public static void reverse(final long[] array, final int startIndexInclusive, final int endIndexExclusive) {
1751        if (array == null) {
1752            return;
1753        }
1754        int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1755        int j = Math.min(array.length, endIndexExclusive) - 1;
1756        long tmp;
1757        while (j > i) {
1758            tmp = array[j];
1759            array[j] = array[i];
1760            array[i] = tmp;
1761            j--;
1762            i++;
1763        }
1764    }
1765
1766    /**
1767     * <p>
1768     * Reverses the order of the given array in the given range.
1769     * 
1770     * <p>
1771     * This method does nothing for a {@code null} input array.
1772     * 
1773     * @param array
1774     *            the array to reverse, may be {@code null}
1775     * @param startIndexInclusive
1776     *            the starting index. Under value (&lt;0) is promoted to 0, over value (&gt;array.length) results in no
1777     *            change.
1778     * @param endIndexExclusive
1779     *            elements up to endIndex-1 are reversed in the array. Under value (&lt; start index) results in no
1780     *            change. Over value (&gt;array.length) is demoted to array length.
1781     * @since 3.2
1782     */
1783    public static void reverse(final Object[] array, final int startIndexInclusive, final 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        Object 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     * 
1803     * <p>
1804     * This method does nothing for a {@code null} input array.
1805     * 
1806     * @param array
1807     *            the array to reverse, may be {@code null}
1808     * @param startIndexInclusive
1809     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
1810     *            change.
1811     * @param endIndexExclusive
1812     *            elements up to endIndex-1 are reversed in the array. Undervalue (&lt; start index) results in no
1813     *            change. Overvalue (&gt;array.length) is demoted to array length.
1814     * @since 3.2
1815     */
1816    public static void reverse(final short[] array, final int startIndexInclusive, final int endIndexExclusive) {
1817        if (array == null) {
1818            return;
1819        }
1820        int i = startIndexInclusive < 0 ? 0 : startIndexInclusive;
1821        int j = Math.min(array.length, endIndexExclusive) - 1;
1822        short tmp;
1823        while (j > i) {
1824            tmp = array[j];
1825            array[j] = array[i];
1826            array[i] = tmp;
1827            j--;
1828            i++;
1829        }
1830    }
1831
1832    // Swap
1833    //-----------------------------------------------------------------------
1834    /**
1835     * Swaps two elements in the given array.
1836     *
1837     * <p>There is no special handling for multi-dimensional arrays. This method
1838     * does nothing for a {@code null} or empty input array or for overflow indices.
1839     * Negative indices are promoted to 0(zero).</p>
1840     * 
1841     * Examples:
1842     * <ul>
1843     *     <li>ArrayUtils.swap(["1", "2", "3"], 0, 2) -&gt; ["3", "2", "1"]</li>
1844     *     <li>ArrayUtils.swap(["1", "2", "3"], 0, 0) -&gt; ["1", "2", "3"]</li>
1845     *     <li>ArrayUtils.swap(["1", "2", "3"], 1, 0) -&gt; ["2", "1", "3"]</li>
1846     *     <li>ArrayUtils.swap(["1", "2", "3"], 0, 5) -&gt; ["1", "2", "3"]</li>
1847     *     <li>ArrayUtils.swap(["1", "2", "3"], -1, 1) -&gt; ["2", "1", "3"]</li>
1848     * </ul>
1849     *
1850     * @param array the array to swap, may be {@code null}
1851     * @param offset1 the index of the first element to swap
1852     * @param offset2 the index of the second element to swap
1853     * @since 3.5
1854     */
1855    public static void swap(final Object[] array, int offset1, int offset2) {
1856        if (array == null || array.length == 0) {
1857            return;
1858        }
1859        swap(array, offset1, offset2, 1);
1860    }
1861
1862    /**
1863     * Swaps two elements in the given long array.
1864     *
1865     * <p>There is no special handling for multi-dimensional arrays. This method
1866     * does nothing for a {@code null} or empty input array or for overflow indices.
1867     * Negative indices are promoted to 0(zero).</p>
1868     *
1869     * Examples:
1870     * <ul>
1871     *     <li>ArrayUtils.swap([true, false, true], 0, 2) -&gt; [true, false, true]</li>
1872     *     <li>ArrayUtils.swap([true, false, true], 0, 0) -&gt; [true, false, true]</li>
1873     *     <li>ArrayUtils.swap([true, false, true], 1, 0) -&gt; [false, true, true]</li>
1874     *     <li>ArrayUtils.swap([true, false, true], 0, 5) -&gt; [true, false, true]</li>
1875     *     <li>ArrayUtils.swap([true, false, true], -1, 1) -&gt; [false, true, true]</li>
1876     * </ul>
1877     *
1878     *
1879     * @param array  the array to swap, may be {@code null}
1880     * @param offset1 the index of the first element to swap
1881     * @param offset2 the index of the second element to swap
1882     * @since 3.5
1883     */
1884    public static void swap(final long[] array, int offset1, int offset2) {
1885        if (array == null || array.length == 0) {
1886            return;
1887        }
1888        swap(array, offset1, offset2, 1);
1889    }
1890
1891    /**
1892     * Swaps two elements in the given int array.
1893     *
1894     * <p>There is no special handling for multi-dimensional arrays. This method
1895     * does nothing for a {@code null} or empty input array or for overflow indices.
1896     * Negative indices are promoted to 0(zero).</p>
1897     *
1898     * Examples:
1899     * <ul>
1900     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
1901     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
1902     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
1903     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
1904     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
1905     * </ul>
1906     *
1907     * @param array  the array to swap, may be {@code null}
1908     * @param offset1 the index of the first element to swap
1909     * @param offset2 the index of the second element to swap
1910     * @since 3.5
1911     */
1912    public static void swap(final int[] array, int offset1, int offset2) {
1913        if (array == null || array.length == 0) {
1914            return;
1915        }
1916        swap(array, offset1, offset2, 1);
1917    }
1918
1919    /**
1920     * Swaps two elements in the given short array.
1921     *
1922     * <p>There is no special handling for multi-dimensional arrays. This method
1923     * does nothing for a {@code null} or empty input array or for overflow indices.
1924     * Negative indices are promoted to 0(zero).</p>
1925     *
1926     * Examples:
1927     * <ul>
1928     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
1929     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
1930     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
1931     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
1932     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
1933     * </ul>
1934     *
1935     * @param array  the array to swap, may be {@code null}
1936     * @param offset1 the index of the first element to swap
1937     * @param offset2 the index of the second element to swap
1938     * @since 3.5
1939     */
1940    public static void swap(final short[] array, int offset1, int offset2) {
1941        if (array == null || array.length == 0) {
1942            return;
1943        }
1944        swap(array, offset1, offset2, 1);
1945    }
1946
1947    /**
1948     * Swaps two elements in the given char array.
1949     *
1950     * <p>There is no special handling for multi-dimensional arrays. This method
1951     * does nothing for a {@code null} or empty input array or for overflow indices.
1952     * Negative indices are promoted to 0(zero).</p>
1953     * 
1954     * Examples:
1955     * <ul>
1956     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
1957     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
1958     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
1959     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
1960     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
1961     * </ul>
1962     *
1963     * @param array  the array to swap, may be {@code null}
1964     * @param offset1 the index of the first element to swap
1965     * @param offset2 the index of the second element to swap
1966     * @since 3.5
1967     */
1968    public static void swap(final char[] array, int offset1, int offset2) {
1969        if (array == null || array.length == 0) {
1970            return;
1971        }
1972        swap(array, offset1, offset2, 1);
1973    }
1974
1975    /**
1976     * Swaps two elements in the given byte array.
1977     *
1978     * <p>There is no special handling for multi-dimensional arrays. This method
1979     * does nothing for a {@code null} or empty input array or for overflow indices.
1980     * Negative indices are promoted to 0(zero).</p>
1981     *
1982     * Examples:
1983     * <ul>
1984     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
1985     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
1986     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
1987     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
1988     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
1989     * </ul>
1990     *
1991     * @param array  the array to swap, may be {@code null}
1992     * @param offset1 the index of the first element to swap
1993     * @param offset2 the index of the second element to swap
1994     * @since 3.5
1995     */
1996    public static void swap(final byte[] array, int offset1, int offset2) {
1997        if (array == null || array.length == 0) {
1998            return;
1999        }
2000        swap(array, offset1, offset2, 1);
2001    }
2002
2003    /**
2004     * Swaps two elements in the given double array.
2005     *
2006     * <p>There is no special handling for multi-dimensional arrays. This method
2007     * does nothing for a {@code null} or empty input array or for overflow indices.
2008     * Negative indices are promoted to 0(zero).</p>
2009     *
2010     * Examples:
2011     * <ul>
2012     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
2013     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
2014     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
2015     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
2016     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
2017     * </ul>
2018     *
2019     * @param array  the array to swap, may be {@code null}
2020     * @param offset1 the index of the first element to swap
2021     * @param offset2 the index of the second element to swap
2022     * @since 3.5
2023     */
2024    public static void swap(final double[] array, int offset1, int offset2) {
2025        if (array == null || array.length == 0) {
2026            return;
2027        }
2028        swap(array, offset1, offset2, 1);
2029    }
2030
2031    /**
2032     * Swaps two elements in the given float array.
2033     *
2034     * <p>There is no special handling for multi-dimensional arrays. This method
2035     * does nothing for a {@code null} or empty input array or for overflow indices.
2036     * Negative indices are promoted to 0(zero).</p>
2037     *
2038     * Examples:
2039     * <ul>
2040     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
2041     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
2042     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
2043     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
2044     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
2045     * </ul>
2046     *
2047     * @param array  the array to swap, may be {@code null}
2048     * @param offset1 the index of the first element to swap
2049     * @param offset2 the index of the second element to swap
2050     * @since 3.5
2051     */
2052    public static void swap(final float[] array, int offset1, int offset2) {
2053        if (array == null || array.length == 0) {
2054            return;
2055        }
2056        swap(array, offset1, offset2, 1);
2057    }
2058
2059    /**
2060     * Swaps two elements in the given boolean array.
2061     *
2062     * <p>There is no special handling for multi-dimensional arrays. This method
2063     * does nothing for a {@code null} or empty input array or for overflow indices.
2064     * Negative indices are promoted to 0(zero).</p>
2065     *
2066     * Examples:
2067     * <ul>
2068     *     <li>ArrayUtils.swap([1, 2, 3], 0, 2) -&gt; [3, 2, 1]</li>
2069     *     <li>ArrayUtils.swap([1, 2, 3], 0, 0) -&gt; [1, 2, 3]</li>
2070     *     <li>ArrayUtils.swap([1, 2, 3], 1, 0) -&gt; [2, 1, 3]</li>
2071     *     <li>ArrayUtils.swap([1, 2, 3], 0, 5) -&gt; [1, 2, 3]</li>
2072     *     <li>ArrayUtils.swap([1, 2, 3], -1, 1) -&gt; [2, 1, 3]</li>
2073     * </ul>
2074     *
2075     * @param array  the array to swap, may be {@code null}
2076     * @param offset1 the index of the first element to swap
2077     * @param offset2 the index of the second element to swap
2078     * @since 3.5
2079     */
2080    public static void swap(final boolean[] array, int offset1, int offset2) {
2081        if (array == null || array.length == 0) {
2082            return;
2083        }
2084        swap(array, offset1, offset2, 1);
2085    }
2086
2087    /**
2088     * Swaps a series of elements in the given boolean array.
2089     *
2090     * <p>This method does nothing for a {@code null} or empty input array or
2091     * for overflow indices. Negative indices are promoted to 0(zero). If any
2092     * of the sub-arrays to swap falls outside of the given array, then the
2093     * swap is stopped at the end of the array and as many as possible elements
2094     * are swapped.</p>
2095     * 
2096     * Examples:
2097     * <ul>
2098     *     <li>ArrayUtils.swap([true, false, true, false], 0, 2, 1) -&gt; [true, false, true, false]</li>
2099     *     <li>ArrayUtils.swap([true, false, true, false], 0, 0, 1) -&gt; [true, false, true, false]</li>
2100     *     <li>ArrayUtils.swap([true, false, true, false], 0, 2, 2) -&gt; [true, false, true, false]</li>
2101     *     <li>ArrayUtils.swap([true, false, true, false], -3, 2, 2) -&gt; [true, false, true, false]</li>
2102     *     <li>ArrayUtils.swap([true, false, true, false], 0, 3, 3) -&gt; [false, false, true, true]</li>
2103     * </ul>
2104     *
2105     * @param array the array to swap, may be {@code null}
2106     * @param offset1 the index of the first element in the series to swap
2107     * @param offset2 the index of the second element in the series to swap
2108     * @param len the number of elements to swap starting with the given indices
2109     * @since 3.5
2110     */
2111    public static void swap(final boolean[] array, int offset1, int offset2, int len) {
2112        if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
2113            return;
2114        }
2115        if (offset1 < 0) {
2116            offset1 = 0;
2117        }
2118        if (offset2 < 0) {
2119            offset2 = 0;
2120        }
2121        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
2122        for (int i = 0; i < len; i++, offset1++, offset2++) {
2123            boolean aux = array[offset1];
2124            array[offset1] = array[offset2];
2125            array[offset2] = aux;
2126        }
2127    }
2128
2129    /**
2130     * Swaps a series of elements in the given byte array.
2131     *
2132     * <p>This method does nothing for a {@code null} or empty input array or
2133     * for overflow indices. Negative indices are promoted to 0(zero). If any
2134     * of the sub-arrays to swap falls outside of the given array, then the
2135     * swap is stopped at the end of the array and as many as possible elements
2136     * are swapped.</p>
2137     *
2138     * Examples:
2139     * <ul>
2140     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
2141     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
2142     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
2143     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
2144     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
2145     * </ul>
2146     *
2147     * @param array the array to swap, may be {@code null}
2148     * @param offset1 the index of the first element in the series to swap
2149     * @param offset2 the index of the second element in the series to swap
2150     * @param len the number of elements to swap starting with the given indices
2151     * @since 3.5
2152     */
2153    public static void swap(final byte[] array, int offset1, int offset2, int len) {
2154        if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
2155            return;
2156        }
2157        if (offset1 < 0) {
2158            offset1 = 0;
2159        }
2160        if (offset2 < 0) {
2161            offset2 = 0;
2162        }
2163        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
2164        for (int i = 0; i < len; i++, offset1++, offset2++) {
2165            byte aux = array[offset1];
2166            array[offset1] = array[offset2];
2167            array[offset2] = aux;
2168        }
2169    }
2170
2171    /**
2172     * Swaps a series of elements in the given char array.
2173     *
2174     * <p>This method does nothing for a {@code null} or empty input array or
2175     * for overflow indices. Negative indices are promoted to 0(zero). If any
2176     * of the sub-arrays to swap falls outside of the given array, then the
2177     * swap is stopped at the end of the array and as many as possible elements
2178     * are swapped.</p>
2179     * 
2180     * Examples:
2181     * <ul>
2182     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
2183     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
2184     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
2185     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
2186     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
2187     * </ul>
2188     *
2189     * @param array the array to swap, may be {@code null}
2190     * @param offset1 the index of the first element in the series to swap
2191     * @param offset2 the index of the second element in the series to swap
2192     * @param len the number of elements to swap starting with the given indices
2193     * @since 3.5
2194     */
2195    public static void swap(final char[] array, int offset1, int offset2, int len) {
2196        if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
2197            return;
2198        }
2199        if (offset1 < 0) {
2200            offset1 = 0;
2201        }
2202        if (offset2 < 0) {
2203            offset2 = 0;
2204        }
2205        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
2206        for (int i = 0; i < len; i++, offset1++, offset2++) {
2207            char aux = array[offset1];
2208            array[offset1] = array[offset2];
2209            array[offset2] = aux;
2210        }
2211    }
2212
2213    /**
2214     * Swaps a series of elements in the given double array.
2215     *
2216     * <p>This method does nothing for a {@code null} or empty input array or
2217     * for overflow indices. Negative indices are promoted to 0(zero). If any
2218     * of the sub-arrays to swap falls outside of the given array, then the
2219     * swap is stopped at the end of the array and as many as possible elements
2220     * are swapped.</p>
2221     *
2222     * Examples:
2223     * <ul>
2224     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
2225     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
2226     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
2227     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
2228     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
2229     * </ul>
2230     *
2231     * @param array the array to swap, may be {@code null}
2232     * @param offset1 the index of the first element in the series to swap
2233     * @param offset2 the index of the second element in the series to swap
2234     * @param len the number of elements to swap starting with the given indices
2235     * @since 3.5
2236     */
2237    public static void swap(final double[] array,  int offset1, int offset2, int len) {
2238        if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
2239            return;
2240        }
2241        if (offset1 < 0) {
2242            offset1 = 0;
2243        }
2244        if (offset2 < 0) {
2245            offset2 = 0;
2246        }
2247        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
2248        for (int i = 0; i < len; i++, offset1++, offset2++) {
2249            double aux = array[offset1];
2250            array[offset1] = array[offset2];
2251            array[offset2] = aux;
2252        }
2253    }
2254
2255    /**
2256     * Swaps a series of elements in the given float array.
2257     *
2258     * <p>This method does nothing for a {@code null} or empty input array or
2259     * for overflow indices. Negative indices are promoted to 0(zero). If any
2260     * of the sub-arrays to swap falls outside of the given array, then the
2261     * swap is stopped at the end of the array and as many as possible elements
2262     * are swapped.</p>
2263     *
2264     * Examples:
2265     * <ul>
2266     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
2267     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
2268     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
2269     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
2270     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
2271     * </ul>
2272     *
2273     * @param array the array to swap, may be {@code null}
2274     * @param offset1 the index of the first element in the series to swap
2275     * @param offset2 the index of the second element in the series to swap
2276     * @param len the number of elements to swap starting with the given indices
2277     * @since 3.5
2278     */
2279    public static void swap(final float[] array, int offset1, int offset2, int len) {
2280        if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
2281            return;
2282        }
2283        if (offset1 < 0) {
2284            offset1 = 0;
2285        }
2286        if (offset2 < 0) {
2287            offset2 = 0;
2288        }
2289        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
2290        for (int i = 0; i < len; i++, offset1++, offset2++) {
2291            float aux = array[offset1];
2292            array[offset1] = array[offset2];
2293            array[offset2] = aux;
2294        }
2295
2296    }
2297
2298    /**
2299     * Swaps a series of elements in the given int array.
2300     *
2301     * <p>This method does nothing for a {@code null} or empty input array or
2302     * for overflow indices. Negative indices are promoted to 0(zero). If any
2303     * of the sub-arrays to swap falls outside of the given array, then the
2304     * swap is stopped at the end of the array and as many as possible elements
2305     * are swapped.</p>
2306     *
2307     * Examples:
2308     * <ul>
2309     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
2310     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
2311     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
2312     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
2313     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
2314     * </ul>
2315     *
2316     * @param array the array to swap, may be {@code null}
2317     * @param offset1 the index of the first element in the series to swap
2318     * @param offset2 the index of the second element in the series to swap
2319     * @param len the number of elements to swap starting with the given indices
2320     * @since 3.5
2321     */
2322    public static void swap(final int[] array,  int offset1, int offset2, int len) {
2323        if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
2324            return;
2325        }
2326        if (offset1 < 0) {
2327            offset1 = 0;
2328        }
2329        if (offset2 < 0) {
2330            offset2 = 0;
2331        }
2332        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
2333        for (int i = 0; i < len; i++, offset1++, offset2++) {
2334            int aux = array[offset1];
2335            array[offset1] = array[offset2];
2336            array[offset2] = aux;
2337        }
2338    }
2339
2340    /**
2341     * Swaps a series of elements in the given long array.
2342     *
2343     * <p>This method does nothing for a {@code null} or empty input array or
2344     * for overflow indices. Negative indices are promoted to 0(zero). If any
2345     * of the sub-arrays to swap falls outside of the given array, then the
2346     * swap is stopped at the end of the array and as many as possible elements
2347     * are swapped.</p>
2348     *
2349     * Examples:
2350     * <ul>
2351     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
2352     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
2353     *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
2354     *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
2355     *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
2356     * </ul>
2357     *
2358     * @param array the array to swap, may be {@code null}
2359     * @param offset1 the index of the first element in the series to swap
2360     * @param offset2 the index of the second element in the series to swap
2361     * @param len the number of elements to swap starting with the given indices
2362     * @since 3.5
2363     */
2364    public static void swap(final long[] array,  int offset1, int offset2, int len) {
2365        if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
2366            return;
2367        }
2368        if (offset1 < 0) {
2369            offset1 = 0;
2370        }
2371        if (offset2 < 0) {
2372            offset2 = 0;
2373        }
2374        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
2375        for (int i = 0; i < len; i++, offset1++, offset2++) {
2376            long aux = array[offset1];
2377            array[offset1] = array[offset2];
2378            array[offset2] = aux;
2379        }
2380    }
2381
2382    /**
2383     * Swaps a series of elements in the given array.
2384     *
2385     * <p>This method does nothing for a {@code null} or empty input array or
2386     * for overflow indices. Negative indices are promoted to 0(zero). If any
2387     * of the sub-arrays to swap falls outside of the given array, then the
2388     * swap is stopped at the end of the array and as many as possible elements
2389     * are swapped.</p>
2390     *
2391     * Examples:
2392     * <ul>
2393     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 0, 2, 1) -&gt; ["3", "2", "1", "4"]</li>
2394     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 0, 0, 1) -&gt; ["1", "2", "3", "4"]</li>
2395     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 2, 0, 2) -&gt; ["3", "4", "1", "2"]</li>
2396     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], -3, 2, 2) -&gt; ["3", "4", "1", "2"]</li>
2397     *     <li>ArrayUtils.swap(["1", "2", "3", "4"], 0, 3, 3) -&gt; ["4", "2", "3", "1"]</li>
2398     * </ul>
2399     *
2400     * @param array the array to swap, may be {@code null}
2401     * @param offset1 the index of the first element in the series to swap
2402     * @param offset2 the index of the second element in the series to swap
2403     * @param len the number of elements to swap starting with the given indices
2404     * @since 3.5
2405     */
2406    public static void swap(final Object[] array,  int offset1, int offset2, int len) {
2407        if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
2408            return;
2409        }
2410        if (offset1 < 0) {
2411            offset1 = 0;
2412        }
2413        if (offset2 < 0) {
2414            offset2 = 0;
2415        }
2416        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
2417        for (int i = 0; i < len; i++, offset1++, offset2++) {
2418            Object aux = array[offset1];
2419            array[offset1] = array[offset2];
2420            array[offset2] = aux;
2421        }
2422    }
2423
2424   /**
2425    * Swaps a series of elements in the given short array.
2426    *
2427    * <p>This method does nothing for a {@code null} or empty input array or
2428    * for overflow indices. Negative indices are promoted to 0(zero). If any
2429    * of the sub-arrays to swap falls outside of the given array, then the
2430    * swap is stopped at the end of the array and as many as possible elements
2431    * are swapped.</p>
2432    *
2433    * Examples:
2434    * <ul>
2435    *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 2, 1) -&gt; [3, 2, 1, 4]</li>
2436    *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 0, 1) -&gt; [1, 2, 3, 4]</li>
2437    *     <li>ArrayUtils.swap([1, 2, 3, 4], 2, 0, 2) -&gt; [3, 4, 1, 2]</li>
2438    *     <li>ArrayUtils.swap([1, 2, 3, 4], -3, 2, 2) -&gt; [3, 4, 1, 2]</li>
2439    *     <li>ArrayUtils.swap([1, 2, 3, 4], 0, 3, 3) -&gt; [4, 2, 3, 1]</li>
2440    * </ul>
2441    *
2442    * @param array the array to swap, may be {@code null}
2443    * @param offset1 the index of the first element in the series to swap
2444    * @param offset2 the index of the second element in the series to swap
2445    * @param len the number of elements to swap starting with the given indices
2446    * @since 3.5
2447    */
2448    public static void swap(final short[] array,  int offset1, int offset2, int len) {
2449        if (array == null || array.length == 0 || offset1 >= array.length || offset2 >= array.length) {
2450            return;
2451        }
2452        if (offset1 < 0) {
2453            offset1 = 0;
2454        }
2455        if (offset2 < 0) {
2456            offset2 = 0;
2457        }
2458        if (offset1 == offset2) {
2459            return;
2460        }
2461        len = Math.min(Math.min(len, array.length - offset1), array.length - offset2);
2462        for (int i = 0; i < len; i++, offset1++, offset2++) {
2463            short aux = array[offset1];
2464            array[offset1] = array[offset2];
2465            array[offset2] = aux;
2466        }
2467    }
2468
2469    // Shift
2470    //-----------------------------------------------------------------------
2471    /**
2472     * Shifts the order of the given array.
2473     *
2474     * <p>There is no special handling for multi-dimensional arrays. This method
2475     * does nothing for {@code null} or empty input arrays.</p>
2476     *
2477     * @param array  the array to shift, may be {@code null}
2478     * @param offset
2479     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
2480     *          rotate, than the effective offset is modulo the number of elements to rotate.
2481     * @since 3.5
2482     */
2483    public static void shift(final Object[] array, int offset) {
2484        if (array == null) {
2485            return;
2486        }
2487        shift(array, 0, array.length, offset);
2488    }
2489
2490    /**
2491     * Shifts the order of the given long array.
2492     *
2493     * <p>There is no special handling for multi-dimensional arrays. This method
2494     * does nothing for {@code null} or empty input arrays.</p>
2495     *
2496     * @param array  the array to shift, may be {@code null}
2497     * @param offset
2498     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
2499     *          rotate, than the effective offset is modulo the number of elements to rotate.
2500     * @since 3.5
2501     */
2502    public static void shift(final long[] array, int offset) {
2503        if (array == null) {
2504            return;
2505        }
2506        shift(array, 0, array.length, offset);
2507    }
2508
2509    /**
2510     * Shifts the order of the given int array.
2511     *
2512     * <p>There is no special handling for multi-dimensional arrays. This method
2513     * does nothing for {@code null} or empty input arrays.</p>
2514     *
2515     * @param array  the array to shift, may be {@code null}
2516     * @param offset
2517     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
2518     *          rotate, than the effective offset is modulo the number of elements to rotate.
2519     * @since 3.5
2520     */
2521    public static void shift(final int[] array, int offset) {
2522        if (array == null) {
2523            return;
2524        }
2525        shift(array, 0, array.length, offset);
2526    }
2527
2528    /**
2529     * Shifts the order of the given short array.
2530     *
2531     * <p>There is no special handling for multi-dimensional arrays. This method
2532     * does nothing for {@code null} or empty input arrays.</p>
2533     *
2534     * @param array  the array to shift, may be {@code null}
2535     * @param offset
2536     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
2537     *          rotate, than the effective offset is modulo the number of elements to rotate.
2538     * @since 3.5
2539     */
2540    public static void shift(final short[] array, int offset) {
2541        if (array == null) {
2542            return;
2543        }
2544        shift(array, 0, array.length, offset);
2545    }
2546
2547    /**
2548     * Shifts the order of the given char array.
2549     *
2550     * <p>There is no special handling for multi-dimensional arrays. This method
2551     * does nothing for {@code null} or empty input arrays.</p>
2552     *
2553     * @param array  the array to shift, may be {@code null}
2554     * @param offset
2555     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
2556     *          rotate, than the effective offset is modulo the number of elements to rotate.
2557     * @since 3.5
2558     */
2559    public static void shift(final char[] array, int offset) {
2560        if (array == null) {
2561            return;
2562        }
2563        shift(array, 0, array.length, offset);
2564    }
2565
2566    /**
2567     * Shifts the order of the given byte array.
2568     *
2569     * <p>There is no special handling for multi-dimensional arrays. This method
2570     * does nothing for {@code null} or empty input arrays.</p>
2571     *
2572     * @param array  the array to shift, may be {@code null}
2573     * @param offset
2574     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
2575     *          rotate, than the effective offset is modulo the number of elements to rotate.
2576     * @since 3.5
2577     */
2578    public static void shift(final byte[] array, int offset) {
2579        if (array == null) {
2580            return;
2581        }
2582        shift(array, 0, array.length, offset);
2583    }
2584
2585    /**
2586     * Shifts the order of the given double array.
2587     *
2588     * <p>There is no special handling for multi-dimensional arrays. This method
2589     * does nothing for {@code null} or empty input arrays.</p>
2590     *
2591     * @param array  the array to shift, may be {@code null}
2592     * @param offset
2593     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
2594     *          rotate, than the effective offset is modulo the number of elements to rotate.
2595     * @since 3.5
2596     */
2597    public static void shift(final double[] array, int offset) {
2598        if (array == null) {
2599            return;
2600        }
2601        shift(array, 0, array.length, offset);
2602    }
2603
2604    /**
2605     * Shifts the order of the given float array.
2606     *
2607     * <p>There is no special handling for multi-dimensional arrays. This method
2608     * does nothing for {@code null} or empty input arrays.</p>
2609     *
2610     * @param array  the array to shift, may be {@code null}
2611     * @param offset
2612     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
2613     *          rotate, than the effective offset is modulo the number of elements to rotate.
2614     * @since 3.5
2615     */
2616    public static void shift(final float[] array, int offset) {
2617        if (array == null) {
2618            return;
2619        }
2620        shift(array, 0, array.length, offset);
2621    }
2622
2623    /**
2624     * Shifts the order of the given boolean array.
2625     *
2626     * <p>There is no special handling for multi-dimensional arrays. This method
2627     * does nothing for {@code null} or empty input arrays.</p>
2628     *
2629     * @param array  the array to shift, may be {@code null}
2630     * @param offset
2631     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
2632     *          rotate, than the effective offset is modulo the number of elements to rotate.
2633     * @since 3.5
2634     */
2635    public static void shift(final boolean[] array, int offset) {
2636        if (array == null) {
2637            return;
2638        }
2639        shift(array, 0, array.length, offset);
2640    }
2641
2642    /**
2643     * Shifts the order of a series of elements in the given boolean array.
2644     *
2645     * <p>There is no special handling for multi-dimensional arrays. This method
2646     * does nothing for {@code null} or empty input arrays.</p>
2647     * 
2648     * @param array
2649     *            the array to shift, may be {@code null}
2650     * @param startIndexInclusive
2651     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
2652     *            change.
2653     * @param endIndexExclusive
2654     *            elements up to endIndex-1 are shiftd in the array. Undervalue (&lt; start index) results in no
2655     *            change. Overvalue (&gt;array.length) is demoted to array length.
2656     * @param offset
2657     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
2658     *          rotate, than the effective offset is modulo the number of elements to rotate.
2659     * @since 3.5
2660     */
2661    public static void shift(final boolean[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
2662        if (array == null) {
2663            return;
2664        }
2665        if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
2666            return;
2667        }
2668        if (startIndexInclusive < 0) {
2669            startIndexInclusive = 0;
2670        } 
2671        if (endIndexExclusive >= array.length) {
2672            endIndexExclusive = array.length;
2673        }        
2674        int n = endIndexExclusive - startIndexInclusive;
2675        if (n <= 1) {
2676            return;
2677        }
2678        offset %= n;
2679        if (offset < 0) {
2680            offset += n;
2681        }
2682        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
2683        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
2684        while (n > 1 && offset > 0) {
2685            int n_offset = n - offset;
2686            
2687            if (offset > n_offset) {
2688                swap(array, startIndexInclusive, startIndexInclusive + n - n_offset,  n_offset);
2689                n = offset;
2690                offset -= n_offset;
2691            } else if (offset < n_offset) {
2692                swap(array, startIndexInclusive, startIndexInclusive + n_offset,  offset);
2693                startIndexInclusive += offset;
2694                n = n_offset;
2695            } else {
2696                swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
2697                break;
2698            }
2699        }
2700    }
2701
2702    /**
2703     * Shifts the order of a series of elements in the given byte array.
2704     *
2705     * <p>There is no special handling for multi-dimensional arrays. This method
2706     * does nothing for {@code null} or empty input arrays.</p>
2707     * 
2708     * @param array
2709     *            the array to shift, may be {@code null}
2710     * @param startIndexInclusive
2711     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
2712     *            change.
2713     * @param endIndexExclusive
2714     *            elements up to endIndex-1 are shiftd in the array. Undervalue (&lt; start index) results in no
2715     *            change. Overvalue (&gt;array.length) is demoted to array length.
2716     * @param offset
2717     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
2718     *          rotate, than the effective offset is modulo the number of elements to rotate.
2719     * @since 3.5
2720     */
2721    public static void shift(final byte[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
2722        if (array == null) {
2723            return;
2724        }
2725        if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
2726            return;
2727        }
2728        if (startIndexInclusive < 0) {
2729            startIndexInclusive = 0;
2730        } 
2731        if (endIndexExclusive >= array.length) {
2732            endIndexExclusive = array.length;
2733        }        
2734        int n = endIndexExclusive - startIndexInclusive;
2735        if (n <= 1) {
2736            return;
2737        }
2738        offset %= n;
2739        if (offset < 0) {
2740            offset += n;
2741        }
2742        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
2743        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
2744        while (n > 1 && offset > 0) {
2745            int n_offset = n - offset;
2746            
2747            if (offset > n_offset) {
2748                swap(array, startIndexInclusive, startIndexInclusive + n - n_offset,  n_offset);
2749                n = offset;
2750                offset -= n_offset;
2751            } else if (offset < n_offset) {
2752                swap(array, startIndexInclusive, startIndexInclusive + n_offset,  offset);
2753                startIndexInclusive += offset;
2754                n = n_offset;
2755            } else {
2756                swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
2757                break;
2758            }
2759        }
2760    }
2761
2762    /**
2763     * Shifts the order of a series of elements in the given char array.
2764     *
2765     * <p>There is no special handling for multi-dimensional arrays. This method
2766     * does nothing for {@code null} or empty input arrays.</p>
2767     *
2768     * @param array
2769     *            the array to shift, may be {@code null}
2770     * @param startIndexInclusive
2771     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
2772     *            change.
2773     * @param endIndexExclusive
2774     *            elements up to endIndex-1 are shiftd in the array. Undervalue (&lt; start index) results in no
2775     *            change. Overvalue (&gt;array.length) is demoted to array length.
2776     * @param offset
2777     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
2778     *          rotate, than the effective offset is modulo the number of elements to rotate.
2779     * @since 3.5
2780     */
2781    public static void shift(final char[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
2782        if (array == null) {
2783            return;
2784        }
2785        if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
2786            return;
2787        }
2788        if (startIndexInclusive < 0) {
2789            startIndexInclusive = 0;
2790        } 
2791        if (endIndexExclusive >= array.length) {
2792            endIndexExclusive = array.length;
2793        }        
2794        int n = endIndexExclusive - startIndexInclusive;
2795        if (n <= 1) {
2796            return;
2797        }
2798        offset %= n;
2799        if (offset < 0) {
2800            offset += n;
2801        }
2802        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
2803        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
2804        while (n > 1 && offset > 0) {
2805            int n_offset = n - offset;
2806            
2807            if (offset > n_offset) {
2808                swap(array, startIndexInclusive, startIndexInclusive + n - n_offset,  n_offset);
2809                n = offset;
2810                offset -= n_offset;
2811            } else if (offset < n_offset) {
2812                swap(array, startIndexInclusive, startIndexInclusive + n_offset,  offset);
2813                startIndexInclusive += offset;
2814                n = n_offset;
2815            } else {
2816                swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
2817                break;
2818            }
2819        }
2820    }
2821
2822    /**
2823     * Shifts the order of a series of elements in the given double array.
2824     *
2825     * <p>There is no special handling for multi-dimensional arrays. This method
2826     * does nothing for {@code null} or empty input arrays.</p>
2827     *
2828     * @param array
2829     *            the array to shift, may be {@code null}
2830     * @param startIndexInclusive
2831     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
2832     *            change.
2833     * @param endIndexExclusive
2834     *            elements up to endIndex-1 are shiftd in the array. Undervalue (&lt; start index) results in no
2835     *            change. Overvalue (&gt;array.length) is demoted to array length.
2836     * @param offset
2837     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
2838     *          rotate, than the effective offset is modulo the number of elements to rotate.
2839     * @since 3.5
2840     */
2841    public static void shift(final double[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
2842        if (array == null) {
2843            return;
2844        }
2845        if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
2846            return;
2847        }
2848        if (startIndexInclusive < 0) {
2849            startIndexInclusive = 0;
2850        } 
2851        if (endIndexExclusive >= array.length) {
2852            endIndexExclusive = array.length;
2853        }        
2854        int n = endIndexExclusive - startIndexInclusive;
2855        if (n <= 1) {
2856            return;
2857        }
2858        offset %= n;
2859        if (offset < 0) {
2860            offset += n;
2861        }
2862        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
2863        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
2864        while (n > 1 && offset > 0) {
2865            int n_offset = n - offset;
2866            
2867            if (offset > n_offset) {
2868                swap(array, startIndexInclusive, startIndexInclusive + n - n_offset,  n_offset);
2869                n = offset;
2870                offset -= n_offset;
2871            } else if (offset < n_offset) {
2872                swap(array, startIndexInclusive, startIndexInclusive + n_offset,  offset);
2873                startIndexInclusive += offset;
2874                n = n_offset;
2875            } else {
2876                swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
2877                break;
2878            }
2879        }
2880    }
2881
2882    /**
2883     * Shifts the order of a series of elements in the given float array.
2884     *
2885     * <p>There is no special handling for multi-dimensional arrays. This method
2886     * does nothing for {@code null} or empty input arrays.</p>
2887     *
2888     * @param array
2889     *            the array to shift, may be {@code null}
2890     * @param startIndexInclusive
2891     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
2892     *            change.
2893     * @param endIndexExclusive
2894     *            elements up to endIndex-1 are shiftd in the array. Undervalue (&lt; start index) results in no
2895     *            change. Overvalue (&gt;array.length) is demoted to array length.
2896     * @param offset
2897     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
2898     *          rotate, than the effective offset is modulo the number of elements to rotate.
2899     * @since 3.5
2900     */
2901    public static void shift(final float[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
2902        if (array == null) {
2903            return;
2904        }
2905        if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
2906            return;
2907        }
2908        if (startIndexInclusive < 0) {
2909            startIndexInclusive = 0;
2910        } 
2911        if (endIndexExclusive >= array.length) {
2912            endIndexExclusive = array.length;
2913        }        
2914        int n = endIndexExclusive - startIndexInclusive;
2915        if (n <= 1) {
2916            return;
2917        }
2918        offset %= n;
2919        if (offset < 0) {
2920            offset += n;
2921        }
2922        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
2923        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
2924        while (n > 1 && offset > 0) {
2925            int n_offset = n - offset;
2926            
2927            if (offset > n_offset) {
2928                swap(array, startIndexInclusive, startIndexInclusive + n - n_offset,  n_offset);
2929                n = offset;
2930                offset -= n_offset;
2931            } else if (offset < n_offset) {
2932                swap(array, startIndexInclusive, startIndexInclusive + n_offset,  offset);
2933                startIndexInclusive += offset;
2934                n = n_offset;
2935            } else {
2936                swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
2937                break;
2938            }
2939        }
2940    }
2941
2942    /**
2943     * Shifts the order of a series of elements in the given int array.
2944     *
2945     * <p>There is no special handling for multi-dimensional arrays. This method
2946     * does nothing for {@code null} or empty input arrays.</p>
2947     *
2948     * @param array
2949     *            the array to shift, may be {@code null}
2950     * @param startIndexInclusive
2951     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
2952     *            change.
2953     * @param endIndexExclusive
2954     *            elements up to endIndex-1 are shiftd in the array. Undervalue (&lt; start index) results in no
2955     *            change. Overvalue (&gt;array.length) is demoted to array length.
2956     * @param offset
2957     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
2958     *          rotate, than the effective offset is modulo the number of elements to rotate.
2959     * @since 3.5
2960     */
2961    public static void shift(final int[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
2962        if (array == null) {
2963            return;
2964        }
2965        if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
2966            return;
2967        }
2968        if (startIndexInclusive < 0) {
2969            startIndexInclusive = 0;
2970        } 
2971        if (endIndexExclusive >= array.length) {
2972            endIndexExclusive = array.length;
2973        }        
2974        int n = endIndexExclusive - startIndexInclusive;
2975        if (n <= 1) {
2976            return;
2977        }
2978        offset %= n;
2979        if (offset < 0) {
2980            offset += n;
2981        }
2982        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
2983        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
2984        while (n > 1 && offset > 0) {
2985            int n_offset = n - offset;
2986            
2987            if (offset > n_offset) {
2988                swap(array, startIndexInclusive, startIndexInclusive + n - n_offset,  n_offset);
2989                n = offset;
2990                offset -= n_offset;
2991            } else if (offset < n_offset) {
2992                swap(array, startIndexInclusive, startIndexInclusive + n_offset,  offset);
2993                startIndexInclusive += offset;
2994                n = n_offset;
2995            } else {
2996                swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
2997                break;
2998            }
2999        }
3000    }
3001
3002    /**
3003     * Shifts the order of a series of elements in the given long array.
3004     *
3005     * <p>There is no special handling for multi-dimensional arrays. This method
3006     * does nothing for {@code null} or empty input arrays.</p>
3007     *
3008     * @param array
3009     *            the array to shift, may be {@code null}
3010     * @param startIndexInclusive
3011     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
3012     *            change.
3013     * @param endIndexExclusive
3014     *            elements up to endIndex-1 are shiftd in the array. Undervalue (&lt; start index) results in no
3015     *            change. Overvalue (&gt;array.length) is demoted to array length.
3016     * @param offset
3017     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
3018     *          rotate, than the effective offset is modulo the number of elements to rotate.
3019     * @since 3.5
3020     */
3021    public static void shift(final long[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
3022        if (array == null) {
3023            return;
3024        }
3025        if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
3026            return;
3027        }
3028        if (startIndexInclusive < 0) {
3029            startIndexInclusive = 0;
3030        } 
3031        if (endIndexExclusive >= array.length) {
3032            endIndexExclusive = array.length;
3033        }        
3034        int n = endIndexExclusive - startIndexInclusive;
3035        if (n <= 1) {
3036            return;
3037        }
3038        offset %= n;
3039        if (offset < 0) {
3040            offset += n;
3041        }
3042        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
3043        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
3044        while (n > 1 && offset > 0) {
3045            int n_offset = n - offset;
3046            
3047            if (offset > n_offset) {
3048                swap(array, startIndexInclusive, startIndexInclusive + n - n_offset,  n_offset);
3049                n = offset;
3050                offset -= n_offset;
3051            } else if (offset < n_offset) {
3052                swap(array, startIndexInclusive, startIndexInclusive + n_offset,  offset);
3053                startIndexInclusive += offset;
3054                n = n_offset;
3055            } else {
3056                swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
3057                break;
3058            }
3059        }
3060    }
3061
3062    /**
3063     * Shifts the order of a series of elements in the given array.
3064     *
3065     * <p>There is no special handling for multi-dimensional arrays. This method
3066     * does nothing for {@code null} or empty input arrays.</p>
3067     *
3068     * @param array
3069     *            the array to shift, may be {@code null}
3070     * @param startIndexInclusive
3071     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
3072     *            change.
3073     * @param endIndexExclusive
3074     *            elements up to endIndex-1 are shiftd in the array. Undervalue (&lt; start index) results in no
3075     *            change. Overvalue (&gt;array.length) is demoted to array length.
3076     * @param offset
3077     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
3078     *          rotate, than the effective offset is modulo the number of elements to rotate.
3079     * @since 3.5
3080     */
3081    public static void shift(final Object[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
3082        if (array == null) {
3083            return;
3084        }
3085        if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
3086            return;
3087        }
3088        if (startIndexInclusive < 0) {
3089            startIndexInclusive = 0;
3090        } 
3091        if (endIndexExclusive >= array.length) {
3092            endIndexExclusive = array.length;
3093        }        
3094        int n = endIndexExclusive - startIndexInclusive;
3095        if (n <= 1) {
3096            return;
3097        }
3098        offset %= n;
3099        if (offset < 0) {
3100            offset += n;
3101        }
3102        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
3103        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
3104        while (n > 1 && offset > 0) {
3105            int n_offset = n - offset;
3106            
3107            if (offset > n_offset) {
3108                swap(array, startIndexInclusive, startIndexInclusive + n - n_offset,  n_offset);
3109                n = offset;
3110                offset -= n_offset;
3111            } else if (offset < n_offset) {
3112                swap(array, startIndexInclusive, startIndexInclusive + n_offset,  offset);
3113                startIndexInclusive += offset;
3114                n = n_offset;
3115            } else {
3116                swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
3117                break;
3118            }
3119        }
3120    }
3121
3122    /**
3123     * Shifts the order of a series of elements in the given short array.
3124     *
3125     * <p>There is no special handling for multi-dimensional arrays. This method
3126     * does nothing for {@code null} or empty input arrays.</p>
3127     *
3128     * @param array
3129     *            the array to shift, may be {@code null}
3130     * @param startIndexInclusive
3131     *            the starting index. Undervalue (&lt;0) is promoted to 0, overvalue (&gt;array.length) results in no
3132     *            change.
3133     * @param endIndexExclusive
3134     *            elements up to endIndex-1 are shifted in the array. Undervalue (&lt; start index) results in no
3135     *            change. Overvalue (&gt;array.length) is demoted to array length.
3136     * @param offset
3137     *          The number of positions to rotate the elements.  If the offset is larger than the number of elements to
3138     *          rotate, than the effective offset is modulo the number of elements to rotate.
3139     * @since 3.5
3140     */
3141    public static void shift(final short[] array, int startIndexInclusive, int endIndexExclusive, int offset) {
3142        if (array == null) {
3143            return;
3144        }
3145        if (startIndexInclusive >= array.length - 1 || endIndexExclusive <= 0) {
3146            return;
3147        }
3148        if (startIndexInclusive < 0) {
3149            startIndexInclusive = 0;
3150        } 
3151        if (endIndexExclusive >= array.length) {
3152            endIndexExclusive = array.length;
3153        }        
3154        int n = endIndexExclusive - startIndexInclusive;
3155        if (n <= 1) {
3156            return;
3157        }
3158        offset %= n;
3159        if (offset < 0) {
3160            offset += n;
3161        }
3162        // For algorithm explanations and proof of O(n) time complexity and O(1) space complexity
3163        // see https://beradrian.wordpress.com/2015/04/07/shift-an-array-in-on-in-place/
3164        while (n > 1 && offset > 0) {
3165            int n_offset = n - offset;
3166            
3167            if (offset > n_offset) {
3168                swap(array, startIndexInclusive, startIndexInclusive + n - n_offset,  n_offset);
3169                n = offset;
3170                offset -= n_offset;
3171            } else if (offset < n_offset) {
3172                swap(array, startIndexInclusive, startIndexInclusive + n_offset,  offset);
3173                startIndexInclusive += offset;
3174                n = n_offset;
3175            } else {
3176                swap(array, startIndexInclusive, startIndexInclusive + n_offset, offset);
3177                break;
3178            }
3179        }
3180    }
3181
3182    // IndexOf search
3183    // ----------------------------------------------------------------------
3184
3185    // Object IndexOf
3186    //-----------------------------------------------------------------------
3187    /**
3188     * <p>Finds the index of the given object in the array.
3189     *
3190     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3191     *
3192     * @param array  the array to search through for the object, may be {@code null}
3193     * @param objectToFind  the object to find, may be {@code null}
3194     * @return the index of the object within the array,
3195     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3196     */
3197    public static int indexOf(final Object[] array, final Object objectToFind) {
3198        return indexOf(array, objectToFind, 0);
3199    }
3200
3201    /**
3202     * <p>Finds the index of the given object in the array starting at the given index.
3203     *
3204     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3205     *
3206     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
3207     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3208     *
3209     * @param array  the array to search through for the object, may be {@code null}
3210     * @param objectToFind  the object to find, may be {@code null}
3211     * @param startIndex  the index to start searching at
3212     * @return the index of the object within the array starting at the index,
3213     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3214     */
3215    public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
3216        if (array == null) {
3217            return INDEX_NOT_FOUND;
3218        }
3219        if (startIndex < 0) {
3220            startIndex = 0;
3221        }
3222        if (objectToFind == null) {
3223            for (int i = startIndex; i < array.length; i++) {
3224                if (array[i] == null) {
3225                    return i;
3226                }
3227            }
3228        } else {
3229            for (int i = startIndex; i < array.length; i++) {
3230                if (objectToFind.equals(array[i])) {
3231                    return i;
3232                }
3233            }
3234        }
3235        return INDEX_NOT_FOUND;
3236    }
3237
3238    /**
3239     * <p>Finds the last index of the given object within the array.
3240     *
3241     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3242     *
3243     * @param array  the array to travers backwords looking for the object, may be {@code null}
3244     * @param objectToFind  the object to find, may be {@code null}
3245     * @return the last index of the object within the array,
3246     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3247     */
3248    public static int lastIndexOf(final Object[] array, final Object objectToFind) {
3249        return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
3250    }
3251
3252    /**
3253     * <p>Finds the last index of the given object in the array starting at the given index.
3254     *
3255     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3256     *
3257     * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than
3258     * the array length will search from the end of the array.
3259     *
3260     * @param array  the array to traverse for looking for the object, may be {@code null}
3261     * @param objectToFind  the object to find, may be {@code null}
3262     * @param startIndex  the start index to travers backwards from
3263     * @return the last index of the object within the array,
3264     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3265     */
3266    public static int lastIndexOf(final Object[] array, final Object objectToFind, int startIndex) {
3267        if (array == null) {
3268            return INDEX_NOT_FOUND;
3269        }
3270        if (startIndex < 0) {
3271            return INDEX_NOT_FOUND;
3272        } else if (startIndex >= array.length) {
3273            startIndex = array.length - 1;
3274        }
3275        if (objectToFind == null) {
3276            for (int i = startIndex; i >= 0; i--) {
3277                if (array[i] == null) {
3278                    return i;
3279                }
3280            }
3281        } else if (array.getClass().getComponentType().isInstance(objectToFind)) {
3282            for (int i = startIndex; i >= 0; i--) {
3283                if (objectToFind.equals(array[i])) {
3284                    return i;
3285                }
3286            }
3287        }
3288        return INDEX_NOT_FOUND;
3289    }
3290
3291    /**
3292     * <p>Checks if the object is in the given array.
3293     *
3294     * <p>The method returns {@code false} if a {@code null} array is passed in.
3295     *
3296     * @param array  the array to search through
3297     * @param objectToFind  the object to find
3298     * @return {@code true} if the array contains the object
3299     */
3300    public static boolean contains(final Object[] array, final Object objectToFind) {
3301        return indexOf(array, objectToFind) != INDEX_NOT_FOUND;
3302    }
3303
3304    // long IndexOf
3305    //-----------------------------------------------------------------------
3306    /**
3307     * <p>Finds the index of the given value in the array.
3308     *
3309     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3310     *
3311     * @param array  the array to search through for the object, may be {@code null}
3312     * @param valueToFind  the value to find
3313     * @return the index of the value within the array,
3314     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3315     */
3316    public static int indexOf(final long[] array, final long valueToFind) {
3317        return indexOf(array, valueToFind, 0);
3318    }
3319
3320    /**
3321     * <p>Finds the index of the given value in the array starting at the given index.
3322     *
3323     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3324     *
3325     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
3326     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3327     *
3328     * @param array  the array to search through for the object, may be {@code null}
3329     * @param valueToFind  the value to find
3330     * @param startIndex  the index to start searching at
3331     * @return the index of the value within the array,
3332     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3333     */
3334    public static int indexOf(final long[] array, final long valueToFind, int startIndex) {
3335        if (array == null) {
3336            return INDEX_NOT_FOUND;
3337        }
3338        if (startIndex < 0) {
3339            startIndex = 0;
3340        }
3341        for (int i = startIndex; i < array.length; i++) {
3342            if (valueToFind == array[i]) {
3343                return i;
3344            }
3345        }
3346        return INDEX_NOT_FOUND;
3347    }
3348
3349    /**
3350     * <p>Finds the last index of the given value within the array.
3351     *
3352     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3353     *
3354     * @param array  the array to travers backwords looking for the object, may be {@code null}
3355     * @param valueToFind  the object to find
3356     * @return the last index of the value within the array,
3357     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3358     */
3359    public static int lastIndexOf(final long[] array, final long valueToFind) {
3360        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
3361    }
3362
3363    /**
3364     * <p>Finds the last index of the given value in the array starting at the given index.
3365     *
3366     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3367     *
3368     * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
3369     * array length will search from the end of the array.
3370     *
3371     * @param array  the array to traverse for looking for the object, may be {@code null}
3372     * @param valueToFind  the value to find
3373     * @param startIndex  the start index to travers backwards from
3374     * @return the last index of the value within the array,
3375     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3376     */
3377    public static int lastIndexOf(final long[] array, final long valueToFind, int startIndex) {
3378        if (array == null) {
3379            return INDEX_NOT_FOUND;
3380        }
3381        if (startIndex < 0) {
3382            return INDEX_NOT_FOUND;
3383        } else if (startIndex >= array.length) {
3384            startIndex = array.length - 1;
3385        }
3386        for (int i = startIndex; i >= 0; i--) {
3387            if (valueToFind == array[i]) {
3388                return i;
3389            }
3390        }
3391        return INDEX_NOT_FOUND;
3392    }
3393
3394    /**
3395     * <p>Checks if the value is in the given array.
3396     *
3397     * <p>The method returns {@code false} if a {@code null} array is passed in.
3398     *
3399     * @param array  the array to search through
3400     * @param valueToFind  the value to find
3401     * @return {@code true} if the array contains the object
3402     */
3403    public static boolean contains(final long[] array, final long valueToFind) {
3404        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
3405    }
3406
3407    // int IndexOf
3408    //-----------------------------------------------------------------------
3409    /**
3410     * <p>Finds the index of the given value in the array.
3411     *
3412     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3413     *
3414     * @param array  the array to search through for the object, may be {@code null}
3415     * @param valueToFind  the value to find
3416     * @return the index of the value within the array,
3417     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3418     */
3419    public static int indexOf(final int[] array, final int valueToFind) {
3420        return indexOf(array, valueToFind, 0);
3421    }
3422
3423    /**
3424     * <p>Finds the index of the given value in the array starting at the given index.
3425     *
3426     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3427     *
3428     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
3429     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3430     *
3431     * @param array  the array to search through for the object, may be {@code null}
3432     * @param valueToFind  the value to find
3433     * @param startIndex  the index to start searching at
3434     * @return the index of the value within the array,
3435     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3436     */
3437    public static int indexOf(final int[] array, final int valueToFind, int startIndex) {
3438        if (array == null) {
3439            return INDEX_NOT_FOUND;
3440        }
3441        if (startIndex < 0) {
3442            startIndex = 0;
3443        }
3444        for (int i = startIndex; i < array.length; i++) {
3445            if (valueToFind == array[i]) {
3446                return i;
3447            }
3448        }
3449        return INDEX_NOT_FOUND;
3450    }
3451
3452    /**
3453     * <p>Finds the last index of the given value within the array.
3454     *
3455     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3456     *
3457     * @param array  the array to travers backwords looking for the object, may be {@code null}
3458     * @param valueToFind  the object to find
3459     * @return the last index of the value within the array,
3460     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3461     */
3462    public static int lastIndexOf(final int[] array, final int valueToFind) {
3463        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
3464    }
3465
3466    /**
3467     * <p>Finds the last index of the given value in the array starting at the given index.
3468     *
3469     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3470     *
3471     * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
3472     * array length will search from the end of the array.
3473     *
3474     * @param array  the array to traverse for looking for the object, may be {@code null}
3475     * @param valueToFind  the value to find
3476     * @param startIndex  the start index to travers backwards from
3477     * @return the last index of the value within the array,
3478     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3479     */
3480    public static int lastIndexOf(final int[] array, final int valueToFind, int startIndex) {
3481        if (array == null) {
3482            return INDEX_NOT_FOUND;
3483        }
3484        if (startIndex < 0) {
3485            return INDEX_NOT_FOUND;
3486        } else if (startIndex >= array.length) {
3487            startIndex = array.length - 1;
3488        }
3489        for (int i = startIndex; i >= 0; i--) {
3490            if (valueToFind == array[i]) {
3491                return i;
3492            }
3493        }
3494        return INDEX_NOT_FOUND;
3495    }
3496
3497    /**
3498     * <p>Checks if the value is in the given array.
3499     *
3500     * <p>The method returns {@code false} if a {@code null} array is passed in.
3501     *
3502     * @param array  the array to search through
3503     * @param valueToFind  the value to find
3504     * @return {@code true} if the array contains the object
3505     */
3506    public static boolean contains(final int[] array, final int valueToFind) {
3507        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
3508    }
3509
3510    // short IndexOf
3511    //-----------------------------------------------------------------------
3512    /**
3513     * <p>Finds the index of the given value in the array.
3514     *
3515     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3516     *
3517     * @param array  the array to search through for the object, may be {@code null}
3518     * @param valueToFind  the value to find
3519     * @return the index of the value within the array,
3520     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3521     */
3522    public static int indexOf(final short[] array, final short valueToFind) {
3523        return indexOf(array, valueToFind, 0);
3524    }
3525
3526    /**
3527     * <p>Finds the index of the given value in the array starting at the given index.
3528     *
3529     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3530     *
3531     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
3532     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3533     *
3534     * @param array  the array to search through for the object, may be {@code null}
3535     * @param valueToFind  the value to find
3536     * @param startIndex  the index to start searching at
3537     * @return the index of the value within the array,
3538     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3539     */
3540    public static int indexOf(final short[] array, final short valueToFind, int startIndex) {
3541        if (array == null) {
3542            return INDEX_NOT_FOUND;
3543        }
3544        if (startIndex < 0) {
3545            startIndex = 0;
3546        }
3547        for (int i = startIndex; i < array.length; i++) {
3548            if (valueToFind == array[i]) {
3549                return i;
3550            }
3551        }
3552        return INDEX_NOT_FOUND;
3553    }
3554
3555    /**
3556     * <p>Finds the last index of the given value within the array.
3557     *
3558     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3559     *
3560     * @param array  the array to travers backwords looking for the object, may be {@code null}
3561     * @param valueToFind  the object to find
3562     * @return the last index of the value within the array,
3563     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3564     */
3565    public static int lastIndexOf(final short[] array, final short valueToFind) {
3566        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
3567    }
3568
3569    /**
3570     * <p>Finds the last index of the given value in the array starting at the given index.
3571     *
3572     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3573     *
3574     * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
3575     * array length will search from the end of the array.
3576     *
3577     * @param array  the array to traverse for looking for the object, may be {@code null}
3578     * @param valueToFind  the value to find
3579     * @param startIndex  the start index to travers backwards from
3580     * @return the last index of the value within the array,
3581     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3582     */
3583    public static int lastIndexOf(final short[] array, final short valueToFind, int startIndex) {
3584        if (array == null) {
3585            return INDEX_NOT_FOUND;
3586        }
3587        if (startIndex < 0) {
3588            return INDEX_NOT_FOUND;
3589        } else if (startIndex >= array.length) {
3590            startIndex = array.length - 1;
3591        }
3592        for (int i = startIndex; i >= 0; i--) {
3593            if (valueToFind == array[i]) {
3594                return i;
3595            }
3596        }
3597        return INDEX_NOT_FOUND;
3598    }
3599
3600    /**
3601     * <p>Checks if the value is in the given array.
3602     *
3603     * <p>The method returns {@code false} if a {@code null} array is passed in.
3604     *
3605     * @param array  the array to search through
3606     * @param valueToFind  the value to find
3607     * @return {@code true} if the array contains the object
3608     */
3609    public static boolean contains(final short[] array, final short valueToFind) {
3610        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
3611    }
3612
3613    // char IndexOf
3614    //-----------------------------------------------------------------------
3615    /**
3616     * <p>Finds the index of the given value in the array.
3617     *
3618     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3619     *
3620     * @param array  the array to search through for the object, may be {@code null}
3621     * @param valueToFind  the value to find
3622     * @return the index of the value within the array,
3623     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3624     * @since 2.1
3625     */
3626    public static int indexOf(final char[] array, final char valueToFind) {
3627        return indexOf(array, valueToFind, 0);
3628    }
3629
3630    /**
3631     * <p>Finds the index of the given value in the array starting at the given index.
3632     *
3633     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3634     *
3635     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
3636     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3637     *
3638     * @param array  the array to search through for the object, may be {@code null}
3639     * @param valueToFind  the value to find
3640     * @param startIndex  the index to start searching at
3641     * @return the index of the value within the array,
3642     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3643     * @since 2.1
3644     */
3645    public static int indexOf(final char[] array, final char valueToFind, int startIndex) {
3646        if (array == null) {
3647            return INDEX_NOT_FOUND;
3648        }
3649        if (startIndex < 0) {
3650            startIndex = 0;
3651        }
3652        for (int i = startIndex; i < array.length; i++) {
3653            if (valueToFind == array[i]) {
3654                return i;
3655            }
3656        }
3657        return INDEX_NOT_FOUND;
3658    }
3659
3660    /**
3661     * <p>Finds the last index of the given value within the array.
3662     *
3663     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3664     *
3665     * @param array  the array to travers backwords looking for the object, may be {@code null}
3666     * @param valueToFind  the object to find
3667     * @return the last index of the value within the array,
3668     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3669     * @since 2.1
3670     */
3671    public static int lastIndexOf(final char[] array, final char valueToFind) {
3672        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
3673    }
3674
3675    /**
3676     * <p>Finds the last index of the given value in the array starting at the given index.
3677     *
3678     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3679     *
3680     * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
3681     * array length will search from the end of the array.
3682     *
3683     * @param array  the array to traverse for looking for the object, may be {@code null}
3684     * @param valueToFind  the value to find
3685     * @param startIndex  the start index to travers backwards from
3686     * @return the last index of the value within the array,
3687     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3688     * @since 2.1
3689     */
3690    public static int lastIndexOf(final char[] array, final char valueToFind, int startIndex) {
3691        if (array == null) {
3692            return INDEX_NOT_FOUND;
3693        }
3694        if (startIndex < 0) {
3695            return INDEX_NOT_FOUND;
3696        } else if (startIndex >= array.length) {
3697            startIndex = array.length - 1;
3698        }
3699        for (int i = startIndex; i >= 0; i--) {
3700            if (valueToFind == array[i]) {
3701                return i;
3702            }
3703        }
3704        return INDEX_NOT_FOUND;
3705    }
3706
3707    /**
3708     * <p>Checks if the value is in the given array.
3709     *
3710     * <p>The method returns {@code false} if a {@code null} array is passed in.
3711     *
3712     * @param array  the array to search through
3713     * @param valueToFind  the value to find
3714     * @return {@code true} if the array contains the object
3715     * @since 2.1
3716     */
3717    public static boolean contains(final char[] array, final char valueToFind) {
3718        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
3719    }
3720
3721    // byte IndexOf
3722    //-----------------------------------------------------------------------
3723    /**
3724     * <p>Finds the index of the given value in the array.
3725     *
3726     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3727     *
3728     * @param array  the array to search through for the object, may be {@code null}
3729     * @param valueToFind  the value to find
3730     * @return the index of the value within the array,
3731     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3732     */
3733    public static int indexOf(final byte[] array, final byte valueToFind) {
3734        return indexOf(array, valueToFind, 0);
3735    }
3736
3737    /**
3738     * <p>Finds the index of the given value in the array starting at the given index.
3739     *
3740     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3741     *
3742     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
3743     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3744     *
3745     * @param array  the array to search through for the object, may be {@code null}
3746     * @param valueToFind  the value to find
3747     * @param startIndex  the index to start searching at
3748     * @return the index of the value within the array,
3749     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3750     */
3751    public static int indexOf(final byte[] array, final byte valueToFind, int startIndex) {
3752        if (array == null) {
3753            return INDEX_NOT_FOUND;
3754        }
3755        if (startIndex < 0) {
3756            startIndex = 0;
3757        }
3758        for (int i = startIndex; i < array.length; i++) {
3759            if (valueToFind == array[i]) {
3760                return i;
3761            }
3762        }
3763        return INDEX_NOT_FOUND;
3764    }
3765
3766    /**
3767     * <p>Finds the last index of the given value within the array.
3768     *
3769     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3770     *
3771     * @param array  the array to travers backwords looking for the object, may be {@code null}
3772     * @param valueToFind  the object to find
3773     * @return the last index of the value within the array,
3774     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3775     */
3776    public static int lastIndexOf(final byte[] array, final byte valueToFind) {
3777        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
3778    }
3779
3780    /**
3781     * <p>Finds the last index of the given value in the array starting at the given index.
3782     *
3783     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3784     *
3785     * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
3786     * array length will search from the end of the array.
3787     *
3788     * @param array  the array to traverse for looking for the object, may be {@code null}
3789     * @param valueToFind  the value to find
3790     * @param startIndex  the start index to travers backwards from
3791     * @return the last index of the value within the array,
3792     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3793     */
3794    public static int lastIndexOf(final byte[] array, final byte valueToFind, int startIndex) {
3795        if (array == null) {
3796            return INDEX_NOT_FOUND;
3797        }
3798        if (startIndex < 0) {
3799            return INDEX_NOT_FOUND;
3800        } else if (startIndex >= array.length) {
3801            startIndex = array.length - 1;
3802        }
3803        for (int i = startIndex; i >= 0; i--) {
3804            if (valueToFind == array[i]) {
3805                return i;
3806            }
3807        }
3808        return INDEX_NOT_FOUND;
3809    }
3810
3811    /**
3812     * <p>Checks if the value is in the given array.
3813     *
3814     * <p>The method returns {@code false} if a {@code null} array is passed in.
3815     *
3816     * @param array  the array to search through
3817     * @param valueToFind  the value to find
3818     * @return {@code true} if the array contains the object
3819     */
3820    public static boolean contains(final byte[] array, final byte valueToFind) {
3821        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
3822    }
3823
3824    // double IndexOf
3825    //-----------------------------------------------------------------------
3826    /**
3827     * <p>Finds the index of the given value in the array.
3828     *
3829     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3830     *
3831     * @param array  the array to search through for the object, may be {@code null}
3832     * @param valueToFind  the value to find
3833     * @return the index of the value within the array,
3834     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3835     */
3836    public static int indexOf(final double[] array, final double valueToFind) {
3837        return indexOf(array, valueToFind, 0);
3838    }
3839
3840    /**
3841     * <p>Finds the index of the given value within a given tolerance in the array.
3842     * This method will return the index of the first value which falls between the region
3843     * defined by valueToFind - tolerance and valueToFind + tolerance.
3844     *
3845     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3846     *
3847     * @param array  the array to search through for the object, may be {@code null}
3848     * @param valueToFind  the value to find
3849     * @param tolerance tolerance of the search
3850     * @return the index of the value within the array,
3851     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3852     */
3853    public static int indexOf(final double[] array, final double valueToFind, final double tolerance) {
3854        return indexOf(array, valueToFind, 0, tolerance);
3855    }
3856
3857    /**
3858     * <p>Finds the index of the given value in the array starting at the given index.
3859     *
3860     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3861     *
3862     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
3863     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3864     *
3865     * @param array  the array to search through for the object, may be {@code null}
3866     * @param valueToFind  the value to find
3867     * @param startIndex  the index to start searching at
3868     * @return the index of the value within the array,
3869     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3870     */
3871    public static int indexOf(final double[] array, final double valueToFind, int startIndex) {
3872        if (ArrayUtils.isEmpty(array)) {
3873            return INDEX_NOT_FOUND;
3874        }
3875        if (startIndex < 0) {
3876            startIndex = 0;
3877        }
3878        for (int i = startIndex; i < array.length; i++) {
3879            if (valueToFind == array[i]) {
3880                return i;
3881            }
3882        }
3883        return INDEX_NOT_FOUND;
3884    }
3885
3886    /**
3887     * <p>Finds the index of the given value in the array starting at the given index.
3888     * This method will return the index of the first value which falls between the region
3889     * defined by valueToFind - tolerance and valueToFind + tolerance.
3890     *
3891     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3892     *
3893     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
3894     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
3895     *
3896     * @param array  the array to search through for the object, may be {@code null}
3897     * @param valueToFind  the value to find
3898     * @param startIndex  the index to start searching at
3899     * @param tolerance tolerance of the search
3900     * @return the index of the value within the array,
3901     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3902     */
3903    public static int indexOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
3904        if (ArrayUtils.isEmpty(array)) {
3905            return INDEX_NOT_FOUND;
3906        }
3907        if (startIndex < 0) {
3908            startIndex = 0;
3909        }
3910        final double min = valueToFind - tolerance;
3911        final double max = valueToFind + tolerance;
3912        for (int i = startIndex; i < array.length; i++) {
3913            if (array[i] >= min && array[i] <= max) {
3914                return i;
3915            }
3916        }
3917        return INDEX_NOT_FOUND;
3918    }
3919
3920    /**
3921     * <p>Finds the last index of the given value within the array.
3922     *
3923     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3924     *
3925     * @param array  the array to travers backwords looking for the object, may be {@code null}
3926     * @param valueToFind  the object to find
3927     * @return the last index of the value within the array,
3928     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3929     */
3930    public static int lastIndexOf(final double[] array, final double valueToFind) {
3931        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
3932    }
3933
3934    /**
3935     * <p>Finds the last index of the given value within a given tolerance in the array.
3936     * This method will return the index of the last value which falls between the region
3937     * defined by valueToFind - tolerance and valueToFind + tolerance.
3938     *
3939     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3940     *
3941     * @param array  the array to search through for the object, may be {@code null}
3942     * @param valueToFind  the value to find
3943     * @param tolerance tolerance of the search
3944     * @return the index of the value within the array,
3945     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3946     */
3947    public static int lastIndexOf(final double[] array, final double valueToFind, final double tolerance) {
3948        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance);
3949    }
3950
3951    /**
3952     * <p>Finds the last index of the given value in the array starting at the given index.
3953     *
3954     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3955     *
3956     * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
3957     * array length will search from the end of the array.
3958     *
3959     * @param array  the array to traverse for looking for the object, may be {@code null}
3960     * @param valueToFind  the value to find
3961     * @param startIndex  the start index to travers backwards from
3962     * @return the last index of the value within the array,
3963     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3964     */
3965    public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex) {
3966        if (ArrayUtils.isEmpty(array)) {
3967            return INDEX_NOT_FOUND;
3968        }
3969        if (startIndex < 0) {
3970            return INDEX_NOT_FOUND;
3971        } else if (startIndex >= array.length) {
3972            startIndex = array.length - 1;
3973        }
3974        for (int i = startIndex; i >= 0; i--) {
3975            if (valueToFind == array[i]) {
3976                return i;
3977            }
3978        }
3979        return INDEX_NOT_FOUND;
3980    }
3981
3982    /**
3983     * <p>Finds the last index of the given value in the array starting at the given index.
3984     * This method will return the index of the last value which falls between the region
3985     * defined by valueToFind - tolerance and valueToFind + tolerance.
3986     *
3987     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
3988     *
3989     * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
3990     * array length will search from the end of the array.
3991     *
3992     * @param array  the array to traverse for looking for the object, may be {@code null}
3993     * @param valueToFind  the value to find
3994     * @param startIndex  the start index to travers backwards from
3995     * @param tolerance  search for value within plus/minus this amount
3996     * @return the last index of the value within the array,
3997     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
3998     */
3999    public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex, final double tolerance) {
4000        if (ArrayUtils.isEmpty(array)) {
4001            return INDEX_NOT_FOUND;
4002        }
4003        if (startIndex < 0) {
4004            return INDEX_NOT_FOUND;
4005        } else if (startIndex >= array.length) {
4006            startIndex = array.length - 1;
4007        }
4008        final double min = valueToFind - tolerance;
4009        final double max = valueToFind + tolerance;
4010        for (int i = startIndex; i >= 0; i--) {
4011            if (array[i] >= min && array[i] <= max) {
4012                return i;
4013            }
4014        }
4015        return INDEX_NOT_FOUND;
4016    }
4017
4018    /**
4019     * <p>Checks if the value is in the given array.
4020     *
4021     * <p>The method returns {@code false} if a {@code null} array is passed in.
4022     *
4023     * @param array  the array to search through
4024     * @param valueToFind  the value to find
4025     * @return {@code true} if the array contains the object
4026     */
4027    public static boolean contains(final double[] array, final double valueToFind) {
4028        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
4029    }
4030
4031    /**
4032     * <p>Checks if a value falling within the given tolerance is in the
4033     * given array.  If the array contains a value within the inclusive range
4034     * defined by (value - tolerance) to (value + tolerance).
4035     *
4036     * <p>The method returns {@code false} if a {@code null} array
4037     * is passed in.
4038     *
4039     * @param array  the array to search
4040     * @param valueToFind  the value to find
4041     * @param tolerance  the array contains the tolerance of the search
4042     * @return true if value falling within tolerance is in array
4043     */
4044    public static boolean contains(final double[] array, final double valueToFind, final double tolerance) {
4045        return indexOf(array, valueToFind, 0, tolerance) != INDEX_NOT_FOUND;
4046    }
4047
4048    // float IndexOf
4049    //-----------------------------------------------------------------------
4050    /**
4051     * <p>Finds the index of the given value in the array.
4052     *
4053     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4054     *
4055     * @param array  the array to search through for the object, may be {@code null}
4056     * @param valueToFind  the value to find
4057     * @return the index of the value within the array,
4058     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4059     */
4060    public static int indexOf(final float[] array, final float valueToFind) {
4061        return indexOf(array, valueToFind, 0);
4062    }
4063
4064    /**
4065     * <p>Finds the index of the given value in the array starting at the given index.
4066     *
4067     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4068     *
4069     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
4070     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
4071     *
4072     * @param array  the array to search through for the object, may be {@code null}
4073     * @param valueToFind  the value to find
4074     * @param startIndex  the index to start searching at
4075     * @return the index of the value within the array,
4076     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4077     */
4078    public static int indexOf(final float[] array, final float valueToFind, int startIndex) {
4079        if (ArrayUtils.isEmpty(array)) {
4080            return INDEX_NOT_FOUND;
4081        }
4082        if (startIndex < 0) {
4083            startIndex = 0;
4084        }
4085        for (int i = startIndex; i < array.length; i++) {
4086            if (valueToFind == array[i]) {
4087                return i;
4088            }
4089        }
4090        return INDEX_NOT_FOUND;
4091    }
4092
4093    /**
4094     * <p>Finds the last index of the given value within the array.
4095     *
4096     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4097     *
4098     * @param array  the array to travers backwords looking for the object, may be {@code null}
4099     * @param valueToFind  the object to find
4100     * @return the last index of the value within the array,
4101     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4102     */
4103    public static int lastIndexOf(final float[] array, final float valueToFind) {
4104        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4105    }
4106
4107    /**
4108     * <p>Finds the last index of the given value in the array starting at the given index.
4109     *
4110     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4111     *
4112     * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
4113     * array length will search from the end of the array.
4114     *
4115     * @param array  the array to traverse for looking for the object, may be {@code null}
4116     * @param valueToFind  the value to find
4117     * @param startIndex  the start index to travers backwards from
4118     * @return the last index of the value within the array,
4119     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4120     */
4121    public static int lastIndexOf(final float[] array, final float valueToFind, int startIndex) {
4122        if (ArrayUtils.isEmpty(array)) {
4123            return INDEX_NOT_FOUND;
4124        }
4125        if (startIndex < 0) {
4126            return INDEX_NOT_FOUND;
4127        } else if (startIndex >= array.length) {
4128            startIndex = array.length - 1;
4129        }
4130        for (int i = startIndex; i >= 0; i--) {
4131            if (valueToFind == array[i]) {
4132                return i;
4133            }
4134        }
4135        return INDEX_NOT_FOUND;
4136    }
4137
4138    /**
4139     * <p>Checks if the value is in the given array.
4140     *
4141     * <p>The method returns {@code false} if a {@code null} array is passed in.
4142     *
4143     * @param array  the array to search through
4144     * @param valueToFind  the value to find
4145     * @return {@code true} if the array contains the object
4146     */
4147    public static boolean contains(final float[] array, final float valueToFind) {
4148        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
4149    }
4150
4151    // boolean IndexOf
4152    //-----------------------------------------------------------------------
4153    /**
4154     * <p>Finds the index of the given value in the array.
4155     *
4156     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4157     *
4158     * @param array  the array to search through for the object, may be {@code null}
4159     * @param valueToFind  the value to find
4160     * @return the index of the value within the array,
4161     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4162     */
4163    public static int indexOf(final boolean[] array, final boolean valueToFind) {
4164        return indexOf(array, valueToFind, 0);
4165    }
4166
4167    /**
4168     * <p>Finds the index of the given value in the array starting at the given index.
4169     *
4170     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4171     *
4172     * <p>A negative startIndex is treated as zero. A startIndex larger than the array
4173     * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).
4174     *
4175     * @param array  the array to search through for the object, may be {@code null}
4176     * @param valueToFind  the value to find
4177     * @param startIndex  the index to start searching at
4178     * @return the index of the value within the array,
4179     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null}
4180     *  array input
4181     */
4182    public static int indexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
4183        if (ArrayUtils.isEmpty(array)) {
4184            return INDEX_NOT_FOUND;
4185        }
4186        if (startIndex < 0) {
4187            startIndex = 0;
4188        }
4189        for (int i = startIndex; i < array.length; i++) {
4190            if (valueToFind == array[i]) {
4191                return i;
4192            }
4193        }
4194        return INDEX_NOT_FOUND;
4195    }
4196
4197    /**
4198     * <p>Finds the last index of the given value within the array.
4199     *
4200     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) if
4201     * {@code null} array input.
4202     *
4203     * @param array  the array to travers backwords looking for the object, may be {@code null}
4204     * @param valueToFind  the object to find
4205     * @return the last index of the value within the array,
4206     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4207     */
4208    public static int lastIndexOf(final boolean[] array, final boolean valueToFind) {
4209        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
4210    }
4211
4212    /**
4213     * <p>Finds the last index of the given value in the array starting at the given index.
4214     *
4215     * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.
4216     *
4217     * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than
4218     * the array length will search from the end of the array.
4219     *
4220     * @param array  the array to traverse for looking for the object, may be {@code null}
4221     * @param valueToFind  the value to find
4222     * @param startIndex  the start index to travers backwards from
4223     * @return the last index of the value within the array,
4224     *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
4225     */
4226    public static int lastIndexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
4227        if (ArrayUtils.isEmpty(array)) {
4228            return INDEX_NOT_FOUND;
4229        }
4230        if (startIndex < 0) {
4231            return INDEX_NOT_FOUND;
4232        } else if (startIndex >= array.length) {
4233            startIndex = array.length - 1;
4234        }
4235        for (int i = startIndex; i >= 0; i--) {
4236            if (valueToFind == array[i]) {
4237                return i;
4238            }
4239        }
4240        return INDEX_NOT_FOUND;
4241    }
4242
4243    /**
4244     * <p>Checks if the value is in the given array.
4245     *
4246     * <p>The method returns {@code false} if a {@code null} array is passed in.
4247     *
4248     * @param array  the array to search through
4249     * @param valueToFind  the value to find
4250     * @return {@code true} if the array contains the object
4251     */
4252    public static boolean contains(final boolean[] array, final boolean valueToFind) {
4253        return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
4254    }
4255
4256    // Primitive/Object array converters
4257    // ----------------------------------------------------------------------
4258
4259    // Character array converters
4260    // ----------------------------------------------------------------------
4261    /**
4262     * <p>Converts an array of object Characters to primitives.
4263     *
4264     * <p>This method returns {@code null} for a {@code null} input array.
4265     *
4266     * @param array  a {@code Character} array, may be {@code null}
4267     * @return a {@code char} array, {@code null} if null array input
4268     * @throws NullPointerException if array content is {@code null}
4269     */
4270    public static char[] toPrimitive(final Character[] array) {
4271        if (array == null) {
4272            return null;
4273        } else if (array.length == 0) {
4274            return EMPTY_CHAR_ARRAY;
4275        }
4276        final char[] result = new char[array.length];
4277        for (int i = 0; i < array.length; i++) {
4278            result[i] = array[i].charValue();
4279        }
4280        return result;
4281    }
4282
4283    /**
4284     * <p>Converts an array of object Character to primitives handling {@code null}.
4285     *
4286     * <p>This method returns {@code null} for a {@code null} input array.
4287     *
4288     * @param array  a {@code Character} array, may be {@code null}
4289     * @param valueForNull  the value to insert if {@code null} found
4290     * @return a {@code char} array, {@code null} if null array input
4291     */
4292    public static char[] toPrimitive(final Character[] array, final char valueForNull) {
4293        if (array == null) {
4294            return null;
4295        } else if (array.length == 0) {
4296            return EMPTY_CHAR_ARRAY;
4297        }
4298        final char[] result = new char[array.length];
4299        for (int i = 0; i < array.length; i++) {
4300            final Character b = array[i];
4301            result[i] = (b == null ? valueForNull : b.charValue());
4302        }
4303        return result;
4304    }
4305
4306    /**
4307     * <p>Converts an array of primitive chars to objects.
4308     *
4309     * <p>This method returns {@code null} for a {@code null} input array.
4310     *
4311     * @param array a {@code char} array
4312     * @return a {@code Character} array, {@code null} if null array input
4313     */
4314    public static Character[] toObject(final char[] array) {
4315        if (array == null) {
4316            return null;
4317        } else if (array.length == 0) {
4318            return EMPTY_CHARACTER_OBJECT_ARRAY;
4319        }
4320        final Character[] result = new Character[array.length];
4321        for (int i = 0; i < array.length; i++) {
4322            result[i] = Character.valueOf(array[i]);
4323        }
4324        return result;
4325     }
4326
4327    // Long array converters
4328    // ----------------------------------------------------------------------
4329    /**
4330     * <p>Converts an array of object Longs to primitives.
4331     *
4332     * <p>This method returns {@code null} for a {@code null} input array.
4333     *
4334     * @param array  a {@code Long} array, may be {@code null}
4335     * @return a {@code long} array, {@code null} if null array input
4336     * @throws NullPointerException if array content is {@code null}
4337     */
4338    public static long[] toPrimitive(final Long[] array) {
4339        if (array == null) {
4340            return null;
4341        } else if (array.length == 0) {
4342            return EMPTY_LONG_ARRAY;
4343        }
4344        final long[] result = new long[array.length];
4345        for (int i = 0; i < array.length; i++) {
4346            result[i] = array[i].longValue();
4347        }
4348        return result;
4349    }
4350
4351    /**
4352     * <p>Converts an array of object Long to primitives handling {@code null}.
4353     *
4354     * <p>This method returns {@code null} for a {@code null} input array.
4355     *
4356     * @param array  a {@code Long} array, may be {@code null}
4357     * @param valueForNull  the value to insert if {@code null} found
4358     * @return a {@code long} array, {@code null} if null array input
4359     */
4360    public static long[] toPrimitive(final Long[] array, final long valueForNull) {
4361        if (array == null) {
4362            return null;
4363        } else if (array.length == 0) {
4364            return EMPTY_LONG_ARRAY;
4365        }
4366        final long[] result = new long[array.length];
4367        for (int i = 0; i < array.length; i++) {
4368            final Long b = array[i];
4369            result[i] = (b == null ? valueForNull : b.longValue());
4370        }
4371        return result;
4372    }
4373
4374    /**
4375     * <p>Converts an array of primitive longs to objects.
4376     *
4377     * <p>This method returns {@code null} for a {@code null} input array.
4378     *
4379     * @param array  a {@code long} array
4380     * @return a {@code Long} array, {@code null} if null array input
4381     */
4382    public static Long[] toObject(final long[] array) {
4383        if (array == null) {
4384            return null;
4385        } else if (array.length == 0) {
4386            return EMPTY_LONG_OBJECT_ARRAY;
4387        }
4388        final Long[] result = new Long[array.length];
4389        for (int i = 0; i < array.length; i++) {
4390            result[i] = Long.valueOf(array[i]);
4391        }
4392        return result;
4393    }
4394
4395    // Int array converters
4396    // ----------------------------------------------------------------------
4397    /**
4398     * <p>Converts an array of object Integers to primitives.
4399     *
4400     * <p>This method returns {@code null} for a {@code null} input array.
4401     *
4402     * @param array  a {@code Integer} array, may be {@code null}
4403     * @return an {@code int} array, {@code null} if null array input
4404     * @throws NullPointerException if array content is {@code null}
4405     */
4406    public static int[] toPrimitive(final Integer[] array) {
4407        if (array == null) {
4408            return null;
4409        } else if (array.length == 0) {
4410            return EMPTY_INT_ARRAY;
4411        }
4412        final int[] result = new int[array.length];
4413        for (int i = 0; i < array.length; i++) {
4414            result[i] = array[i].intValue();
4415        }
4416        return result;
4417    }
4418
4419    /**
4420     * <p>Converts an array of object Integer to primitives handling {@code null}.
4421     *
4422     * <p>This method returns {@code null} for a {@code null} input array.
4423     *
4424     * @param array  a {@code Integer} array, may be {@code null}
4425     * @param valueForNull  the value to insert if {@code null} found
4426     * @return an {@code int} array, {@code null} if null array input
4427     */
4428    public static int[] toPrimitive(final Integer[] array, final int valueForNull) {
4429        if (array == null) {
4430            return null;
4431        } else if (array.length == 0) {
4432            return EMPTY_INT_ARRAY;
4433        }
4434        final int[] result = new int[array.length];
4435        for (int i = 0; i < array.length; i++) {
4436            final Integer b = array[i];
4437            result[i] = (b == null ? valueForNull : b.intValue());
4438        }
4439        return result;
4440    }
4441
4442    /**
4443     * <p>Converts an array of primitive ints to objects.
4444     *
4445     * <p>This method returns {@code null} for a {@code null} input array.
4446     *
4447     * @param array  an {@code int} array
4448     * @return an {@code Integer} array, {@code null} if null array input
4449     */
4450    public static Integer[] toObject(final int[] array) {
4451        if (array == null) {
4452            return null;
4453        } else if (array.length == 0) {
4454            return EMPTY_INTEGER_OBJECT_ARRAY;
4455        }
4456        final Integer[] result = new Integer[array.length];
4457        for (int i = 0; i < array.length; i++) {
4458            result[i] = Integer.valueOf(array[i]);
4459        }
4460        return result;
4461    }
4462
4463    // Short array converters
4464    // ----------------------------------------------------------------------
4465    /**
4466     * <p>Converts an array of object Shorts to primitives.
4467     *
4468     * <p>This method returns {@code null} for a {@code null} input array.
4469     *
4470     * @param array  a {@code Short} array, may be {@code null}
4471     * @return a {@code byte} array, {@code null} if null array input
4472     * @throws NullPointerException if array content is {@code null}
4473     */
4474    public static short[] toPrimitive(final Short[] array) {
4475        if (array == null) {
4476            return null;
4477        } else if (array.length == 0) {
4478            return EMPTY_SHORT_ARRAY;
4479        }
4480        final short[] result = new short[array.length];
4481        for (int i = 0; i < array.length; i++) {
4482            result[i] = array[i].shortValue();
4483        }
4484        return result;
4485    }
4486
4487    /**
4488     * <p>Converts an array of object Short to primitives handling {@code null}.
4489     *
4490     * <p>This method returns {@code null} for a {@code null} input array.
4491     *
4492     * @param array  a {@code Short} array, may be {@code null}
4493     * @param valueForNull  the value to insert if {@code null} found
4494     * @return a {@code byte} array, {@code null} if null array input
4495     */
4496    public static short[] toPrimitive(final Short[] array, final short valueForNull) {
4497        if (array == null) {
4498            return null;
4499        } else if (array.length == 0) {
4500            return EMPTY_SHORT_ARRAY;
4501        }
4502        final short[] result = new short[array.length];
4503        for (int i = 0; i < array.length; i++) {
4504            final Short b = array[i];
4505            result[i] = (b == null ? valueForNull : b.shortValue());
4506        }
4507        return result;
4508    }
4509
4510    /**
4511     * <p>Converts an array of primitive shorts to objects.
4512     *
4513     * <p>This method returns {@code null} for a {@code null} input array.
4514     *
4515     * @param array  a {@code short} array
4516     * @return a {@code Short} array, {@code null} if null array input
4517     */
4518    public static Short[] toObject(final short[] array) {
4519        if (array == null) {
4520            return null;
4521        } else if (array.length == 0) {
4522            return EMPTY_SHORT_OBJECT_ARRAY;
4523        }
4524        final Short[] result = new Short[array.length];
4525        for (int i = 0; i < array.length; i++) {
4526            result[i] = Short.valueOf(array[i]);
4527        }
4528        return result;
4529    }
4530
4531    // Byte array converters
4532    // ----------------------------------------------------------------------
4533    /**
4534     * <p>Converts an array of object Bytes to primitives.
4535     *
4536     * <p>This method returns {@code null} for a {@code null} input array.
4537     *
4538     * @param array  a {@code Byte} array, may be {@code null}
4539     * @return a {@code byte} array, {@code null} if null array input
4540     * @throws NullPointerException if array content is {@code null}
4541     */
4542    public static byte[] toPrimitive(final Byte[] array) {
4543        if (array == null) {
4544            return null;
4545        } else if (array.length == 0) {
4546            return EMPTY_BYTE_ARRAY;
4547        }
4548        final byte[] result = new byte[array.length];
4549        for (int i = 0; i < array.length; i++) {
4550            result[i] = array[i].byteValue();
4551        }
4552        return result;
4553    }
4554
4555    /**
4556     * <p>Converts an array of object Bytes to primitives handling {@code null}.
4557     *
4558     * <p>This method returns {@code null} for a {@code null} input array.
4559     *
4560     * @param array  a {@code Byte} array, may be {@code null}
4561     * @param valueForNull  the value to insert if {@code null} found
4562     * @return a {@code byte} array, {@code null} if null array input
4563     */
4564    public static byte[] toPrimitive(final Byte[] array, final byte valueForNull) {
4565        if (array == null) {
4566            return null;
4567        } else if (array.length == 0) {
4568            return EMPTY_BYTE_ARRAY;
4569        }
4570        final byte[] result = new byte[array.length];
4571        for (int i = 0; i < array.length; i++) {
4572            final Byte b = array[i];
4573            result[i] = (b == null ? valueForNull : b.byteValue());
4574        }
4575        return result;
4576    }
4577
4578    /**
4579     * <p>Converts an array of primitive bytes to objects.
4580     *
4581     * <p>This method returns {@code null} for a {@code null} input array.
4582     *
4583     * @param array  a {@code byte} array
4584     * @return a {@code Byte} array, {@code null} if null array input
4585     */
4586    public static Byte[] toObject(final byte[] array) {
4587        if (array == null) {
4588            return null;
4589        } else if (array.length == 0) {
4590            return EMPTY_BYTE_OBJECT_ARRAY;
4591        }
4592        final Byte[] result = new Byte[array.length];
4593        for (int i = 0; i < array.length; i++) {
4594            result[i] = Byte.valueOf(array[i]);
4595        }
4596        return result;
4597    }
4598
4599    // Double array converters
4600    // ----------------------------------------------------------------------
4601    /**
4602     * <p>Converts an array of object Doubles to primitives.
4603     *
4604     * <p>This method returns {@code null} for a {@code null} input array.
4605     *
4606     * @param array  a {@code Double} array, may be {@code null}
4607     * @return a {@code double} array, {@code null} if null array input
4608     * @throws NullPointerException if array content is {@code null}
4609     */
4610    public static double[] toPrimitive(final Double[] array) {
4611        if (array == null) {
4612            return null;
4613        } else if (array.length == 0) {
4614            return EMPTY_DOUBLE_ARRAY;
4615        }
4616        final double[] result = new double[array.length];
4617        for (int i = 0; i < array.length; i++) {
4618            result[i] = array[i].doubleValue();
4619        }
4620        return result;
4621    }
4622
4623    /**
4624     * <p>Converts an array of object Doubles to primitives handling {@code null}.
4625     *
4626     * <p>This method returns {@code null} for a {@code null} input array.
4627     *
4628     * @param array  a {@code Double} array, may be {@code null}
4629     * @param valueForNull  the value to insert if {@code null} found
4630     * @return a {@code double} array, {@code null} if null array input
4631     */
4632    public static double[] toPrimitive(final Double[] array, final double valueForNull) {
4633        if (array == null) {
4634            return null;
4635        } else if (array.length == 0) {
4636            return EMPTY_DOUBLE_ARRAY;
4637        }
4638        final double[] result = new double[array.length];
4639        for (int i = 0; i < array.length; i++) {
4640            final Double b = array[i];
4641            result[i] = (b == null ? valueForNull : b.doubleValue());
4642        }
4643        return result;
4644    }
4645
4646    /**
4647     * <p>Converts an array of primitive doubles to objects.
4648     *
4649     * <p>This method returns {@code null} for a {@code null} input array.
4650     *
4651     * @param array  a {@code double} array
4652     * @return a {@code Double} array, {@code null} if null array input
4653     */
4654    public static Double[] toObject(final double[] array) {
4655        if (array == null) {
4656            return null;
4657        } else if (array.length == 0) {
4658            return EMPTY_DOUBLE_OBJECT_ARRAY;
4659        }
4660        final Double[] result = new Double[array.length];
4661        for (int i = 0; i < array.length; i++) {
4662            result[i] = Double.valueOf(array[i]);
4663        }
4664        return result;
4665    }
4666
4667    //   Float array converters
4668    // ----------------------------------------------------------------------
4669    /**
4670     * <p>Converts an array of object Floats to primitives.
4671     *
4672     * <p>This method returns {@code null} for a {@code null} input array.
4673     *
4674     * @param array  a {@code Float} array, may be {@code null}
4675     * @return a {@code float} array, {@code null} if null array input
4676     * @throws NullPointerException if array content is {@code null}
4677     */
4678    public static float[] toPrimitive(final Float[] array) {
4679        if (array == null) {
4680            return null;
4681        } else if (array.length == 0) {
4682            return EMPTY_FLOAT_ARRAY;
4683        }
4684        final float[] result = new float[array.length];
4685        for (int i = 0; i < array.length; i++) {
4686            result[i] = array[i].floatValue();
4687        }
4688        return result;
4689    }
4690
4691    /**
4692     * <p>Converts an array of object Floats to primitives handling {@code null}.
4693     *
4694     * <p>This method returns {@code null} for a {@code null} input array.
4695     *
4696     * @param array  a {@code Float} array, may be {@code null}
4697     * @param valueForNull  the value to insert if {@code null} found
4698     * @return a {@code float} array, {@code null} if null array input
4699     */
4700    public static float[] toPrimitive(final Float[] array, final float valueForNull) {
4701        if (array == null) {
4702            return null;
4703        } else if (array.length == 0) {
4704            return EMPTY_FLOAT_ARRAY;
4705        }
4706        final float[] result = new float[array.length];
4707        for (int i = 0; i < array.length; i++) {
4708            final Float b = array[i];
4709            result[i] = (b == null ? valueForNull : b.floatValue());
4710        }
4711        return result;
4712    }
4713
4714    /**
4715     * <p>Converts an array of primitive floats to objects.
4716     *
4717     * <p>This method returns {@code null} for a {@code null} input array.
4718     *
4719     * @param array  a {@code float} array
4720     * @return a {@code Float} array, {@code null} if null array input
4721     */
4722    public static Float[] toObject(final float[] array) {
4723        if (array == null) {
4724            return null;
4725        } else if (array.length == 0) {
4726            return EMPTY_FLOAT_OBJECT_ARRAY;
4727        }
4728        final Float[] result = new Float[array.length];
4729        for (int i = 0; i < array.length; i++) {
4730            result[i] = Float.valueOf(array[i]);
4731        }
4732        return result;
4733    }
4734
4735    /**
4736     * <p>Create an array of primitive type from an array of wrapper types.
4737     *
4738     * <p>This method returns {@code null} for a {@code null} input array.
4739     *
4740     * @param array  an array of wrapper object
4741     * @return an array of the corresponding primitive type, or the original array
4742     * @since 3.5
4743     */
4744    public static Object toPrimitive(final Object array) {
4745        if (array == null) {
4746            return null;
4747        }
4748        Class<?> ct = array.getClass().getComponentType();
4749        Class<?> pt = ClassUtils.wrapperToPrimitive(ct);
4750        if(Integer.TYPE.equals(pt)) {
4751            return toPrimitive((Integer[]) array);
4752        }
4753        if(Long.TYPE.equals(pt)) {
4754            return toPrimitive((Long[]) array);
4755        }
4756        if(Short.TYPE.equals(pt)) {
4757            return toPrimitive((Short[]) array);
4758        }
4759        if(Double.TYPE.equals(pt)) {
4760            return toPrimitive((Double[]) array);
4761        }
4762        if(Float.TYPE.equals(pt)) {
4763            return toPrimitive((Float[]) array);
4764        }
4765        return array;
4766    }
4767
4768    // Boolean array converters
4769    // ----------------------------------------------------------------------
4770    /**
4771     * <p>Converts an array of object Booleans to primitives.
4772     *
4773     * <p>This method returns {@code null} for a {@code null} input array.
4774     *
4775     * @param array  a {@code Boolean} array, may be {@code null}
4776     * @return a {@code boolean} array, {@code null} if null array input
4777     * @throws NullPointerException if array content is {@code null}
4778     */
4779    public static boolean[] toPrimitive(final Boolean[] array) {
4780        if (array == null) {
4781            return null;
4782        } else if (array.length == 0) {
4783            return EMPTY_BOOLEAN_ARRAY;
4784        }
4785        final boolean[] result = new boolean[array.length];
4786        for (int i = 0; i < array.length; i++) {
4787            result[i] = array[i].booleanValue();
4788        }
4789        return result;
4790    }
4791
4792    /**
4793     * <p>Converts an array of object Booleans to primitives handling {@code null}.
4794     *
4795     * <p>This method returns {@code null} for a {@code null} input array.
4796     *
4797     * @param array  a {@code Boolean} array, may be {@code null}
4798     * @param valueForNull  the value to insert if {@code null} found
4799     * @return a {@code boolean} array, {@code null} if null array input
4800     */
4801    public static boolean[] toPrimitive(final Boolean[] array, final boolean valueForNull) {
4802        if (array == null) {
4803            return null;
4804        } else if (array.length == 0) {
4805            return EMPTY_BOOLEAN_ARRAY;
4806        }
4807        final boolean[] result = new boolean[array.length];
4808        for (int i = 0; i < array.length; i++) {
4809            final Boolean b = array[i];
4810            result[i] = (b == null ? valueForNull : b.booleanValue());
4811        }
4812        return result;
4813    }
4814
4815    /**
4816     * <p>Converts an array of primitive booleans to objects.
4817     *
4818     * <p>This method returns {@code null} for a {@code null} input array.
4819     *
4820     * @param array  a {@code boolean} array
4821     * @return a {@code Boolean} array, {@code null} if null array input
4822     */
4823    public static Boolean[] toObject(final boolean[] array) {
4824        if (array == null) {
4825            return null;
4826        } else if (array.length == 0) {
4827            return EMPTY_BOOLEAN_OBJECT_ARRAY;
4828        }
4829        final Boolean[] result = new Boolean[array.length];
4830        for (int i = 0; i < array.length; i++) {
4831            result[i] = (array[i] ? Boolean.TRUE : Boolean.FALSE);
4832        }
4833        return result;
4834    }
4835
4836    // ----------------------------------------------------------------------
4837    /**
4838     * <p>Checks if an array of Objects is empty or {@code null}.
4839     *
4840     * @param array  the array to test
4841     * @return {@code true} if the array is empty or {@code null}
4842     * @since 2.1
4843     */
4844    public static boolean isEmpty(final Object[] array) {
4845        return getLength(array) == 0;
4846    }
4847
4848    /**
4849     * <p>Checks if an array of primitive longs is empty or {@code null}.
4850     *
4851     * @param array  the array to test
4852     * @return {@code true} if the array is empty or {@code null}
4853     * @since 2.1
4854     */
4855    public static boolean isEmpty(final long[] array) {
4856        return getLength(array) == 0;
4857    }
4858
4859    /**
4860     * <p>Checks if an array of primitive ints is empty or {@code null}.
4861     *
4862     * @param array  the array to test
4863     * @return {@code true} if the array is empty or {@code null}
4864     * @since 2.1
4865     */
4866    public static boolean isEmpty(final int[] array) {
4867        return getLength(array) == 0;
4868    }
4869
4870    /**
4871     * <p>Checks if an array of primitive shorts is empty or {@code null}.
4872     *
4873     * @param array  the array to test
4874     * @return {@code true} if the array is empty or {@code null}
4875     * @since 2.1
4876     */
4877    public static boolean isEmpty(final short[] array) {
4878        return getLength(array) == 0;
4879    }
4880
4881    /**
4882     * <p>Checks if an array of primitive chars is empty or {@code null}.
4883     *
4884     * @param array  the array to test
4885     * @return {@code true} if the array is empty or {@code null}
4886     * @since 2.1
4887     */
4888    public static boolean isEmpty(final char[] array) {
4889        return getLength(array) == 0;
4890    }
4891
4892    /**
4893     * <p>Checks if an array of primitive bytes is empty or {@code null}.
4894     *
4895     * @param array  the array to test
4896     * @return {@code true} if the array is empty or {@code null}
4897     * @since 2.1
4898     */
4899    public static boolean isEmpty(final byte[] array) {
4900        return getLength(array) == 0;
4901    }
4902
4903    /**
4904     * <p>Checks if an array of primitive doubles is empty or {@code null}.
4905     *
4906     * @param array  the array to test
4907     * @return {@code true} if the array is empty or {@code null}
4908     * @since 2.1
4909     */
4910    public static boolean isEmpty(final double[] array) {
4911        return getLength(array) == 0;
4912    }
4913
4914    /**
4915     * <p>Checks if an array of primitive floats is empty or {@code null}.
4916     *
4917     * @param array  the array to test
4918     * @return {@code true} if the array is empty or {@code null}
4919     * @since 2.1
4920     */
4921    public static boolean isEmpty(final float[] array) {
4922        return getLength(array) == 0;
4923    }
4924
4925    /**
4926     * <p>Checks if an array of primitive booleans is empty or {@code null}.
4927     *
4928     * @param array  the array to test
4929     * @return {@code true} if the array is empty or {@code null}
4930     * @since 2.1
4931     */
4932    public static boolean isEmpty(final boolean[] array) {
4933        return getLength(array) == 0;
4934    }
4935
4936    // ----------------------------------------------------------------------
4937    /**
4938     * <p>Checks if an array of Objects is not empty and not {@code null}.
4939     *
4940     * @param <T> the component type of the array
4941     * @param array  the array to test
4942     * @return {@code true} if the array is not empty and not {@code null}
4943     * @since 2.5
4944     */
4945     public static <T> boolean isNotEmpty(final T[] array) {
4946         return !isEmpty(array);
4947     }
4948
4949    /**
4950     * <p>Checks if an array of primitive longs is not empty and not {@code null}.
4951     *
4952     * @param array  the array to test
4953     * @return {@code true} if the array is not empty and not {@code null}
4954     * @since 2.5
4955     */
4956    public static boolean isNotEmpty(final long[] array) {
4957        return !isEmpty(array);
4958    }
4959
4960    /**
4961     * <p>Checks if an array of primitive ints is not empty and not {@code null}.
4962     *
4963     * @param array  the array to test
4964     * @return {@code true} if the array is not empty and not {@code null}
4965     * @since 2.5
4966     */
4967    public static boolean isNotEmpty(final int[] array) {
4968        return !isEmpty(array);
4969    }
4970
4971    /**
4972     * <p>Checks if an array of primitive shorts is not empty and not {@code null}.
4973     *
4974     * @param array  the array to test
4975     * @return {@code true} if the array is not empty and not {@code null}
4976     * @since 2.5
4977     */
4978    public static boolean isNotEmpty(final short[] array) {
4979        return !isEmpty(array);
4980    }
4981
4982    /**
4983     * <p>Checks if an array of primitive chars is not empty and not {@code null}.
4984     *
4985     * @param array  the array to test
4986     * @return {@code true} if the array is not empty and not {@code null}
4987     * @since 2.5
4988     */
4989    public static boolean isNotEmpty(final char[] array) {
4990        return !isEmpty(array);
4991    }
4992
4993    /**
4994     * <p>Checks if an array of primitive bytes is not empty and not {@code null}.
4995     *
4996     * @param array  the array to test
4997     * @return {@code true} if the array is not empty and not {@code null}
4998     * @since 2.5
4999     */
5000    public static boolean isNotEmpty(final byte[] array) {
5001        return !isEmpty(array);
5002    }
5003
5004    /**
5005     * <p>Checks if an array of primitive doubles is not empty and not {@code null}.
5006     *
5007     * @param array  the array to test
5008     * @return {@code true} if the array is not empty and not {@code null}
5009     * @since 2.5
5010     */
5011    public static boolean isNotEmpty(final double[] array) {
5012        return !isEmpty(array);
5013    }
5014
5015    /**
5016     * <p>Checks if an array of primitive floats is not empty and not {@code null}.
5017     *
5018     * @param array  the array to test
5019     * @return {@code true} if the array is not empty and not {@code null}
5020     * @since 2.5
5021     */
5022    public static boolean isNotEmpty(final float[] array) {
5023        return !isEmpty(array);
5024    }
5025
5026    /**
5027     * <p>Checks if an array of primitive booleans is not empty and not {@code null}.
5028     *
5029     * @param array  the array to test
5030     * @return {@code true} if the array is not empty and not {@code null}
5031     * @since 2.5
5032     */
5033    public static boolean isNotEmpty(final boolean[] array) {
5034        return !isEmpty(array);
5035    }
5036
5037    /**
5038     * <p>Adds all the elements of the given arrays into a new array.
5039     * <p>The new array contains all of the element of {@code array1} followed
5040     * by all of the elements {@code array2}. When an array is returned, it is always
5041     * a new array.
5042     *
5043     * <pre>
5044     * ArrayUtils.addAll(null, null)     = null
5045     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
5046     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
5047     * ArrayUtils.addAll([], [])         = []
5048     * ArrayUtils.addAll([null], [null]) = [null, null]
5049     * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
5050     * </pre>
5051     *
5052     * @param <T> the component type of the array
5053     * @param array1  the first array whose elements are added to the new array, may be {@code null}
5054     * @param array2  the second array whose elements are added to the new array, may be {@code null}
5055     * @return The new array, {@code null} if both arrays are {@code null}.
5056     *      The type of the new array is the type of the first array,
5057     *      unless the first array is null, in which case the type is the same as the second array.
5058     * @since 2.1
5059     * @throws IllegalArgumentException if the array types are incompatible
5060     */
5061    public static <T> T[] addAll(final T[] array1, final T... array2) {
5062        if (array1 == null) {
5063            return clone(array2);
5064        } else if (array2 == null) {
5065            return clone(array1);
5066        }
5067        final Class<?> type1 = array1.getClass().getComponentType();
5068        @SuppressWarnings("unchecked") // OK, because array is of type T
5069        final
5070        T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);
5071        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
5072        try {
5073            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
5074        } catch (final ArrayStoreException ase) {
5075            // Check if problem was due to incompatible types
5076            /*
5077             * We do this here, rather than before the copy because:
5078             * - it would be a wasted check most of the time
5079             * - safer, in case check turns out to be too strict
5080             */
5081            final Class<?> type2 = array2.getClass().getComponentType();
5082            if (!type1.isAssignableFrom(type2)) {
5083                throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of "
5084                        + type1.getName(), ase);
5085            }
5086            throw ase; // No, so rethrow original
5087        }
5088        return joinedArray;
5089    }
5090
5091    /**
5092     * <p>Adds all the elements of the given arrays into a new array.
5093     * <p>The new array contains all of the element of {@code array1} followed
5094     * by all of the elements {@code array2}. When an array is returned, it is always
5095     * a new array.
5096     *
5097     * <pre>
5098     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
5099     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
5100     * ArrayUtils.addAll([], [])         = []
5101     * </pre>
5102     *
5103     * @param array1  the first array whose elements are added to the new array.
5104     * @param array2  the second array whose elements are added to the new array.
5105     * @return The new boolean[] array.
5106     * @since 2.1
5107     */
5108    public static boolean[] addAll(final boolean[] array1, final boolean... array2) {
5109        if (array1 == null) {
5110            return clone(array2);
5111        } else if (array2 == null) {
5112            return clone(array1);
5113        }
5114        final boolean[] joinedArray = new boolean[array1.length + array2.length];
5115        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
5116        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
5117        return joinedArray;
5118    }
5119
5120    /**
5121     * <p>Adds all the elements of the given arrays into a new array.
5122     * <p>The new array contains all of the element of {@code array1} followed
5123     * by all of the elements {@code array2}. When an array is returned, it is always
5124     * a new array.
5125     *
5126     * <pre>
5127     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
5128     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
5129     * ArrayUtils.addAll([], [])         = []
5130     * </pre>
5131     *
5132     * @param array1  the first array whose elements are added to the new array.
5133     * @param array2  the second array whose elements are added to the new array.
5134     * @return The new char[] array.
5135     * @since 2.1
5136     */
5137    public static char[] addAll(final char[] array1, final char... array2) {
5138        if (array1 == null) {
5139            return clone(array2);
5140        } else if (array2 == null) {
5141            return clone(array1);
5142        }
5143        final char[] joinedArray = new char[array1.length + array2.length];
5144        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
5145        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
5146        return joinedArray;
5147    }
5148
5149    /**
5150     * <p>Adds all the elements of the given arrays into a new array.
5151     * <p>The new array contains all of the element of {@code array1} followed
5152     * by all of the elements {@code array2}. When an array is returned, it is always
5153     * a new array.
5154     *
5155     * <pre>
5156     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
5157     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
5158     * ArrayUtils.addAll([], [])         = []
5159     * </pre>
5160     *
5161     * @param array1  the first array whose elements are added to the new array.
5162     * @param array2  the second array whose elements are added to the new array.
5163     * @return The new byte[] array.
5164     * @since 2.1
5165     */
5166    public static byte[] addAll(final byte[] array1, final byte... array2) {
5167        if (array1 == null) {
5168            return clone(array2);
5169        } else if (array2 == null) {
5170            return clone(array1);
5171        }
5172        final byte[] joinedArray = new byte[array1.length + array2.length];
5173        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
5174        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
5175        return joinedArray;
5176    }
5177
5178    /**
5179     * <p>Adds all the elements of the given arrays into a new array.
5180     * <p>The new array contains all of the element of {@code array1} followed
5181     * by all of the elements {@code array2}. When an array is returned, it is always
5182     * a new array.
5183     *
5184     * <pre>
5185     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
5186     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
5187     * ArrayUtils.addAll([], [])         = []
5188     * </pre>
5189     *
5190     * @param array1  the first array whose elements are added to the new array.
5191     * @param array2  the second array whose elements are added to the new array.
5192     * @return The new short[] array.
5193     * @since 2.1
5194     */
5195    public static short[] addAll(final short[] array1, final short... array2) {
5196        if (array1 == null) {
5197            return clone(array2);
5198        } else if (array2 == null) {
5199            return clone(array1);
5200        }
5201        final short[] joinedArray = new short[array1.length + array2.length];
5202        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
5203        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
5204        return joinedArray;
5205    }
5206
5207    /**
5208     * <p>Adds all the elements of the given arrays into a new array.
5209     * <p>The new array contains all of the element of {@code array1} followed
5210     * by all of the elements {@code array2}. When an array is returned, it is always
5211     * a new array.
5212     *
5213     * <pre>
5214     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
5215     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
5216     * ArrayUtils.addAll([], [])         = []
5217     * </pre>
5218     *
5219     * @param array1  the first array whose elements are added to the new array.
5220     * @param array2  the second array whose elements are added to the new array.
5221     * @return The new int[] array.
5222     * @since 2.1
5223     */
5224    public static int[] addAll(final int[] array1, final int... array2) {
5225        if (array1 == null) {
5226            return clone(array2);
5227        } else if (array2 == null) {
5228            return clone(array1);
5229        }
5230        final int[] joinedArray = new int[array1.length + array2.length];
5231        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
5232        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
5233        return joinedArray;
5234    }
5235
5236    /**
5237     * <p>Adds all the elements of the given arrays into a new array.
5238     * <p>The new array contains all of the element of {@code array1} followed
5239     * by all of the elements {@code array2}. When an array is returned, it is always
5240     * a new array.
5241     *
5242     * <pre>
5243     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
5244     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
5245     * ArrayUtils.addAll([], [])         = []
5246     * </pre>
5247     *
5248     * @param array1  the first array whose elements are added to the new array.
5249     * @param array2  the second array whose elements are added to the new array.
5250     * @return The new long[] array.
5251     * @since 2.1
5252     */
5253    public static long[] addAll(final long[] array1, final long... array2) {
5254        if (array1 == null) {
5255            return clone(array2);
5256        } else if (array2 == null) {
5257            return clone(array1);
5258        }
5259        final long[] joinedArray = new long[array1.length + array2.length];
5260        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
5261        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
5262        return joinedArray;
5263    }
5264
5265    /**
5266     * <p>Adds all the elements of the given arrays into a new array.
5267     * <p>The new array contains all of the element of {@code array1} followed
5268     * by all of the elements {@code array2}. When an array is returned, it is always
5269     * a new array.
5270     *
5271     * <pre>
5272     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
5273     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
5274     * ArrayUtils.addAll([], [])         = []
5275     * </pre>
5276     *
5277     * @param array1  the first array whose elements are added to the new array.
5278     * @param array2  the second array whose elements are added to the new array.
5279     * @return The new float[] array.
5280     * @since 2.1
5281     */
5282    public static float[] addAll(final float[] array1, final float... array2) {
5283        if (array1 == null) {
5284            return clone(array2);
5285        } else if (array2 == null) {
5286            return clone(array1);
5287        }
5288        final float[] joinedArray = new float[array1.length + array2.length];
5289        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
5290        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
5291        return joinedArray;
5292    }
5293
5294    /**
5295     * <p>Adds all the elements of the given arrays into a new array.
5296     * <p>The new array contains all of the element of {@code array1} followed
5297     * by all of the elements {@code array2}. When an array is returned, it is always
5298     * a new array.
5299     *
5300     * <pre>
5301     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
5302     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
5303     * ArrayUtils.addAll([], [])         = []
5304     * </pre>
5305     *
5306     * @param array1  the first array whose elements are added to the new array.
5307     * @param array2  the second array whose elements are added to the new array.
5308     * @return The new double[] array.
5309     * @since 2.1
5310     */
5311    public static double[] addAll(final double[] array1, final double... array2) {
5312        if (array1 == null) {
5313            return clone(array2);
5314        } else if (array2 == null) {
5315            return clone(array1);
5316        }
5317        final double[] joinedArray = new double[array1.length + array2.length];
5318        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
5319        System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
5320        return joinedArray;
5321    }
5322
5323    /**
5324     * <p>Copies the given array and adds the given element at the end of the new array.
5325     *
5326     * <p>The new array contains the same elements of the input
5327     * array plus the given element in the last position. The component type of
5328     * the new array is the same as that of the input array.
5329     *
5330     * <p>If the input array is {@code null}, a new one element array is returned
5331     *  whose component type is the same as the element, unless the element itself is null,
5332     *  in which case the return type is Object[]
5333     *
5334     * <pre>
5335     * ArrayUtils.add(null, null)      = [null]
5336     * ArrayUtils.add(null, "a")       = ["a"]
5337     * ArrayUtils.add(["a"], null)     = ["a", null]
5338     * ArrayUtils.add(["a"], "b")      = ["a", "b"]
5339     * ArrayUtils.add(["a", "b"], "c") = ["a", "b", "c"]
5340     * </pre>
5341     *
5342     * @param <T> the component type of the array
5343     * @param array  the array to "add" the element to, may be {@code null}
5344     * @param element  the object to add, may be {@code null}
5345     * @return A new array containing the existing elements plus the new element
5346     * The returned array type will be that of the input array (unless null),
5347     * in which case it will have the same type as the element.
5348     * If both are null, an IllegalArgumentException is thrown
5349     * @since 2.1
5350     * @throws IllegalArgumentException if both arguments are null
5351     */
5352    public static <T> T[] add(final T[] array, final T element) {
5353        Class<?> type;
5354        if (array != null) {
5355            type = array.getClass().getComponentType();
5356        } else if (element != null) {
5357            type = element.getClass();
5358        } else {
5359            throw new IllegalArgumentException("Arguments cannot both be null");
5360        }
5361        @SuppressWarnings("unchecked") // type must be T
5362        final
5363        T[] newArray = (T[]) copyArrayGrow1(array, type);
5364        newArray[newArray.length - 1] = element;
5365        return newArray;
5366    }
5367
5368    /**
5369     * <p>Copies the given array and adds the given element at the end of the new array.
5370     *
5371     * <p>The new array contains the same elements of the input
5372     * array plus the given element in the last position. The component type of
5373     * the new array is the same as that of the input array.
5374     *
5375     * <p>If the input array is {@code null}, a new one element array is returned
5376     *  whose component type is the same as the element.
5377     *
5378     * <pre>
5379     * ArrayUtils.add(null, true)          = [true]
5380     * ArrayUtils.add([true], false)       = [true, false]
5381     * ArrayUtils.add([true, false], true) = [true, false, true]
5382     * </pre>
5383     *
5384     * @param array  the array to copy and add the element to, may be {@code null}
5385     * @param element  the object to add at the last index of the new array
5386     * @return A new array containing the existing elements plus the new element
5387     * @since 2.1
5388     */
5389    public static boolean[] add(final boolean[] array, final boolean element) {
5390        final boolean[] newArray = (boolean[])copyArrayGrow1(array, Boolean.TYPE);
5391        newArray[newArray.length - 1] = element;
5392        return newArray;
5393    }
5394
5395    /**
5396     * <p>Copies the given array and adds the given element at the end of the new array.
5397     *
5398     * <p>The new array contains the same elements of the input
5399     * array plus the given element in the last position. The component type of
5400     * the new array is the same as that of the input array.
5401     *
5402     * <p>If the input array is {@code null}, a new one element array is returned
5403     *  whose component type is the same as the element.
5404     *
5405     * <pre>
5406     * ArrayUtils.add(null, 0)   = [0]
5407     * ArrayUtils.add([1], 0)    = [1, 0]
5408     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
5409     * </pre>
5410     *
5411     * @param array  the array to copy and add the element to, may be {@code null}
5412     * @param element  the object to add at the last index of the new array
5413     * @return A new array containing the existing elements plus the new element
5414     * @since 2.1
5415     */
5416    public static byte[] add(final byte[] array, final byte element) {
5417        final byte[] newArray = (byte[])copyArrayGrow1(array, Byte.TYPE);
5418        newArray[newArray.length - 1] = element;
5419        return newArray;
5420    }
5421
5422    /**
5423     * <p>Copies the given array and adds the given element at the end of the new array.
5424     *
5425     * <p>The new array contains the same elements of the input
5426     * array plus the given element in the last position. The component type of
5427     * the new array is the same as that of the input array.
5428     *
5429     * <p>If the input array is {@code null}, a new one element array is returned
5430     *  whose component type is the same as the element.
5431     *
5432     * <pre>
5433     * ArrayUtils.add(null, '0')       = ['0']
5434     * ArrayUtils.add(['1'], '0')      = ['1', '0']
5435     * ArrayUtils.add(['1', '0'], '1') = ['1', '0', '1']
5436     * </pre>
5437     *
5438     * @param array  the array to copy and add the element to, may be {@code null}
5439     * @param element  the object to add at the last index of the new array
5440     * @return A new array containing the existing elements plus the new element
5441     * @since 2.1
5442     */
5443    public static char[] add(final char[] array, final char element) {
5444        final char[] newArray = (char[])copyArrayGrow1(array, Character.TYPE);
5445        newArray[newArray.length - 1] = element;
5446        return newArray;
5447    }
5448
5449    /**
5450     * <p>Copies the given array and adds the given element at the end of the new array.
5451     *
5452     * <p>The new array contains the same elements of the input
5453     * array plus the given element in the last position. The component type of
5454     * the new array is the same as that of the input array.
5455     *
5456     * <p>If the input array is {@code null}, a new one element array is returned
5457     *  whose component type is the same as the element.
5458     *
5459     * <pre>
5460     * ArrayUtils.add(null, 0)   = [0]
5461     * ArrayUtils.add([1], 0)    = [1, 0]
5462     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
5463     * </pre>
5464     *
5465     * @param array  the array to copy and add the element to, may be {@code null}
5466     * @param element  the object to add at the last index of the new array
5467     * @return A new array containing the existing elements plus the new element
5468     * @since 2.1
5469     */
5470    public static double[] add(final double[] array, final double element) {
5471        final double[] newArray = (double[])copyArrayGrow1(array, Double.TYPE);
5472        newArray[newArray.length - 1] = element;
5473        return newArray;
5474    }
5475
5476    /**
5477     * <p>Copies the given array and adds the given element at the end of the new array.
5478     *
5479     * <p>The new array contains the same elements of the input
5480     * array plus the given element in the last position. The component type of
5481     * the new array is the same as that of the input array.
5482     *
5483     * <p>If the input array is {@code null}, a new one element array is returned
5484     *  whose component type is the same as the element.
5485     *
5486     * <pre>
5487     * ArrayUtils.add(null, 0)   = [0]
5488     * ArrayUtils.add([1], 0)    = [1, 0]
5489     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
5490     * </pre>
5491     *
5492     * @param array  the array to copy and add the element to, may be {@code null}
5493     * @param element  the object to add at the last index of the new array
5494     * @return A new array containing the existing elements plus the new element
5495     * @since 2.1
5496     */
5497    public static float[] add(final float[] array, final float element) {
5498        final float[] newArray = (float[])copyArrayGrow1(array, Float.TYPE);
5499        newArray[newArray.length - 1] = element;
5500        return newArray;
5501    }
5502
5503    /**
5504     * <p>Copies the given array and adds the given element at the end of the new array.
5505     *
5506     * <p>The new array contains the same elements of the input
5507     * array plus the given element in the last position. The component type of
5508     * the new array is the same as that of the input array.
5509     *
5510     * <p>If the input array is {@code null}, a new one element array is returned
5511     *  whose component type is the same as the element.
5512     *
5513     * <pre>
5514     * ArrayUtils.add(null, 0)   = [0]
5515     * ArrayUtils.add([1], 0)    = [1, 0]
5516     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
5517     * </pre>
5518     *
5519     * @param array  the array to copy and add the element to, may be {@code null}
5520     * @param element  the object to add at the last index of the new array
5521     * @return A new array containing the existing elements plus the new element
5522     * @since 2.1
5523     */
5524    public static int[] add(final int[] array, final int element) {
5525        final int[] newArray = (int[])copyArrayGrow1(array, Integer.TYPE);
5526        newArray[newArray.length - 1] = element;
5527        return newArray;
5528    }
5529
5530    /**
5531     * <p>Copies the given array and adds the given element at the end of the new array.
5532     *
5533     * <p>The new array contains the same elements of the input
5534     * array plus the given element in the last position. The component type of
5535     * the new array is the same as that of the input array.
5536     *
5537     * <p>If the input array is {@code null}, a new one element array is returned
5538     *  whose component type is the same as the element.
5539     *
5540     * <pre>
5541     * ArrayUtils.add(null, 0)   = [0]
5542     * ArrayUtils.add([1], 0)    = [1, 0]
5543     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
5544     * </pre>
5545     *
5546     * @param array  the array to copy and add the element to, may be {@code null}
5547     * @param element  the object to add at the last index of the new array
5548     * @return A new array containing the existing elements plus the new element
5549     * @since 2.1
5550     */
5551    public static long[] add(final long[] array, final long element) {
5552        final long[] newArray = (long[])copyArrayGrow1(array, Long.TYPE);
5553        newArray[newArray.length - 1] = element;
5554        return newArray;
5555    }
5556
5557    /**
5558     * <p>Copies the given array and adds the given element at the end of the new array.
5559     *
5560     * <p>The new array contains the same elements of the input
5561     * array plus the given element in the last position. The component type of
5562     * the new array is the same as that of the input array.
5563     *
5564     * <p>If the input array is {@code null}, a new one element array is returned
5565     *  whose component type is the same as the element.
5566     *
5567     * <pre>
5568     * ArrayUtils.add(null, 0)   = [0]
5569     * ArrayUtils.add([1], 0)    = [1, 0]
5570     * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
5571     * </pre>
5572     *
5573     * @param array  the array to copy and add the element to, may be {@code null}
5574     * @param element  the object to add at the last index of the new array
5575     * @return A new array containing the existing elements plus the new element
5576     * @since 2.1
5577     */
5578    public static short[] add(final short[] array, final short element) {
5579        final short[] newArray = (short[]) copyArrayGrow1(array, Short.TYPE);
5580        newArray[newArray.length - 1] = element;
5581        return newArray;
5582    }
5583
5584    /**
5585     * Returns a copy of the given array of size 1 greater than the argument.
5586     * The last value of the array is left to the default value.
5587     *
5588     * @param array The array to copy, must not be {@code null}.
5589     * @param newArrayComponentType If {@code array} is {@code null}, create a
5590     * size 1 array of this type.
5591     * @return A new copy of the array of size 1 greater than the input.
5592     */
5593    private static Object copyArrayGrow1(final Object array, final Class<?> newArrayComponentType) {
5594        if (array != null) {
5595            final int arrayLength = Array.getLength(array);
5596            final Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
5597            System.arraycopy(array, 0, newArray, 0, arrayLength);
5598            return newArray;
5599        }
5600        return Array.newInstance(newArrayComponentType, 1);
5601    }
5602
5603    /**
5604     * <p>Inserts the specified element at the specified position in the array.
5605     * Shifts the element currently at that position (if any) and any subsequent
5606     * elements to the right (adds one to their indices).
5607     *
5608     * <p>This method returns a new array with the same elements of the input
5609     * array plus the given element on the specified position. The component
5610     * type of the returned array is always the same as that of the input
5611     * array.
5612     *
5613     * <p>If the input array is {@code null}, a new one element array is returned
5614     *  whose component type is the same as the element.
5615     *
5616     * <pre>
5617     * ArrayUtils.add(null, 0, null)      = [null]
5618     * ArrayUtils.add(null, 0, "a")       = ["a"]
5619     * ArrayUtils.add(["a"], 1, null)     = ["a", null]
5620     * ArrayUtils.add(["a"], 1, "b")      = ["a", "b"]
5621     * ArrayUtils.add(["a", "b"], 3, "c") = ["a", "b", "c"]
5622     * </pre>
5623     *
5624     * @param <T> the component type of the array
5625     * @param array  the array to add the element to, may be {@code null}
5626     * @param index  the position of the new object
5627     * @param element  the object to add
5628     * @return A new array containing the existing elements and the new element
5629     * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt; array.length).
5630     * @throws IllegalArgumentException if both array and element are null
5631     */
5632    public static <T> T[] add(final T[] array, final int index, final T element) {
5633        Class<?> clss = null;
5634        if (array != null) {
5635            clss = array.getClass().getComponentType();
5636        } else if (element != null) {
5637            clss = element.getClass();
5638        } else {
5639            throw new IllegalArgumentException("Array and element cannot both be null");
5640        }
5641        @SuppressWarnings("unchecked") // the add method creates an array of type clss, which is type T
5642        final T[] newArray = (T[]) add(array, index, element, clss);
5643        return newArray;
5644    }
5645
5646    /**
5647     * <p>Inserts the specified element at the specified position in the array.
5648     * Shifts the element currently at that position (if any) and any subsequent
5649     * elements to the right (adds one to their indices).
5650     *
5651     * <p>This method returns a new array with the same elements of the input
5652     * array plus the given element on the specified position. The component
5653     * type of the returned array is always the same as that of the input
5654     * array.
5655     *
5656     * <p>If the input array is {@code null}, a new one element array is returned
5657     *  whose component type is the same as the element.
5658     *
5659     * <pre>
5660     * ArrayUtils.add(null, 0, true)          = [true]
5661     * ArrayUtils.add([true], 0, false)       = [false, true]
5662     * ArrayUtils.add([false], 1, true)       = [false, true]
5663     * ArrayUtils.add([true, false], 1, true) = [true, true, false]
5664     * </pre>
5665     *
5666     * @param array  the array to add the element to, may be {@code null}
5667     * @param index  the position of the new object
5668     * @param element  the object to add
5669     * @return A new array containing the existing elements and the new element
5670     * @throws IndexOutOfBoundsException if the index is out of range (index &lt; 0 || index &gt; array.length).
5671     */
5672    public static boolean[] add(final boolean[] array, final int index, final boolean element) {
5673        return (boolean[]) add(array, index, Boolean.valueOf(element), Boolean.TYPE);
5674    }
5675
5676    /**
5677     * <p>Inserts the specified element at the specified position in the array.
5678     * Shifts the element currently at that position (if any) and any subsequent
5679     * elements to the right (adds one to their indices).
5680     *
5681     * <p>This method returns a new array with the same elements of the input
5682     * array plus the given element on the specified position. The component
5683     * type of the returned array is always the same as that of the input
5684     * array.
5685     *
5686     * <p>If the input array is {@code null}, a new one element array is returned
5687     *  whose component type is the same as the element.
5688     *
5689     * <pre>
5690     * ArrayUtils.add(null, 0, 'a')            = ['a']
5691     * ArrayUtils.add(['a'], 0, 'b')           = ['b', 'a']
5692     * ArrayUtils.add(['a', 'b'], 0, 'c')      = ['c', 'a', 'b']
5693     * ArrayUtils.add(['a', 'b'], 1, 'k')      = ['a', 'k', 'b']
5694     * ArrayUtils.add(['a', 'b', 'c'], 1, 't') = ['a', 't', 'b', 'c']
5695     * </pre>
5696     *
5697     * @param array  the array to add the element to, may be {@code null}
5698     * @param index  the position of the new object
5699     * @param element  the object to add
5700     * @return A new array containing the existing elements and the new element
5701     * @throws IndexOutOfBoundsException if the index is out of range
5702     * (index &lt; 0 || index &gt; array.length).
5703     */
5704    public static char[] add(final char[] array, final int index, final char element) {
5705        return (char[]) add(array, index, Character.valueOf(element), Character.TYPE);
5706    }
5707
5708    /**
5709     * <p>Inserts the specified element at the specified position in the array.
5710     * Shifts the element currently at that position (if any) and any subsequent
5711     * elements to the right (adds one to their indices).
5712     *
5713     * <p>This method returns a new array with the same elements of the input
5714     * array plus the given element on the specified position. The component
5715     * type of the returned array is always the same as that of the input
5716     * array.
5717     *
5718     * <p>If the input array is {@code null}, a new one element array is returned
5719     *  whose component type is the same as the element.
5720     *
5721     * <pre>
5722     * ArrayUtils.add([1], 0, 2)         = [2, 1]
5723     * ArrayUtils.add([2, 6], 2, 3)      = [2, 6, 3]
5724     * ArrayUtils.add([2, 6], 0, 1)      = [1, 2, 6]
5725     * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
5726     * </pre>
5727     *
5728     * @param array  the array to add the element to, may be {@code null}
5729     * @param index  the position of the new object
5730     * @param element  the object to add
5731     * @return A new array containing the existing elements and the new element
5732     * @throws IndexOutOfBoundsException if the index is out of range
5733     * (index &lt; 0 || index &gt; array.length).
5734     */
5735    public static byte[] add(final byte[] array, final int index, final byte element) {
5736        return (byte[]) add(array, index, Byte.valueOf(element), Byte.TYPE);
5737    }
5738
5739    /**
5740     * <p>Inserts the specified element at the specified position in the array.
5741     * Shifts the element currently at that position (if any) and any subsequent
5742     * elements to the right (adds one to their indices).
5743     *
5744     * <p>This method returns a new array with the same elements of the input
5745     * array plus the given element on the specified position. The component
5746     * type of the returned array is always the same as that of the input
5747     * array.
5748     *
5749     * <p>If the input array is {@code null}, a new one element array is returned
5750     *  whose component type is the same as the element.
5751     *
5752     * <pre>
5753     * ArrayUtils.add([1], 0, 2)         = [2, 1]
5754     * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
5755     * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
5756     * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
5757     * </pre>
5758     *
5759     * @param array  the array to add the element to, may be {@code null}
5760     * @param index  the position of the new object
5761     * @param element  the object to add
5762     * @return A new array containing the existing elements and the new element
5763     * @throws IndexOutOfBoundsException if the index is out of range
5764     * (index &lt; 0 || index &gt; array.length).
5765     */
5766    public static short[] add(final short[] array, final int index, final short element) {
5767        return (short[]) add(array, index, Short.valueOf(element), Short.TYPE);
5768    }
5769
5770    /**
5771     * <p>Inserts the specified element at the specified position in the array.
5772     * Shifts the element currently at that position (if any) and any subsequent
5773     * elements to the right (adds one to their indices).
5774     *
5775     * <p>This method returns a new array with the same elements of the input
5776     * array plus the given element on the specified position. The component
5777     * type of the returned array is always the same as that of the input
5778     * array.
5779     *
5780     * <p>If the input array is {@code null}, a new one element array is returned
5781     *  whose component type is the same as the element.
5782     *
5783     * <pre>
5784     * ArrayUtils.add([1], 0, 2)         = [2, 1]
5785     * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
5786     * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
5787     * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
5788     * </pre>
5789     *
5790     * @param array  the array to add the element to, may be {@code null}
5791     * @param index  the position of the new object
5792     * @param element  the object to add
5793     * @return A new array containing the existing elements and the new element
5794     * @throws IndexOutOfBoundsException if the index is out of range
5795     * (index &lt; 0 || index &gt; array.length).
5796     */
5797    public static int[] add(final int[] array, final int index, final int element) {
5798        return (int[]) add(array, index, Integer.valueOf(element), Integer.TYPE);
5799    }
5800
5801    /**
5802     * <p>Inserts the specified element at the specified position in the array.
5803     * Shifts the element currently at that position (if any) and any subsequent
5804     * elements to the right (adds one to their indices).
5805     *
5806     * <p>This method returns a new array with the same elements of the input
5807     * array plus the given element on the specified position. The component
5808     * type of the returned array is always the same as that of the input
5809     * array.
5810     *
5811     * <p>If the input array is {@code null}, a new one element array is returned
5812     *  whose component type is the same as the element.
5813     *
5814     * <pre>
5815     * ArrayUtils.add([1L], 0, 2L)           = [2L, 1L]
5816     * ArrayUtils.add([2L, 6L], 2, 10L)      = [2L, 6L, 10L]
5817     * ArrayUtils.add([2L, 6L], 0, -4L)      = [-4L, 2L, 6L]
5818     * ArrayUtils.add([2L, 6L, 3L], 2, 1L)   = [2L, 6L, 1L, 3L]
5819     * </pre>
5820     *
5821     * @param array  the array to add the element to, may be {@code null}
5822     * @param index  the position of the new object
5823     * @param element  the object to add
5824     * @return A new array containing the existing elements and the new element
5825     * @throws IndexOutOfBoundsException if the index is out of range
5826     * (index &lt; 0 || index &gt; array.length).
5827     */
5828    public static long[] add(final long[] array, final int index, final long element) {
5829        return (long[]) add(array, index, Long.valueOf(element), Long.TYPE);
5830    }
5831
5832    /**
5833     * <p>Inserts the specified element at the specified position in the array.
5834     * Shifts the element currently at that position (if any) and any subsequent
5835     * elements to the right (adds one to their indices).
5836     *
5837     * <p>This method returns a new array with the same elements of the input
5838     * array plus the given element on the specified position. The component
5839     * type of the returned array is always the same as that of the input
5840     * array.
5841     *
5842     * <p>If the input array is {@code null}, a new one element array is returned
5843     *  whose component type is the same as the element.
5844     *
5845     * <pre>
5846     * ArrayUtils.add([1.1f], 0, 2.2f)               = [2.2f, 1.1f]
5847     * ArrayUtils.add([2.3f, 6.4f], 2, 10.5f)        = [2.3f, 6.4f, 10.5f]
5848     * ArrayUtils.add([2.6f, 6.7f], 0, -4.8f)        = [-4.8f, 2.6f, 6.7f]
5849     * ArrayUtils.add([2.9f, 6.0f, 0.3f], 2, 1.0f)   = [2.9f, 6.0f, 1.0f, 0.3f]
5850     * </pre>
5851     *
5852     * @param array  the array to add the element to, may be {@code null}
5853     * @param index  the position of the new object
5854     * @param element  the object to add
5855     * @return A new array containing the existing elements and the new element
5856     * @throws IndexOutOfBoundsException if the index is out of range
5857     * (index &lt; 0 || index &gt; array.length).
5858     */
5859    public static float[] add(final float[] array, final int index, final float element) {
5860        return (float[]) add(array, index, Float.valueOf(element), Float.TYPE);
5861    }
5862
5863    /**
5864     * <p>Inserts the specified element at the specified position in the array.
5865     * Shifts the element currently at that position (if any) and any subsequent
5866     * elements to the right (adds one to their indices).
5867     *
5868     * <p>This method returns a new array with the same elements of the input
5869     * array plus the given element on the specified position. The component
5870     * type of the returned array is always the same as that of the input
5871     * array.
5872     *
5873     * <p>If the input array is {@code null}, a new one element array is returned
5874     *  whose component type is the same as the element.
5875     *
5876     * <pre>
5877     * ArrayUtils.add([1.1], 0, 2.2)              = [2.2, 1.1]
5878     * ArrayUtils.add([2.3, 6.4], 2, 10.5)        = [2.3, 6.4, 10.5]
5879     * ArrayUtils.add([2.6, 6.7], 0, -4.8)        = [-4.8, 2.6, 6.7]
5880     * ArrayUtils.add([2.9, 6.0, 0.3], 2, 1.0)    = [2.9, 6.0, 1.0, 0.3]
5881     * </pre>
5882     *
5883     * @param array  the array to add the element to, may be {@code null}
5884     * @param index  the position of the new object
5885     * @param element  the object to add
5886     * @return A new array containing the existing elements and the new element
5887     * @throws IndexOutOfBoundsException if the index is out of range
5888     * (index &lt; 0 || index &gt; array.length).
5889     */
5890    public static double[] add(final double[] array, final int index, final double element) {
5891        return (double[]) add(array, index, Double.valueOf(element), Double.TYPE);
5892    }
5893
5894    /**
5895     * Underlying implementation of add(array, index, element) methods.
5896     * The last parameter is the class, which may not equal element.getClass
5897     * for primitives.
5898     *
5899     * @param array  the array to add the element to, may be {@code null}
5900     * @param index  the position of the new object
5901     * @param element  the object to add
5902     * @param clss the type of the element being added
5903     * @return A new array containing the existing elements and the new element
5904     */
5905    private static Object add(final Object array, final int index, final Object element, final Class<?> clss) {
5906        if (array == null) {
5907            if (index != 0) {
5908                throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
5909            }
5910            final Object joinedArray = Array.newInstance(clss, 1);
5911            Array.set(joinedArray, 0, element);
5912            return joinedArray;
5913        }
5914        final int length = Array.getLength(array);
5915        if (index > length || index < 0) {
5916            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
5917        }
5918        final Object result = Array.newInstance(clss, length + 1);
5919        System.arraycopy(array, 0, result, 0, index);
5920        Array.set(result, index, element);
5921        if (index < length) {
5922            System.arraycopy(array, index, result, index + 1, length - index);
5923        }
5924        return result;
5925    }
5926
5927    /**
5928     * <p>Removes the element at the specified position from the specified array.
5929     * All subsequent elements are shifted to the left (subtracts one from
5930     * their indices).
5931     *
5932     * <p>This method returns a new array with the same elements of the input
5933     * array except the element on the specified position. The component
5934     * type of the returned array is always the same as that of the input
5935     * array.
5936     *
5937     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5938     * will be thrown, because in that case no valid index can be specified.
5939     *
5940     * <pre>
5941     * ArrayUtils.remove(["a"], 0)           = []
5942     * ArrayUtils.remove(["a", "b"], 0)      = ["b"]
5943     * ArrayUtils.remove(["a", "b"], 1)      = ["a"]
5944     * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"]
5945     * </pre>
5946     *
5947     * @param <T> the component type of the array
5948     * @param array  the array to remove the element from, may not be {@code null}
5949     * @param index  the position of the element to be removed
5950     * @return A new array containing the existing elements except the element
5951     *         at the specified position.
5952     * @throws IndexOutOfBoundsException if the index is out of range
5953     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
5954     * @since 2.1
5955     */
5956    @SuppressWarnings("unchecked") // remove() always creates an array of the same type as its input
5957    public static <T> T[] remove(final T[] array, final int index) {
5958        return (T[]) remove((Object) array, index);
5959    }
5960
5961    /**
5962     * <p>Removes the first occurrence of the specified element from the
5963     * specified array. All subsequent elements are shifted to the left
5964     * (subtracts one from their indices). If the array doesn't contains
5965     * such an element, no elements are removed from the array.
5966     *
5967     * <p>This method returns a new array with the same elements of the input
5968     * array except the first occurrence of the specified element. The component
5969     * type of the returned array is always the same as that of the input
5970     * array.
5971     *
5972     * <pre>
5973     * ArrayUtils.removeElement(null, "a")            = null
5974     * ArrayUtils.removeElement([], "a")              = []
5975     * ArrayUtils.removeElement(["a"], "b")           = ["a"]
5976     * ArrayUtils.removeElement(["a", "b"], "a")      = ["b"]
5977     * ArrayUtils.removeElement(["a", "b", "a"], "a") = ["b", "a"]
5978     * </pre>
5979     *
5980     * @param <T> the component type of the array
5981     * @param array  the array to remove the element from, may be {@code null}
5982     * @param element  the element to be removed
5983     * @return A new array containing the existing elements except the first
5984     *         occurrence of the specified element.
5985     * @since 2.1
5986     */
5987    public static <T> T[] removeElement(final T[] array, final Object element) {
5988        final int index = indexOf(array, element);
5989        if (index == INDEX_NOT_FOUND) {
5990            return clone(array);
5991        }
5992        return remove(array, index);
5993    }
5994
5995    /**
5996     * <p>Removes the element at the specified position from the specified array.
5997     * All subsequent elements are shifted to the left (subtracts one from
5998     * their indices).
5999     *
6000     * <p>This method returns a new array with the same elements of the input
6001     * array except the element on the specified position. The component
6002     * type of the returned array is always the same as that of the input
6003     * array.
6004     *
6005     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
6006     * will be thrown, because in that case no valid index can be specified.
6007     *
6008     * <pre>
6009     * ArrayUtils.remove([true], 0)              = []
6010     * ArrayUtils.remove([true, false], 0)       = [false]
6011     * ArrayUtils.remove([true, false], 1)       = [true]
6012     * ArrayUtils.remove([true, true, false], 1) = [true, false]
6013     * </pre>
6014     *
6015     * @param array  the array to remove the element from, may not be {@code null}
6016     * @param index  the position of the element to be removed
6017     * @return A new array containing the existing elements except the element
6018     *         at the specified position.
6019     * @throws IndexOutOfBoundsException if the index is out of range
6020     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
6021     * @since 2.1
6022     */
6023    public static boolean[] remove(final boolean[] array, final int index) {
6024        return (boolean[]) remove((Object) array, index);
6025    }
6026
6027    /**
6028     * <p>Removes the first occurrence of the specified element from the
6029     * specified array. All subsequent elements are shifted to the left
6030     * (subtracts one from their indices). If the array doesn't contains
6031     * such an element, no elements are removed from the array.
6032     *
6033     * <p>This method returns a new array with the same elements of the input
6034     * array except the first occurrence of the specified element. The component
6035     * type of the returned array is always the same as that of the input
6036     * array.
6037     *
6038     * <pre>
6039     * ArrayUtils.removeElement(null, true)                = null
6040     * ArrayUtils.removeElement([], true)                  = []
6041     * ArrayUtils.removeElement([true], false)             = [true]
6042     * ArrayUtils.removeElement([true, false], false)      = [true]
6043     * ArrayUtils.removeElement([true, false, true], true) = [false, true]
6044     * </pre>
6045     *
6046     * @param array  the array to remove the element from, may be {@code null}
6047     * @param element  the element to be removed
6048     * @return A new array containing the existing elements except the first
6049     *         occurrence of the specified element.
6050     * @since 2.1
6051     */
6052    public static boolean[] removeElement(final boolean[] array, final boolean element) {
6053        final int index = indexOf(array, element);
6054        if (index == INDEX_NOT_FOUND) {
6055            return clone(array);
6056        }
6057        return remove(array, index);
6058    }
6059
6060    /**
6061     * <p>Removes the element at the specified position from the specified array.
6062     * All subsequent elements are shifted to the left (subtracts one from
6063     * their indices).
6064     *
6065     * <p>This method returns a new array with the same elements of the input
6066     * array except the element on the specified position. The component
6067     * type of the returned array is always the same as that of the input
6068     * array.
6069     *
6070     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
6071     * will be thrown, because in that case no valid index can be specified.
6072     *
6073     * <pre>
6074     * ArrayUtils.remove([1], 0)          = []
6075     * ArrayUtils.remove([1, 0], 0)       = [0]
6076     * ArrayUtils.remove([1, 0], 1)       = [1]
6077     * ArrayUtils.remove([1, 0, 1], 1)    = [1, 1]
6078     * </pre>
6079     *
6080     * @param array  the array to remove the element from, may not be {@code null}
6081     * @param index  the position of the element to be removed
6082     * @return A new array containing the existing elements except the element
6083     *         at the specified position.
6084     * @throws IndexOutOfBoundsException if the index is out of range
6085     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
6086     * @since 2.1
6087     */
6088    public static byte[] remove(final byte[] array, final int index) {
6089        return (byte[]) remove((Object) array, index);
6090    }
6091
6092    /**
6093     * <p>Removes the first occurrence of the specified element from the
6094     * specified array. All subsequent elements are shifted to the left
6095     * (subtracts one from their indices). If the array doesn't contains
6096     * such an element, no elements are removed from the array.
6097     *
6098     * <p>This method returns a new array with the same elements of the input
6099     * array except the first occurrence of the specified element. The component
6100     * type of the returned array is always the same as that of the input
6101     * array.
6102     *
6103     * <pre>
6104     * ArrayUtils.removeElement(null, 1)        = null
6105     * ArrayUtils.removeElement([], 1)          = []
6106     * ArrayUtils.removeElement([1], 0)         = [1]
6107     * ArrayUtils.removeElement([1, 0], 0)      = [1]
6108     * ArrayUtils.removeElement([1, 0, 1], 1)   = [0, 1]
6109     * </pre>
6110     *
6111     * @param array  the array to remove the element from, may be {@code null}
6112     * @param element  the element to be removed
6113     * @return A new array containing the existing elements except the first
6114     *         occurrence of the specified element.
6115     * @since 2.1
6116     */
6117    public static byte[] removeElement(final byte[] array, final byte element) {
6118        final int index = indexOf(array, element);
6119        if (index == INDEX_NOT_FOUND) {
6120            return clone(array);
6121        }
6122        return remove(array, index);
6123    }
6124
6125    /**
6126     * <p>Removes the element at the specified position from the specified array.
6127     * All subsequent elements are shifted to the left (subtracts one from
6128     * their indices).
6129     *
6130     * <p>This method returns a new array with the same elements of the input
6131     * array except the element on the specified position. The component
6132     * type of the returned array is always the same as that of the input
6133     * array.
6134     *
6135     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
6136     * will be thrown, because in that case no valid index can be specified.
6137     *
6138     * <pre>
6139     * ArrayUtils.remove(['a'], 0)           = []
6140     * ArrayUtils.remove(['a', 'b'], 0)      = ['b']
6141     * ArrayUtils.remove(['a', 'b'], 1)      = ['a']
6142     * ArrayUtils.remove(['a', 'b', 'c'], 1) = ['a', 'c']
6143     * </pre>
6144     *
6145     * @param array  the array to remove the element from, may not be {@code null}
6146     * @param index  the position of the element to be removed
6147     * @return A new array containing the existing elements except the element
6148     *         at the specified position.
6149     * @throws IndexOutOfBoundsException if the index is out of range
6150     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
6151     * @since 2.1
6152     */
6153    public static char[] remove(final char[] array, final int index) {
6154        return (char[]) remove((Object) array, index);
6155    }
6156
6157    /**
6158     * <p>Removes the first occurrence of the specified element from the
6159     * specified array. All subsequent elements are shifted to the left
6160     * (subtracts one from their indices). If the array doesn't contains
6161     * such an element, no elements are removed from the array.
6162     *
6163     * <p>This method returns a new array with the same elements of the input
6164     * array except the first occurrence of the specified element. The component
6165     * type of the returned array is always the same as that of the input
6166     * array.
6167     *
6168     * <pre>
6169     * ArrayUtils.removeElement(null, 'a')            = null
6170     * ArrayUtils.removeElement([], 'a')              = []
6171     * ArrayUtils.removeElement(['a'], 'b')           = ['a']
6172     * ArrayUtils.removeElement(['a', 'b'], 'a')      = ['b']
6173     * ArrayUtils.removeElement(['a', 'b', 'a'], 'a') = ['b', 'a']
6174     * </pre>
6175     *
6176     * @param array  the array to remove the element from, may be {@code null}
6177     * @param element  the element to be removed
6178     * @return A new array containing the existing elements except the first
6179     *         occurrence of the specified element.
6180     * @since 2.1
6181     */
6182    public static char[] removeElement(final char[] array, final char element) {
6183        final int index = indexOf(array, element);
6184        if (index == INDEX_NOT_FOUND) {
6185            return clone(array);
6186        }
6187        return remove(array, index);
6188    }
6189
6190    /**
6191     * <p>Removes the element at the specified position from the specified array.
6192     * All subsequent elements are shifted to the left (subtracts one from
6193     * their indices).
6194     *
6195     * <p>This method returns a new array with the same elements of the input
6196     * array except the element on the specified position. The component
6197     * type of the returned array is always the same as that of the input
6198     * array.
6199     *
6200     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
6201     * will be thrown, because in that case no valid index can be specified.
6202     *
6203     * <pre>
6204     * ArrayUtils.remove([1.1], 0)           = []
6205     * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
6206     * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
6207     * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
6208     * </pre>
6209     *
6210     * @param array  the array to remove the element from, may not be {@code null}
6211     * @param index  the position of the element to be removed
6212     * @return A new array containing the existing elements except the element
6213     *         at the specified position.
6214     * @throws IndexOutOfBoundsException if the index is out of range
6215     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
6216     * @since 2.1
6217     */
6218    public static double[] remove(final double[] array, final int index) {
6219        return (double[]) remove((Object) array, index);
6220    }
6221
6222    /**
6223     * <p>Removes the first occurrence of the specified element from the
6224     * specified array. All subsequent elements are shifted to the left
6225     * (subtracts one from their indices). If the array doesn't contains
6226     * such an element, no elements are removed from the array.
6227     *
6228     * <p>This method returns a new array with the same elements of the input
6229     * array except the first occurrence of the specified element. The component
6230     * type of the returned array is always the same as that of the input
6231     * array.
6232     *
6233     * <pre>
6234     * ArrayUtils.removeElement(null, 1.1)            = null
6235     * ArrayUtils.removeElement([], 1.1)              = []
6236     * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
6237     * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
6238     * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
6239     * </pre>
6240     *
6241     * @param array  the array to remove the element from, may be {@code null}
6242     * @param element  the element to be removed
6243     * @return A new array containing the existing elements except the first
6244     *         occurrence of the specified element.
6245     * @since 2.1
6246     */
6247    public static double[] removeElement(final double[] array, final double element) {
6248        final int index = indexOf(array, element);
6249        if (index == INDEX_NOT_FOUND) {
6250            return clone(array);
6251        }
6252        return remove(array, index);
6253    }
6254
6255    /**
6256     * <p>Removes the element at the specified position from the specified array.
6257     * All subsequent elements are shifted to the left (subtracts one from
6258     * their indices).
6259     *
6260     * <p>This method returns a new array with the same elements of the input
6261     * array except the element on the specified position. The component
6262     * type of the returned array is always the same as that of the input
6263     * array.
6264     *
6265     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
6266     * will be thrown, because in that case no valid index can be specified.
6267     *
6268     * <pre>
6269     * ArrayUtils.remove([1.1], 0)           = []
6270     * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
6271     * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
6272     * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
6273     * </pre>
6274     *
6275     * @param array  the array to remove the element from, may not be {@code null}
6276     * @param index  the position of the element to be removed
6277     * @return A new array containing the existing elements except the element
6278     *         at the specified position.
6279     * @throws IndexOutOfBoundsException if the index is out of range
6280     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
6281     * @since 2.1
6282     */
6283    public static float[] remove(final float[] array, final int index) {
6284        return (float[]) remove((Object) array, index);
6285    }
6286
6287    /**
6288     * <p>Removes the first occurrence of the specified element from the
6289     * specified array. All subsequent elements are shifted to the left
6290     * (subtracts one from their indices). If the array doesn't contains
6291     * such an element, no elements are removed from the array.
6292     *
6293     * <p>This method returns a new array with the same elements of the input
6294     * array except the first occurrence of the specified element. The component
6295     * type of the returned array is always the same as that of the input
6296     * array.
6297     *
6298     * <pre>
6299     * ArrayUtils.removeElement(null, 1.1)            = null
6300     * ArrayUtils.removeElement([], 1.1)              = []
6301     * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
6302     * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
6303     * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
6304     * </pre>
6305     *
6306     * @param array  the array to remove the element from, may be {@code null}
6307     * @param element  the element to be removed
6308     * @return A new array containing the existing elements except the first
6309     *         occurrence of the specified element.
6310     * @since 2.1
6311     */
6312    public static float[] removeElement(final float[] array, final float element) {
6313        final int index = indexOf(array, element);
6314        if (index == INDEX_NOT_FOUND) {
6315            return clone(array);
6316        }
6317        return remove(array, index);
6318    }
6319
6320    /**
6321     * <p>Removes the element at the specified position from the specified array.
6322     * All subsequent elements are shifted to the left (subtracts one from
6323     * their indices).
6324     *
6325     * <p>This method returns a new array with the same elements of the input
6326     * array except the element on the specified position. The component
6327     * type of the returned array is always the same as that of the input
6328     * array.
6329     *
6330     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
6331     * will be thrown, because in that case no valid index can be specified.
6332     *
6333     * <pre>
6334     * ArrayUtils.remove([1], 0)         = []
6335     * ArrayUtils.remove([2, 6], 0)      = [6]
6336     * ArrayUtils.remove([2, 6], 1)      = [2]
6337     * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
6338     * </pre>
6339     *
6340     * @param array  the array to remove the element from, may not be {@code null}
6341     * @param index  the position of the element to be removed
6342     * @return A new array containing the existing elements except the element
6343     *         at the specified position.
6344     * @throws IndexOutOfBoundsException if the index is out of range
6345     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
6346     * @since 2.1
6347     */
6348    public static int[] remove(final int[] array, final int index) {
6349        return (int[]) remove((Object) array, index);
6350    }
6351
6352    /**
6353     * <p>Removes the first occurrence of the specified element from the
6354     * specified array. All subsequent elements are shifted to the left
6355     * (subtracts one from their indices). If the array doesn't contains
6356     * such an element, no elements are removed from the array.
6357     *
6358     * <p>This method returns a new array with the same elements of the input
6359     * array except the first occurrence of the specified element. The component
6360     * type of the returned array is always the same as that of the input
6361     * array.
6362     *
6363     * <pre>
6364     * ArrayUtils.removeElement(null, 1)      = null
6365     * ArrayUtils.removeElement([], 1)        = []
6366     * ArrayUtils.removeElement([1], 2)       = [1]
6367     * ArrayUtils.removeElement([1, 3], 1)    = [3]
6368     * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
6369     * </pre>
6370     *
6371     * @param array  the array to remove the element from, may be {@code null}
6372     * @param element  the element to be removed
6373     * @return A new array containing the existing elements except the first
6374     *         occurrence of the specified element.
6375     * @since 2.1
6376     */
6377    public static int[] removeElement(final int[] array, final int element) {
6378        final int index = indexOf(array, element);
6379        if (index == INDEX_NOT_FOUND) {
6380            return clone(array);
6381        }
6382        return remove(array, index);
6383    }
6384
6385    /**
6386     * <p>Removes the element at the specified position from the specified array.
6387     * All subsequent elements are shifted to the left (subtracts one from
6388     * their indices).
6389     *
6390     * <p>This method returns a new array with the same elements of the input
6391     * array except the element on the specified position. The component
6392     * type of the returned array is always the same as that of the input
6393     * array.
6394     *
6395     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
6396     * will be thrown, because in that case no valid index can be specified.
6397     *
6398     * <pre>
6399     * ArrayUtils.remove([1], 0)         = []
6400     * ArrayUtils.remove([2, 6], 0)      = [6]
6401     * ArrayUtils.remove([2, 6], 1)      = [2]
6402     * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
6403     * </pre>
6404     *
6405     * @param array  the array to remove the element from, may not be {@code null}
6406     * @param index  the position of the element to be removed
6407     * @return A new array containing the existing elements except the element
6408     *         at the specified position.
6409     * @throws IndexOutOfBoundsException if the index is out of range
6410     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
6411     * @since 2.1
6412     */
6413    public static long[] remove(final long[] array, final int index) {
6414        return (long[]) remove((Object) array, index);
6415    }
6416
6417    /**
6418     * <p>Removes the first occurrence of the specified element from the
6419     * specified array. All subsequent elements are shifted to the left
6420     * (subtracts one from their indices). If the array doesn't contains
6421     * such an element, no elements are removed from the array.
6422     *
6423     * <p>This method returns a new array with the same elements of the input
6424     * array except the first occurrence of the specified element. The component
6425     * type of the returned array is always the same as that of the input
6426     * array.
6427     *
6428     * <pre>
6429     * ArrayUtils.removeElement(null, 1)      = null
6430     * ArrayUtils.removeElement([], 1)        = []
6431     * ArrayUtils.removeElement([1], 2)       = [1]
6432     * ArrayUtils.removeElement([1, 3], 1)    = [3]
6433     * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
6434     * </pre>
6435     *
6436     * @param array  the array to remove the element from, may be {@code null}
6437     * @param element  the element to be removed
6438     * @return A new array containing the existing elements except the first
6439     *         occurrence of the specified element.
6440     * @since 2.1
6441     */
6442    public static long[] removeElement(final long[] array, final long element) {
6443        final int index = indexOf(array, element);
6444        if (index == INDEX_NOT_FOUND) {
6445            return clone(array);
6446        }
6447        return remove(array, index);
6448    }
6449
6450    /**
6451     * <p>Removes the element at the specified position from the specified array.
6452     * All subsequent elements are shifted to the left (subtracts one from
6453     * their indices).
6454     *
6455     * <p>This method returns a new array with the same elements of the input
6456     * array except the element on the specified position. The component
6457     * type of the returned array is always the same as that of the input
6458     * array.
6459     *
6460     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
6461     * will be thrown, because in that case no valid index can be specified.
6462     *
6463     * <pre>
6464     * ArrayUtils.remove([1], 0)         = []
6465     * ArrayUtils.remove([2, 6], 0)      = [6]
6466     * ArrayUtils.remove([2, 6], 1)      = [2]
6467     * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
6468     * </pre>
6469     *
6470     * @param array  the array to remove the element from, may not be {@code null}
6471     * @param index  the position of the element to be removed
6472     * @return A new array containing the existing elements except the element
6473     *         at the specified position.
6474     * @throws IndexOutOfBoundsException if the index is out of range
6475     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
6476     * @since 2.1
6477     */
6478    public static short[] remove(final short[] array, final int index) {
6479        return (short[]) remove((Object) array, index);
6480    }
6481
6482    /**
6483     * <p>Removes the first occurrence of the specified element from the
6484     * specified array. All subsequent elements are shifted to the left
6485     * (subtracts one from their indices). If the array doesn't contains
6486     * such an element, no elements are removed from the array.
6487     *
6488     * <p>This method returns a new array with the same elements of the input
6489     * array except the first occurrence of the specified element. The component
6490     * type of the returned array is always the same as that of the input
6491     * array.
6492     *
6493     * <pre>
6494     * ArrayUtils.removeElement(null, 1)      = null
6495     * ArrayUtils.removeElement([], 1)        = []
6496     * ArrayUtils.removeElement([1], 2)       = [1]
6497     * ArrayUtils.removeElement([1, 3], 1)    = [3]
6498     * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
6499     * </pre>
6500     *
6501     * @param array  the array to remove the element from, may be {@code null}
6502     * @param element  the element to be removed
6503     * @return A new array containing the existing elements except the first
6504     *         occurrence of the specified element.
6505     * @since 2.1
6506     */
6507    public static short[] removeElement(final short[] array, final short element) {
6508        final int index = indexOf(array, element);
6509        if (index == INDEX_NOT_FOUND) {
6510            return clone(array);
6511        }
6512        return remove(array, index);
6513    }
6514
6515    /**
6516     * <p>Removes the element at the specified position from the specified array.
6517     * All subsequent elements are shifted to the left (subtracts one from
6518     * their indices).
6519     *
6520     * <p>This method returns a new array with the same elements of the input
6521     * array except the element on the specified position. The component
6522     * type of the returned array is always the same as that of the input
6523     * array.
6524     *
6525     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
6526     * will be thrown, because in that case no valid index can be specified.
6527     *
6528     * @param array  the array to remove the element from, may not be {@code null}
6529     * @param index  the position of the element to be removed
6530     * @return A new array containing the existing elements except the element
6531     *         at the specified position.
6532     * @throws IndexOutOfBoundsException if the index is out of range
6533     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
6534     * @since 2.1
6535     */
6536    private static Object remove(final Object array, final int index) {
6537        final int length = getLength(array);
6538        if (index < 0 || index >= length) {
6539            throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
6540        }
6541
6542        final Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
6543        System.arraycopy(array, 0, result, 0, index);
6544        if (index < length - 1) {
6545            System.arraycopy(array, index + 1, result, index, length - index - 1);
6546        }
6547
6548        return result;
6549    }
6550
6551    /**
6552     * <p>Removes the elements at the specified positions from the specified array.
6553     * All remaining elements are shifted to the left.
6554     *
6555     * <p>This method returns a new array with the same elements of the input
6556     * array except those at the specified positions. The component
6557     * type of the returned array is always the same as that of the input
6558     * array.
6559     *
6560     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
6561     * will be thrown, because in that case no valid index can be specified.
6562     *
6563     * <pre>
6564     * ArrayUtils.removeAll(["a", "b", "c"], 0, 2) = ["b"]
6565     * ArrayUtils.removeAll(["a", "b", "c"], 1, 2) = ["a"]
6566     * </pre>
6567     *
6568     * @param <T> the component type of the array
6569     * @param array   the array to remove the element from, may not be {@code null}
6570     * @param indices the positions of the elements to be removed
6571     * @return A new array containing the existing elements except those
6572     *         at the specified positions.
6573     * @throws IndexOutOfBoundsException if any index is out of range
6574     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
6575     * @since 3.0.1
6576     */
6577    @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
6578    public static <T> T[] removeAll(final T[] array, final int... indices) {
6579        return (T[]) removeAll((Object) array, indices);
6580    }
6581
6582    /**
6583     * <p>Removes occurrences of specified elements, in specified quantities,
6584     * from the specified array. All subsequent elements are shifted left.
6585     * For any element-to-be-removed specified in greater quantities than
6586     * contained in the original array, no change occurs beyond the
6587     * removal of the existing matching items.
6588     *
6589     * <p>This method returns a new array with the same elements of the input
6590     * array except for the earliest-encountered occurrences of the specified
6591     * elements. The component type of the returned array is always the same
6592     * as that of the input array.
6593     *
6594     * <pre>
6595     * ArrayUtils.removeElements(null, "a", "b")            = null
6596     * ArrayUtils.removeElements([], "a", "b")              = []
6597     * ArrayUtils.removeElements(["a"], "b", "c")           = ["a"]
6598     * ArrayUtils.removeElements(["a", "b"], "a", "c")      = ["b"]
6599     * ArrayUtils.removeElements(["a", "b", "a"], "a")      = ["b", "a"]
6600     * ArrayUtils.removeElements(["a", "b", "a"], "a", "a") = ["b"]
6601     * </pre>
6602     *
6603     * @param <T> the component type of the array
6604     * @param array  the array to remove the element from, may be {@code null}
6605     * @param values the elements to be removed
6606     * @return A new array containing the existing elements except the
6607     *         earliest-encountered occurrences of the specified elements.
6608     * @since 3.0.1
6609     */
6610    public static <T> T[] removeElements(final T[] array, final T... values) {
6611        if (isEmpty(array) || isEmpty(values)) {
6612            return clone(array);
6613        }
6614        final HashMap<T, MutableInt> occurrences = new HashMap<T, MutableInt>(values.length);
6615        for (final T v : values) {
6616            final MutableInt count = occurrences.get(v);
6617            if (count == null) {
6618                occurrences.put(v, new MutableInt(1));
6619            } else {
6620                count.increment();
6621            }
6622        }
6623        final BitSet toRemove = new BitSet();
6624        for (int i = 0; i < array.length; i++) {
6625            final T key = array[i];
6626            final MutableInt count = occurrences.get(key);
6627            if (count != null) {
6628                if (count.decrementAndGet() == 0) {
6629                    occurrences.remove(key);
6630                }
6631                toRemove.set(i);
6632            }
6633        }
6634        @SuppressWarnings("unchecked") // removeAll() always creates an array of the same type as its input
6635        final
6636        T[] result = (T[]) removeAll(array, toRemove);
6637        return result;
6638    }
6639
6640    /**
6641     * <p>Removes the elements at the specified positions from the specified array.
6642     * All remaining elements are shifted to the left.
6643     *
6644     * <p>This method returns a new array with the same elements of the input
6645     * array except those at the specified positions. The component
6646     * type of the returned array is always the same as that of the input
6647     * array.
6648     *
6649     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
6650     * will be thrown, because in that case no valid index can be specified.
6651     *
6652     * <pre>
6653     * ArrayUtils.removeAll([1], 0)             = []
6654     * ArrayUtils.removeAll([2, 6], 0)          = [6]
6655     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
6656     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
6657     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
6658     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
6659     * </pre>
6660     *
6661     * @param array   the array to remove the element from, may not be {@code null}
6662     * @param indices the positions of the elements to be removed
6663     * @return A new array containing the existing elements except those
6664     *         at the specified positions.
6665     * @throws IndexOutOfBoundsException if any index is out of range
6666     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
6667     * @since 3.0.1
6668     */
6669    public static byte[] removeAll(final byte[] array, final int... indices) {
6670        return (byte[]) removeAll((Object) array, indices);
6671    }
6672
6673    /**
6674     * <p>Removes occurrences of specified elements, in specified quantities,
6675     * from the specified array. All subsequent elements are shifted left.
6676     * For any element-to-be-removed specified in greater quantities than
6677     * contained in the original array, no change occurs beyond the
6678     * removal of the existing matching items.
6679     *
6680     * <p>This method returns a new array with the same elements of the input
6681     * array except for the earliest-encountered occurrences of the specified
6682     * elements. The component type of the returned array is always the same
6683     * as that of the input array.
6684     *
6685     * <pre>
6686     * ArrayUtils.removeElements(null, 1, 2)      = null
6687     * ArrayUtils.removeElements([], 1, 2)        = []
6688     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6689     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6690     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6691     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6692     * </pre>
6693     *
6694     * @param array  the array to remove the element from, may be {@code null}
6695     * @param values the elements to be removed
6696     * @return A new array containing the existing elements except the
6697     *         earliest-encountered occurrences of the specified elements.
6698     * @since 3.0.1
6699     */
6700    public static byte[] removeElements(final byte[] array, final byte... values) {
6701        if (isEmpty(array) || isEmpty(values)) {
6702            return clone(array);
6703        }
6704        final Map<Byte, MutableInt> occurrences = new HashMap<Byte, MutableInt>(values.length);
6705        for (final byte v : values) {
6706            final Byte boxed = Byte.valueOf(v);
6707            final MutableInt count = occurrences.get(boxed);
6708            if (count == null) {
6709                occurrences.put(boxed, new MutableInt(1));
6710            } else {
6711                count.increment();
6712            }
6713        }
6714        final BitSet toRemove = new BitSet();
6715        for (int i = 0; i < array.length; i++) {
6716            final byte key = array[i];
6717            final MutableInt count = occurrences.get(key);
6718            if (count != null) {
6719                if (count.decrementAndGet() == 0) {
6720                    occurrences.remove(key);
6721                }
6722                toRemove.set(i);
6723            }
6724        }
6725        return (byte[]) removeAll(array, toRemove);
6726    }
6727
6728    /**
6729     * <p>Removes the elements at the specified positions from the specified array.
6730     * All remaining elements are shifted to the left.
6731     *
6732     * <p>This method returns a new array with the same elements of the input
6733     * array except those at the specified positions. The component
6734     * type of the returned array is always the same as that of the input
6735     * array.
6736     *
6737     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
6738     * will be thrown, because in that case no valid index can be specified.
6739     *
6740     * <pre>
6741     * ArrayUtils.removeAll([1], 0)             = []
6742     * ArrayUtils.removeAll([2, 6], 0)          = [6]
6743     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
6744     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
6745     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
6746     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
6747     * </pre>
6748     *
6749     * @param array   the array to remove the element from, may not be {@code null}
6750     * @param indices the positions of the elements to be removed
6751     * @return A new array containing the existing elements except those
6752     *         at the specified positions.
6753     * @throws IndexOutOfBoundsException if any index is out of range
6754     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
6755     * @since 3.0.1
6756     */
6757    public static short[] removeAll(final short[] array, final int... indices) {
6758        return (short[]) removeAll((Object) array, indices);
6759    }
6760
6761    /**
6762     * <p>Removes occurrences of specified elements, in specified quantities,
6763     * from the specified array. All subsequent elements are shifted left.
6764     * For any element-to-be-removed specified in greater quantities than
6765     * contained in the original array, no change occurs beyond the
6766     * removal of the existing matching items.
6767     *
6768     * <p>This method returns a new array with the same elements of the input
6769     * array except for the earliest-encountered occurrences of the specified
6770     * elements. The component type of the returned array is always the same
6771     * as that of the input array.
6772     *
6773     * <pre>
6774     * ArrayUtils.removeElements(null, 1, 2)      = null
6775     * ArrayUtils.removeElements([], 1, 2)        = []
6776     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6777     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6778     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6779     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6780     * </pre>
6781     *
6782     * @param array  the array to remove the element from, may be {@code null}
6783     * @param values the elements to be removed
6784     * @return A new array containing the existing elements except the
6785     *         earliest-encountered occurrences of the specified elements.
6786     * @since 3.0.1
6787     */
6788    public static short[] removeElements(final short[] array, final short... values) {
6789        if (isEmpty(array) || isEmpty(values)) {
6790            return clone(array);
6791        }
6792        final HashMap<Short, MutableInt> occurrences = new HashMap<Short, MutableInt>(values.length);
6793        for (final short v : values) {
6794            final Short boxed = Short.valueOf(v);
6795            final MutableInt count = occurrences.get(boxed);
6796            if (count == null) {
6797                occurrences.put(boxed, new MutableInt(1));
6798            } else {
6799                count.increment();
6800            }
6801        }
6802        final BitSet toRemove = new BitSet();
6803        for (int i = 0; i < array.length; i++) {
6804            final short key = array[i];
6805            final MutableInt count = occurrences.get(key);
6806            if (count != null) {
6807                if (count.decrementAndGet() == 0) {
6808                    occurrences.remove(key);
6809                }
6810                toRemove.set(i);
6811            }
6812        }
6813        return (short[]) removeAll(array, toRemove);
6814    }
6815
6816    /**
6817     * <p>Removes the elements at the specified positions from the specified array.
6818     * All remaining elements are shifted to the left.
6819     *
6820     * <p>This method returns a new array with the same elements of the input
6821     * array except those at the specified positions. The component
6822     * type of the returned array is always the same as that of the input
6823     * array.
6824     *
6825     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
6826     * will be thrown, because in that case no valid index can be specified.
6827     *
6828     * <pre>
6829     * ArrayUtils.removeAll([1], 0)             = []
6830     * ArrayUtils.removeAll([2, 6], 0)          = [6]
6831     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
6832     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
6833     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
6834     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
6835     * </pre>
6836     *
6837     * @param array   the array to remove the element from, may not be {@code null}
6838     * @param indices the positions of the elements to be removed
6839     * @return A new array containing the existing elements except those
6840     *         at the specified positions.
6841     * @throws IndexOutOfBoundsException if any index is out of range
6842     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
6843     * @since 3.0.1
6844     */
6845    public static int[] removeAll(final int[] array, final int... indices) {
6846        return (int[]) removeAll((Object) array, indices);
6847    }
6848
6849    /**
6850     * <p>Removes occurrences of specified elements, in specified quantities,
6851     * from the specified array. All subsequent elements are shifted left.
6852     * For any element-to-be-removed specified in greater quantities than
6853     * contained in the original array, no change occurs beyond the
6854     * removal of the existing matching items.
6855     *
6856     * <p>This method returns a new array with the same elements of the input
6857     * array except for the earliest-encountered occurrences of the specified
6858     * elements. The component type of the returned array is always the same
6859     * as that of the input array.
6860     *
6861     * <pre>
6862     * ArrayUtils.removeElements(null, 1, 2)      = null
6863     * ArrayUtils.removeElements([], 1, 2)        = []
6864     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6865     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6866     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6867     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6868     * </pre>
6869     *
6870     * @param array  the array to remove the element from, may be {@code null}
6871     * @param values the elements to be removed
6872     * @return A new array containing the existing elements except the
6873     *         earliest-encountered occurrences of the specified elements.
6874     * @since 3.0.1
6875     */
6876    public static int[] removeElements(final int[] array, final int... values) {
6877        if (isEmpty(array) || isEmpty(values)) {
6878            return clone(array);
6879        }
6880        final HashMap<Integer, MutableInt> occurrences = new HashMap<Integer, MutableInt>(values.length);
6881        for (final int v : values) {
6882            final Integer boxed = Integer.valueOf(v);
6883            final MutableInt count = occurrences.get(boxed);
6884            if (count == null) {
6885                occurrences.put(boxed, new MutableInt(1));
6886            } else {
6887                count.increment();
6888            }
6889        }
6890        final BitSet toRemove = new BitSet();
6891        for (int i = 0; i < array.length; i++) {
6892            final int key = array[i];
6893            final MutableInt count = occurrences.get(key);
6894            if (count != null) {
6895                if (count.decrementAndGet() == 0) {
6896                    occurrences.remove(key);
6897                }
6898                toRemove.set(i);
6899            }
6900        }
6901        return (int[]) removeAll(array, toRemove);
6902    }
6903
6904    /**
6905     * <p>Removes the elements at the specified positions from the specified array.
6906     * All remaining elements are shifted to the left.
6907     *
6908     * <p>This method returns a new array with the same elements of the input
6909     * array except those at the specified positions. The component
6910     * type of the returned array is always the same as that of the input
6911     * array.
6912     *
6913     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
6914     * will be thrown, because in that case no valid index can be specified.
6915     *
6916     * <pre>
6917     * ArrayUtils.removeAll([1], 0)             = []
6918     * ArrayUtils.removeAll([2, 6], 0)          = [6]
6919     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
6920     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
6921     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
6922     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
6923     * </pre>
6924     *
6925     * @param array   the array to remove the element from, may not be {@code null}
6926     * @param indices the positions of the elements to be removed
6927     * @return A new array containing the existing elements except those
6928     *         at the specified positions.
6929     * @throws IndexOutOfBoundsException if any index is out of range
6930     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
6931     * @since 3.0.1
6932     */
6933    public static char[] removeAll(final char[] array, final int... indices) {
6934        return (char[]) removeAll((Object) array, indices);
6935    }
6936
6937    /**
6938     * <p>Removes occurrences of specified elements, in specified quantities,
6939     * from the specified array. All subsequent elements are shifted left.
6940     * For any element-to-be-removed specified in greater quantities than
6941     * contained in the original array, no change occurs beyond the
6942     * removal of the existing matching items.
6943     *
6944     * <p>This method returns a new array with the same elements of the input
6945     * array except for the earliest-encountered occurrences of the specified
6946     * elements. The component type of the returned array is always the same
6947     * as that of the input array.
6948     *
6949     * <pre>
6950     * ArrayUtils.removeElements(null, 1, 2)      = null
6951     * ArrayUtils.removeElements([], 1, 2)        = []
6952     * ArrayUtils.removeElements([1], 2, 3)       = [1]
6953     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
6954     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
6955     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
6956     * </pre>
6957     *
6958     * @param array  the array to remove the element from, may be {@code null}
6959     * @param values the elements to be removed
6960     * @return A new array containing the existing elements except the
6961     *         earliest-encountered occurrences of the specified elements.
6962     * @since 3.0.1
6963     */
6964    public static char[] removeElements(final char[] array, final char... values) {
6965        if (isEmpty(array) || isEmpty(values)) {
6966            return clone(array);
6967        }
6968        final HashMap<Character, MutableInt> occurrences = new HashMap<Character, MutableInt>(values.length);
6969        for (final char v : values) {
6970            final Character boxed = Character.valueOf(v);
6971            final MutableInt count = occurrences.get(boxed);
6972            if (count == null) {
6973                occurrences.put(boxed, new MutableInt(1));
6974            } else {
6975                count.increment();
6976            }
6977        }
6978        final BitSet toRemove = new BitSet();
6979        for (int i = 0; i < array.length; i++) {
6980            final char key = array[i];
6981            final MutableInt count = occurrences.get(key);
6982            if (count != null) {
6983                if (count.decrementAndGet() == 0) {
6984                    occurrences.remove(key);
6985                }
6986                toRemove.set(i);
6987            }
6988        }
6989        return (char[]) removeAll(array, toRemove);
6990    }
6991
6992    /**
6993     * <p>Removes the elements at the specified positions from the specified array.
6994     * All remaining elements are shifted to the left.
6995     *
6996     * <p>This method returns a new array with the same elements of the input
6997     * array except those at the specified positions. The component
6998     * type of the returned array is always the same as that of the input
6999     * array.
7000     *
7001     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
7002     * will be thrown, because in that case no valid index can be specified.
7003     *
7004     * <pre>
7005     * ArrayUtils.removeAll([1], 0)             = []
7006     * ArrayUtils.removeAll([2, 6], 0)          = [6]
7007     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
7008     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
7009     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
7010     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
7011     * </pre>
7012     *
7013     * @param array   the array to remove the element from, may not be {@code null}
7014     * @param indices the positions of the elements to be removed
7015     * @return A new array containing the existing elements except those
7016     *         at the specified positions.
7017     * @throws IndexOutOfBoundsException if any index is out of range
7018     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
7019     * @since 3.0.1
7020     */
7021    public static long[] removeAll(final long[] array, final int... indices) {
7022        return (long[]) removeAll((Object) array, indices);
7023    }
7024
7025    /**
7026     * <p>Removes occurrences of specified elements, in specified quantities,
7027     * from the specified array. All subsequent elements are shifted left.
7028     * For any element-to-be-removed specified in greater quantities than
7029     * contained in the original array, no change occurs beyond the
7030     * removal of the existing matching items.
7031     *
7032     * <p>This method returns a new array with the same elements of the input
7033     * array except for the earliest-encountered occurrences of the specified
7034     * elements. The component type of the returned array is always the same
7035     * as that of the input array.
7036     *
7037     * <pre>
7038     * ArrayUtils.removeElements(null, 1, 2)      = null
7039     * ArrayUtils.removeElements([], 1, 2)        = []
7040     * ArrayUtils.removeElements([1], 2, 3)       = [1]
7041     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
7042     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
7043     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
7044     * </pre>
7045     *
7046     * @param array  the array to remove the element from, may be {@code null}
7047     * @param values the elements to be removed
7048     * @return A new array containing the existing elements except the
7049     *         earliest-encountered occurrences of the specified elements.
7050     * @since 3.0.1
7051     */
7052    public static long[] removeElements(final long[] array, final long... values) {
7053        if (isEmpty(array) || isEmpty(values)) {
7054            return clone(array);
7055        }
7056        final HashMap<Long, MutableInt> occurrences = new HashMap<Long, MutableInt>(values.length);
7057        for (final long v : values) {
7058            final Long boxed = Long.valueOf(v);
7059            final MutableInt count = occurrences.get(boxed);
7060            if (count == null) {
7061                occurrences.put(boxed, new MutableInt(1));
7062            } else {
7063                count.increment();
7064            }
7065        }
7066        final BitSet toRemove = new BitSet();
7067        for (int i = 0; i < array.length; i++) {
7068            final long key = array[i];
7069            final MutableInt count = occurrences.get(key);
7070            if (count != null) {
7071                if (count.decrementAndGet() == 0) {
7072                    occurrences.remove(key);
7073                }
7074                toRemove.set(i);
7075            }
7076        }
7077        return (long[]) removeAll(array, toRemove);
7078    }
7079
7080    /**
7081     * <p>Removes the elements at the specified positions from the specified array.
7082     * All remaining elements are shifted to the left.
7083     *
7084     * <p>This method returns a new array with the same elements of the input
7085     * array except those at the specified positions. The component
7086     * type of the returned array is always the same as that of the input
7087     * array.
7088     *
7089     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
7090     * will be thrown, because in that case no valid index can be specified.
7091     *
7092     * <pre>
7093     * ArrayUtils.removeAll([1], 0)             = []
7094     * ArrayUtils.removeAll([2, 6], 0)          = [6]
7095     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
7096     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
7097     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
7098     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
7099     * </pre>
7100     *
7101     * @param array   the array to remove the element from, may not be {@code null}
7102     * @param indices the positions of the elements to be removed
7103     * @return A new array containing the existing elements except those
7104     *         at the specified positions.
7105     * @throws IndexOutOfBoundsException if any index is out of range
7106     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
7107     * @since 3.0.1
7108     */
7109    public static float[] removeAll(final float[] array, final int... indices) {
7110        return (float[]) removeAll((Object) array, indices);
7111    }
7112
7113    /**
7114     * <p>Removes occurrences of specified elements, in specified quantities,
7115     * from the specified array. All subsequent elements are shifted left.
7116     * For any element-to-be-removed specified in greater quantities than
7117     * contained in the original array, no change occurs beyond the
7118     * removal of the existing matching items.
7119     *
7120     * <p>This method returns a new array with the same elements of the input
7121     * array except for the earliest-encountered occurrences of the specified
7122     * elements. The component type of the returned array is always the same
7123     * as that of the input array.
7124     *
7125     * <pre>
7126     * ArrayUtils.removeElements(null, 1, 2)      = null
7127     * ArrayUtils.removeElements([], 1, 2)        = []
7128     * ArrayUtils.removeElements([1], 2, 3)       = [1]
7129     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
7130     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
7131     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
7132     * </pre>
7133     *
7134     * @param array  the array to remove the element from, may be {@code null}
7135     * @param values the elements to be removed
7136     * @return A new array containing the existing elements except the
7137     *         earliest-encountered occurrences of the specified elements.
7138     * @since 3.0.1
7139     */
7140    public static float[] removeElements(final float[] array, final float... values) {
7141        if (isEmpty(array) || isEmpty(values)) {
7142            return clone(array);
7143        }
7144        final HashMap<Float, MutableInt> occurrences = new HashMap<Float, MutableInt>(values.length);
7145        for (final float v : values) {
7146            final Float boxed = Float.valueOf(v);
7147            final MutableInt count = occurrences.get(boxed);
7148            if (count == null) {
7149                occurrences.put(boxed, new MutableInt(1));
7150            } else {
7151                count.increment();
7152            }
7153        }
7154        final BitSet toRemove = new BitSet();
7155        for (int i = 0; i < array.length; i++) {
7156            final float key = array[i];
7157            final MutableInt count = occurrences.get(key);
7158            if (count != null) {
7159                if (count.decrementAndGet() == 0) {
7160                    occurrences.remove(key);
7161                }
7162                toRemove.set(i);
7163            }
7164        }
7165        return (float[]) removeAll(array, toRemove);
7166    }
7167
7168    /**
7169     * <p>Removes the elements at the specified positions from the specified array.
7170     * All remaining elements are shifted to the left.
7171     *
7172     * <p>This method returns a new array with the same elements of the input
7173     * array except those at the specified positions. The component
7174     * type of the returned array is always the same as that of the input
7175     * array.
7176     *
7177     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
7178     * will be thrown, because in that case no valid index can be specified.
7179     *
7180     * <pre>
7181     * ArrayUtils.removeAll([1], 0)             = []
7182     * ArrayUtils.removeAll([2, 6], 0)          = [6]
7183     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
7184     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
7185     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
7186     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
7187     * </pre>
7188     *
7189     * @param array   the array to remove the element from, may not be {@code null}
7190     * @param indices the positions of the elements to be removed
7191     * @return A new array containing the existing elements except those
7192     *         at the specified positions.
7193     * @throws IndexOutOfBoundsException if any index is out of range
7194     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
7195     * @since 3.0.1
7196     */
7197    public static double[] removeAll(final double[] array, final int... indices) {
7198        return (double[]) removeAll((Object) array, indices);
7199    }
7200
7201    /**
7202     * <p>Removes occurrences of specified elements, in specified quantities,
7203     * from the specified array. All subsequent elements are shifted left.
7204     * For any element-to-be-removed specified in greater quantities than
7205     * contained in the original array, no change occurs beyond the
7206     * removal of the existing matching items.
7207     *
7208     * <p>This method returns a new array with the same elements of the input
7209     * array except for the earliest-encountered occurrences of the specified
7210     * elements. The component type of the returned array is always the same
7211     * as that of the input array.
7212     *
7213     * <pre>
7214     * ArrayUtils.removeElements(null, 1, 2)      = null
7215     * ArrayUtils.removeElements([], 1, 2)        = []
7216     * ArrayUtils.removeElements([1], 2, 3)       = [1]
7217     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
7218     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
7219     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
7220     * </pre>
7221     *
7222     * @param array  the array to remove the element from, may be {@code null}
7223     * @param values the elements to be removed
7224     * @return A new array containing the existing elements except the
7225     *         earliest-encountered occurrences of the specified elements.
7226     * @since 3.0.1
7227     */
7228    public static double[] removeElements(final double[] array, final double... values) {
7229        if (isEmpty(array) || isEmpty(values)) {
7230            return clone(array);
7231        }
7232        final HashMap<Double, MutableInt> occurrences = new HashMap<Double, MutableInt>(values.length);
7233        for (final double v : values) {
7234            final Double boxed = Double.valueOf(v);
7235            final MutableInt count = occurrences.get(boxed);
7236            if (count == null) {
7237                occurrences.put(boxed, new MutableInt(1));
7238            } else {
7239                count.increment();
7240            }
7241        }
7242        final BitSet toRemove = new BitSet();
7243        for (int i = 0; i < array.length; i++) {
7244            final double key = array[i];
7245            final MutableInt count = occurrences.get(key);
7246            if (count != null) {
7247                if (count.decrementAndGet() == 0) {
7248                    occurrences.remove(key);
7249                }
7250                toRemove.set(i);
7251            }
7252        }
7253        return (double[]) removeAll(array, toRemove);
7254    }
7255
7256    /**
7257     * <p>Removes the elements at the specified positions from the specified array.
7258     * All remaining elements are shifted to the left.
7259     *
7260     * <p>This method returns a new array with the same elements of the input
7261     * array except those at the specified positions. The component
7262     * type of the returned array is always the same as that of the input
7263     * array.
7264     *
7265     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
7266     * will be thrown, because in that case no valid index can be specified.
7267     *
7268     * <pre>
7269     * ArrayUtils.removeAll([true, false, true], 0, 2) = [false]
7270     * ArrayUtils.removeAll([true, false, true], 1, 2) = [true]
7271     * </pre>
7272     *
7273     * @param array   the array to remove the element from, may not be {@code null}
7274     * @param indices the positions of the elements to be removed
7275     * @return A new array containing the existing elements except those
7276     *         at the specified positions.
7277     * @throws IndexOutOfBoundsException if any index is out of range
7278     * (index &lt; 0 || index &gt;= array.length), or if the array is {@code null}.
7279     * @since 3.0.1
7280     */
7281    public static boolean[] removeAll(final boolean[] array, final int... indices) {
7282        return (boolean[]) removeAll((Object) array, indices);
7283    }
7284
7285    /**
7286     * <p>Removes occurrences of specified elements, in specified quantities,
7287     * from the specified array. All subsequent elements are shifted left.
7288     * For any element-to-be-removed specified in greater quantities than
7289     * contained in the original array, no change occurs beyond the
7290     * removal of the existing matching items.
7291     *
7292     * <p>This method returns a new array with the same elements of the input
7293     * array except for the earliest-encountered occurrences of the specified
7294     * elements. The component type of the returned array is always the same
7295     * as that of the input array.
7296     *
7297     * <pre>
7298     * ArrayUtils.removeElements(null, true, false)               = null
7299     * ArrayUtils.removeElements([], true, false)                 = []
7300     * ArrayUtils.removeElements([true], false, false)            = [true]
7301     * ArrayUtils.removeElements([true, false], true, true)       = [false]
7302     * ArrayUtils.removeElements([true, false, true], true)       = [false, true]
7303     * ArrayUtils.removeElements([true, false, true], true, true) = [false]
7304     * </pre>
7305     *
7306     * @param array  the array to remove the element from, may be {@code null}
7307     * @param values the elements to be removed
7308     * @return A new array containing the existing elements except the
7309     *         earliest-encountered occurrences of the specified elements.
7310     * @since 3.0.1
7311     */
7312    public static boolean[] removeElements(final boolean[] array, final boolean... values) {
7313        if (isEmpty(array) || isEmpty(values)) {
7314            return clone(array);
7315        }
7316        final HashMap<Boolean, MutableInt> occurrences = new HashMap<Boolean, MutableInt>(2); // only two possible values here
7317        for (final boolean v : values) {
7318            final Boolean boxed = Boolean.valueOf(v);
7319            final MutableInt count = occurrences.get(boxed);
7320            if (count == null) {
7321                occurrences.put(boxed, new MutableInt(1));
7322            } else {
7323                count.increment();
7324            }
7325        }
7326        final BitSet toRemove = new BitSet();
7327        for (int i = 0; i < array.length; i++) {
7328            final boolean key = array[i];
7329            final MutableInt count = occurrences.get(key);
7330            if (count != null) {
7331                if (count.decrementAndGet() == 0) {
7332                    occurrences.remove(key);
7333                }
7334                toRemove.set(i);
7335            }
7336        }
7337        return (boolean[]) removeAll(array, toRemove);
7338    }
7339
7340    /**
7341     * Removes multiple array elements specified by index.
7342     * @param array source
7343     * @param indices to remove
7344     * @return new array of same type minus elements specified by unique values of {@code indices}
7345     * @since 3.0.1
7346     */
7347    // package protected for access by unit tests
7348    static Object removeAll(final Object array, final int... indices) {
7349        final int length = getLength(array);
7350        int diff = 0; // number of distinct indexes, i.e. number of entries that will be removed
7351        int[] clonedIndices = clone(indices);
7352        Arrays.sort(clonedIndices);
7353
7354        // identify length of result array
7355        if (isNotEmpty(clonedIndices)) {
7356            int i = clonedIndices.length;
7357            int prevIndex = length;
7358            while (--i >= 0) {
7359                final int index = clonedIndices[i];
7360                if (index < 0 || index >= length) {
7361                    throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
7362                }
7363                if (index >= prevIndex) {
7364                    continue;
7365                }
7366                diff++;
7367                prevIndex = index;
7368            }
7369        }
7370
7371        // create result array
7372        final Object result = Array.newInstance(array.getClass().getComponentType(), length - diff);
7373        if (diff < length) {
7374            int end = length; // index just after last copy
7375            int dest = length - diff; // number of entries so far not copied
7376            for (int i = clonedIndices.length - 1; i >= 0; i--) {
7377                final int index = clonedIndices[i];
7378                if (end - index > 1) { // same as (cp > 0)
7379                    final int cp = end - index - 1;
7380                    dest -= cp;
7381                    System.arraycopy(array, index + 1, result, dest, cp);
7382                    // Afer this copy, we still have room for dest items.
7383                }
7384                end = index;
7385            }
7386            if (end > 0) {
7387                System.arraycopy(array, 0, result, 0, end);
7388            }
7389        }
7390        return result;
7391    }
7392
7393    /**
7394     * Removes multiple array elements specified by indices.
7395     * 
7396     * @param array source
7397     * @param indices to remove
7398     * @return new array of same type minus elements specified by the set bits in {@code indices}
7399     * @since 3.2
7400     */
7401    // package protected for access by unit tests
7402    static Object removeAll(final Object array, final BitSet indices) {
7403        final int srcLength = ArrayUtils.getLength(array);
7404        // No need to check maxIndex here, because method only currently called from removeElements()
7405        // which guarantee to generate on;y valid bit entries.
7406//        final int maxIndex = indices.length();
7407//        if (maxIndex > srcLength) { 
7408//            throw new IndexOutOfBoundsException("Index: " + (maxIndex-1) + ", Length: " + srcLength);
7409//        }
7410        final int removals = indices.cardinality(); // true bits are items to remove
7411        final Object result = Array.newInstance(array.getClass().getComponentType(), srcLength - removals);
7412        int srcIndex = 0;
7413        int destIndex = 0;
7414        int count;
7415        int set;
7416        while ((set = indices.nextSetBit(srcIndex)) != -1) {
7417            count = set - srcIndex;
7418            if (count > 0) {
7419                System.arraycopy(array, srcIndex, result, destIndex, count);
7420                destIndex += count;
7421            }
7422            srcIndex = indices.nextClearBit(set);
7423        }
7424        count = srcLength - srcIndex;
7425        if (count > 0) {
7426            System.arraycopy(array, srcIndex, result, destIndex, count);            
7427        }
7428        return result;
7429    }
7430
7431    /**
7432     * <p>This method checks whether the provided array is sorted according to the class's 
7433     * {@code compareTo} method.
7434     *
7435     * @param array the array to check
7436     * @param <T> the datatype of the array to check, it must implement {@code Comparable}
7437     * @return whether the array is sorted
7438     * @since 3.4
7439     */
7440    public static <T extends Comparable<? super T>> boolean isSorted(final T[] array) {
7441        return isSorted(array, new Comparator<T>() {
7442            @Override
7443            public int compare(T o1, T o2) {
7444                return o1.compareTo(o2);
7445            }
7446        });
7447    }
7448   
7449
7450    /**
7451     * <p>This method checks whether the provided array is sorted according to the provided {@code Comparator}.
7452     *
7453     * @param array the array to check
7454     * @param comparator the {@code Comparator} to compare over
7455     * @param <T> the datatype of the array
7456     * @return whether the array is sorted
7457     * @since 3.4
7458     */
7459    public static <T> boolean isSorted(final T[] array, final Comparator<T> comparator) {
7460        if (comparator == null) {
7461            throw new IllegalArgumentException("Comparator should not be null.");
7462        }
7463        
7464        if (array == null || array.length < 2) {
7465            return true;
7466        }
7467
7468        T previous = array[0];
7469        final int n = array.length;
7470        for (int i = 1; i < n; i++) {
7471            final T current = array[i];
7472            if (comparator.compare(previous, current) > 0) {
7473                return false;
7474            }
7475
7476            previous = current;
7477        }
7478        return true;
7479    }
7480
7481    /**
7482     * <p>This method checks whether the provided array is sorted according to natural ordering.
7483     *
7484     * @param array the array to check
7485     * @return whether the array is sorted according to natural ordering
7486     * @since 3.4
7487     */
7488    public static boolean isSorted(int[] array) {
7489        if (array == null || array.length < 2) {
7490            return true;
7491        }
7492
7493        int previous = array[0];
7494        final int n = array.length;
7495        for (int i = 1; i < n; i++) {
7496            final int current = array[i];
7497            if (NumberUtils.compare(previous, current) > 0) {
7498                return false;
7499            }
7500
7501            previous = current;
7502        }
7503        return true;
7504    }
7505
7506    /**
7507     * <p>This method checks whether the provided array is sorted according to natural ordering.
7508     *
7509     * @param array the array to check
7510     * @return whether the array is sorted according to natural ordering
7511     * @since 3.4
7512     */
7513    public static boolean isSorted(long[] array) {
7514        if (array == null || array.length < 2) {
7515            return true;
7516        }
7517
7518        long previous = array[0];
7519        final int n = array.length;
7520        for (int i = 1; i < n; i++) {
7521            final long current = array[i];
7522            if (NumberUtils.compare(previous, current) > 0) {
7523                return false;
7524            }
7525
7526            previous = current;
7527        }
7528        return true;
7529    }
7530
7531    /**
7532     * <p>This method checks whether the provided array is sorted according to natural ordering.
7533     *
7534     * @param array the array to check
7535     * @return whether the array is sorted according to natural ordering
7536     * @since 3.4
7537     */
7538    public static boolean isSorted(short[] array) {
7539        if (array == null || array.length < 2) {
7540            return true;
7541        }
7542
7543        short previous = array[0];
7544        final int n = array.length;
7545        for (int i = 1; i < n; i++) {
7546            final short current = array[i];
7547            if (NumberUtils.compare(previous, current) > 0) {
7548                return false;
7549            }
7550
7551            previous = current;
7552        }
7553        return true;
7554    }
7555
7556    /**
7557     * <p>This method checks whether the provided array is sorted according to natural ordering.
7558     *
7559     * @param array the array to check
7560     * @return whether the array is sorted according to natural ordering
7561     * @since 3.4
7562     */
7563    public static boolean isSorted(final double[] array) {
7564        if (array == null || array.length < 2) {
7565            return true;
7566        }
7567
7568        double previous = array[0];
7569        final int n = array.length;
7570        for (int i = 1; i < n; i++) {
7571            final double current = array[i];
7572            if (Double.compare(previous, current) > 0) {
7573                return false;
7574            }
7575
7576            previous = current;
7577        }
7578        return true;
7579    }
7580
7581    /**
7582     * <p>This method checks whether the provided array is sorted according to natural ordering.
7583     *
7584     * @param array the array to check
7585     * @return whether the array is sorted according to natural ordering
7586     * @since 3.4
7587     */
7588    public static boolean isSorted(final float[] array) {
7589        if (array == null || array.length < 2) {
7590            return true;
7591        }
7592
7593        float previous = array[0];
7594        final int n = array.length;
7595        for (int i = 1; i < n; i++) {
7596            final float current = array[i];
7597            if (Float.compare(previous, current) > 0) {
7598                return false;
7599            }
7600
7601            previous = current;
7602        }
7603        return true;
7604    }
7605
7606    /**
7607     * <p>This method checks whether the provided array is sorted according to natural ordering.
7608     *
7609     * @param array the array to check
7610     * @return whether the array is sorted according to natural ordering
7611     * @since 3.4
7612     */
7613    public static boolean isSorted(byte[] array) {
7614        if (array == null || array.length < 2) {
7615            return true;
7616        }
7617
7618        byte previous = array[0];
7619        final int n = array.length;
7620        for (int i = 1; i < n; i++) {
7621            final byte current = array[i];
7622            if (NumberUtils.compare(previous, current) > 0) {
7623                return false;
7624            }
7625
7626            previous = current;
7627        }
7628        return true;
7629    }
7630
7631    /**
7632     * <p>This method checks whether the provided array is sorted according to natural ordering.
7633     *
7634     * @param array the array to check
7635     * @return whether the array is sorted according to natural ordering
7636     * @since 3.4
7637     */
7638    public static boolean isSorted(char[] array) {
7639        if (array == null || array.length < 2) {
7640            return true;
7641        }
7642
7643        char previous = array[0];
7644        final int n = array.length;
7645        for (int i = 1; i < n; i++) {
7646            final char current = array[i];
7647            if (CharUtils.compare(previous, current) > 0) {
7648                return false;
7649            }
7650
7651            previous = current;
7652        }
7653        return true;
7654    }
7655
7656    /**
7657     * <p>This method checks whether the provided array is sorted according to natural ordering
7658     * ({@code false} before {@code true}).
7659     *
7660     * @param array the array to check
7661     * @return whether the array is sorted according to natural ordering
7662     * @since 3.4
7663     */
7664    public static boolean isSorted(boolean[] array) {
7665        if (array == null || array.length < 2) {
7666            return true;
7667        }
7668
7669        boolean previous = array[0];
7670        final int n = array.length;
7671        for (int i = 1; i < n; i++) {
7672            final boolean current = array[i];
7673            if (BooleanUtils.compare(previous, current) > 0) {
7674                return false;
7675            }
7676
7677            previous = current;
7678        }
7679        return true;
7680    }
7681
7682    /**
7683     * Removes the occurrences of the specified element from the specified boolean array.
7684     *
7685     * <p>
7686     * All subsequent elements are shifted to the left (subtracts one from their indices).
7687     * If the array doesn't contains such an element, no elements are removed from the array.
7688     * <code>null</code> will be returned if the input array is <code>null</code>.
7689     * </p>
7690     *
7691     * @param element the element to remove
7692     * @param array the input array
7693     *
7694     * @return A new array containing the existing elements except the occurrences of the specified element.
7695     * @since 3.5
7696     */
7697    public static boolean[] removeAllOccurences(final boolean[] array, final boolean element) {
7698        int index = indexOf(array, element);
7699        if (index == INDEX_NOT_FOUND) {
7700            return clone(array);
7701        }
7702
7703        int[] indices = new int[array.length - index];
7704        indices[0] = index;
7705        int count = 1;
7706
7707        while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
7708            indices[count++] = index;
7709        }
7710
7711        return removeAll(array, Arrays.copyOf(indices, count));
7712    }
7713
7714    /**
7715     * Removes the occurrences of the specified element from the specified char array.
7716     *
7717     * <p>
7718     * All subsequent elements are shifted to the left (subtracts one from their indices).
7719     * If the array doesn't contains such an element, no elements are removed from the array.
7720     * <code>null</code> will be returned if the input array is <code>null</code>.
7721     * </p>
7722     *
7723     * @param element the element to remove
7724     * @param array the input array
7725     *
7726     * @return A new array containing the existing elements except the occurrences of the specified element.
7727     * @since 3.5
7728     */
7729    public static char[] removeAllOccurences(final char[] array, final char element) {
7730        int index = indexOf(array, element);
7731        if (index == INDEX_NOT_FOUND) {
7732            return clone(array);
7733        }
7734
7735        int[] indices = new int[array.length - index];
7736        indices[0] = index;
7737        int count = 1;
7738
7739        while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
7740            indices[count++] = index;
7741        }
7742
7743        return removeAll(array, Arrays.copyOf(indices, count));
7744    }
7745
7746    /**
7747     * Removes the occurrences of the specified element from the specified byte array.
7748     *
7749     * <p>
7750     * All subsequent elements are shifted to the left (subtracts one from their indices).
7751     * If the array doesn't contains such an element, no elements are removed from the array.
7752     * <code>null</code> will be returned if the input array is <code>null</code>.
7753     * </p>
7754     *
7755     * @param element the element to remove
7756     * @param array the input array
7757     *
7758     * @return A new array containing the existing elements except the occurrences of the specified element.
7759     * @since 3.5
7760     */
7761    public static byte[] removeAllOccurences(final byte[] array, final byte element) {
7762        int index = indexOf(array, element);
7763        if (index == INDEX_NOT_FOUND) {
7764            return clone(array);
7765        }
7766
7767        int[] indices = new int[array.length - index];
7768        indices[0] = index;
7769        int count = 1;
7770
7771        while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
7772            indices[count++] = index;
7773        }
7774
7775        return removeAll(array, Arrays.copyOf(indices, count));
7776    }
7777
7778    /**
7779     * Removes the occurrences of the specified element from the specified short array.
7780     *
7781     * <p>
7782     * All subsequent elements are shifted to the left (subtracts one from their indices).
7783     * If the array doesn't contains such an element, no elements are removed from the array.
7784     * <code>null</code> will be returned if the input array is <code>null</code>.
7785     * </p>
7786     *
7787     * @param element the element to remove
7788     * @param array the input array
7789     *
7790     * @return A new array containing the existing elements except the occurrences of the specified element.
7791     * @since 3.5
7792     */
7793    public static short[] removeAllOccurences(final short[] array, final short element) {
7794        int index = indexOf(array, element);
7795        if (index == INDEX_NOT_FOUND) {
7796            return clone(array);
7797        }
7798
7799        int[] indices = new int[array.length - index];
7800        indices[0] = index;
7801        int count = 1;
7802
7803        while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
7804            indices[count++] = index;
7805        }
7806
7807        return removeAll(array, Arrays.copyOf(indices, count));
7808    }
7809
7810    /**
7811     * Removes the occurrences of the specified element from the specified int array.
7812     *
7813     * <p>
7814     * All subsequent elements are shifted to the left (subtracts one from their indices).
7815     * If the array doesn't contains such an element, no elements are removed from the array.
7816     * <code>null</code> will be returned if the input array is <code>null</code>.
7817     * </p>
7818     *
7819     * @param element the element to remove
7820     * @param array the input array
7821     *
7822     * @return A new array containing the existing elements except the occurrences of the specified element.
7823     * @since 3.5
7824     */
7825    public static int[] removeAllOccurences(final int[] array, final int element) {
7826        int index = indexOf(array, element);
7827        if (index == INDEX_NOT_FOUND) {
7828            return clone(array);
7829        }
7830
7831        int[] indices = new int[array.length - index];
7832        indices[0] = index;
7833        int count = 1;
7834
7835        while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
7836            indices[count++] = index;
7837        }
7838
7839        return removeAll(array, Arrays.copyOf(indices, count));
7840    }
7841
7842    /**
7843     * Removes the occurrences of the specified element from the specified long array.
7844     *
7845     * <p>
7846     * All subsequent elements are shifted to the left (subtracts one from their indices).
7847     * If the array doesn't contains such an element, no elements are removed from the array.
7848     * <code>null</code> will be returned if the input array is <code>null</code>.
7849     * </p>
7850     *
7851     * @param element the element to remove
7852     * @param array the input array
7853     *
7854     * @return A new array containing the existing elements except the occurrences of the specified element.
7855     * @since 3.5
7856     */
7857    public static long[] removeAllOccurences(final long[] array, final long element) {
7858        int index = indexOf(array, element);
7859        if (index == INDEX_NOT_FOUND) {
7860            return clone(array);
7861        }
7862
7863        int[] indices = new int[array.length - index];
7864        indices[0] = index;
7865        int count = 1;
7866
7867        while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
7868            indices[count++] = index;
7869        }
7870
7871        return removeAll(array, Arrays.copyOf(indices, count));
7872    }
7873
7874    /**
7875     * Removes the occurrences of the specified element from the specified float array.
7876     *
7877     * <p>
7878     * All subsequent elements are shifted to the left (subtracts one from their indices).
7879     * If the array doesn't contains such an element, no elements are removed from the array.
7880     * <code>null</code> will be returned if the input array is <code>null</code>.
7881     * </p>
7882     *
7883     * @param element the element to remove
7884     * @param array the input array
7885     *
7886     * @return A new array containing the existing elements except the occurrences of the specified element.
7887     * @since 3.5
7888     */
7889    public static float[] removeAllOccurences(final float[] array, final float element) {
7890        int index = indexOf(array, element);
7891        if (index == INDEX_NOT_FOUND) {
7892            return clone(array);
7893        }
7894
7895        int[] indices = new int[array.length - index];
7896        indices[0] = index;
7897        int count = 1;
7898
7899        while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
7900            indices[count++] = index;
7901        }
7902
7903        return removeAll(array, Arrays.copyOf(indices, count));
7904    }
7905
7906    /**
7907     * Removes the occurrences of the specified element from the specified double array.
7908     *
7909     * <p>
7910     * All subsequent elements are shifted to the left (subtracts one from their indices).
7911     * If the array doesn't contains such an element, no elements are removed from the array.
7912     * <code>null</code> will be returned if the input array is <code>null</code>.
7913     * </p>
7914     *
7915     * @param element the element to remove
7916     * @param array the input array
7917     *
7918     * @return A new array containing the existing elements except the occurrences of the specified element.
7919     * @since 3.5
7920     */
7921    public static double[] removeAllOccurences(final double[] array, final double element) {
7922        int index = indexOf(array, element);
7923        if (index == INDEX_NOT_FOUND) {
7924            return clone(array);
7925        }
7926
7927        int[] indices = new int[array.length - index];
7928        indices[0] = index;
7929        int count = 1;
7930
7931        while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
7932            indices[count++] = index;
7933        }
7934
7935        return removeAll(array, Arrays.copyOf(indices, count));
7936    }
7937
7938    /**
7939     * Removes the occurrences of the specified element from the specified array.
7940     *
7941     * <p>
7942     * All subsequent elements are shifted to the left (subtracts one from their indices).
7943     * If the array doesn't contains such an element, no elements are removed from the array.
7944     * <code>null</code> will be returned if the input array is <code>null</code>.
7945     * </p>
7946     *
7947     * @param <T> the type of object in the array
7948     * @param element the element to remove
7949     * @param array the input array
7950     *
7951     * @return A new array containing the existing elements except the occurrences of the specified element.
7952     * @since 3.5
7953     */
7954    public static <T> T[] removeAllOccurences(final T[] array, final T element) {
7955        int index = indexOf(array, element);
7956        if (index == INDEX_NOT_FOUND) {
7957            return clone(array);
7958        }
7959
7960        int[] indices = new int[array.length - index];
7961        indices[0] = index;
7962        int count = 1;
7963
7964        while ((index = indexOf(array, element, indices[count - 1] + 1)) != INDEX_NOT_FOUND) {
7965            indices[count++] = index;
7966        }
7967
7968        return removeAll(array, Arrays.copyOf(indices, count));
7969    }
7970}