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