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