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