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