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     */
017    package org.apache.commons.lang3;
018    
019    import java.lang.reflect.Array;
020    import java.util.Arrays;
021    import java.util.HashMap;
022    import java.util.HashSet;
023    import java.util.Map;
024    
025    import org.apache.commons.lang3.builder.EqualsBuilder;
026    import org.apache.commons.lang3.builder.HashCodeBuilder;
027    import org.apache.commons.lang3.builder.ToStringBuilder;
028    import org.apache.commons.lang3.builder.ToStringStyle;
029    import org.apache.commons.lang3.mutable.MutableInt;
030    
031    /**
032     * <p>Operations on arrays, primitive arrays (like {@code int[]}) and
033     * primitive wrapper arrays (like {@code Integer[]}).</p>
034     *
035     * <p>This class tries to handle {@code null} input gracefully.
036     * An exception will not be thrown for a {@code null}
037     * array input. However, an Object array that contains a {@code null}
038     * element may throw an exception. Each method documents its behaviour.</p>
039     *
040     * <p>#ThreadSafe#</p>
041     * @since 2.0
042     * @version $Id: ArrayUtils.java 1154216 2011-08-05 13:57:16Z mbenson $
043     */
044    public class ArrayUtils {
045    
046        /**
047         * An empty immutable {@code Object} array.
048         */
049        public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
050        /**
051         * An empty immutable {@code Class} array.
052         */
053        public static final Class<?>[] EMPTY_CLASS_ARRAY = new Class[0];
054        /**
055         * An empty immutable {@code String} array.
056         */
057        public static final String[] EMPTY_STRING_ARRAY = new String[0];
058        /**
059         * An empty immutable {@code long} array.
060         */
061        public static final long[] EMPTY_LONG_ARRAY = new long[0];
062        /**
063         * An empty immutable {@code Long} array.
064         */
065        public static final Long[] EMPTY_LONG_OBJECT_ARRAY = new Long[0];
066        /**
067         * An empty immutable {@code int} array.
068         */
069        public static final int[] EMPTY_INT_ARRAY = new int[0];
070        /**
071         * An empty immutable {@code Integer} array.
072         */
073        public static final Integer[] EMPTY_INTEGER_OBJECT_ARRAY = new Integer[0];
074        /**
075         * An empty immutable {@code short} array.
076         */
077        public static final short[] EMPTY_SHORT_ARRAY = new short[0];
078        /**
079         * An empty immutable {@code Short} array.
080         */
081        public static final Short[] EMPTY_SHORT_OBJECT_ARRAY = new Short[0];
082        /**
083         * An empty immutable {@code byte} array.
084         */
085        public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
086        /**
087         * An empty immutable {@code Byte} array.
088         */
089        public static final Byte[] EMPTY_BYTE_OBJECT_ARRAY = new Byte[0];
090        /**
091         * An empty immutable {@code double} array.
092         */
093        public static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
094        /**
095         * An empty immutable {@code Double} array.
096         */
097        public static final Double[] EMPTY_DOUBLE_OBJECT_ARRAY = new Double[0];
098        /**
099         * An empty immutable {@code float} array.
100         */
101        public static final float[] EMPTY_FLOAT_ARRAY = new float[0];
102        /**
103         * An empty immutable {@code Float} array.
104         */
105        public static final Float[] EMPTY_FLOAT_OBJECT_ARRAY = new Float[0];
106        /**
107         * An empty immutable {@code boolean} array.
108         */
109        public static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
110        /**
111         * An empty immutable {@code Boolean} array.
112         */
113        public static final Boolean[] EMPTY_BOOLEAN_OBJECT_ARRAY = new Boolean[0];
114        /**
115         * An empty immutable {@code char} array.
116         */
117        public static final char[] EMPTY_CHAR_ARRAY = new char[0];
118        /**
119         * An empty immutable {@code Character} array.
120         */
121        public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = new Character[0];
122    
123        /**
124         * The index value when an element is not found in a list or array: {@code -1}.
125         * This value is returned by methods in this class and can also be used in comparisons with values returned by
126         * various method from {@link java.util.List}.
127         */
128        public static final int INDEX_NOT_FOUND = -1;
129    
130        /**
131         * <p>ArrayUtils instances should NOT be constructed in standard programming.
132         * Instead, the class should be used as <code>ArrayUtils.clone(new int[] {2})</code>.</p>
133         *
134         * <p>This constructor is public to permit tools that require a JavaBean instance
135         * to operate.</p>
136         */
137        public ArrayUtils() {
138          super();
139        }
140    
141    
142        // NOTE: Cannot use {@code} to enclose text which includes {}, but <code></code> is OK
143    
144    
145        // Basic methods handling multi-dimensional arrays
146        //-----------------------------------------------------------------------
147        /**
148         * <p>Outputs an array as a String, treating {@code null} as an empty array.</p>
149         *
150         * <p>Multi-dimensional arrays are handled correctly, including
151         * multi-dimensional primitive arrays.</p>
152         *
153         * <p>The format is that of Java source code, for example <code>{a,b}</code>.</p>
154         *
155         * @param array  the array to get a toString for, may be {@code null}
156         * @return a String representation of the array, '{}' if null array input
157         */
158        public static String toString(Object array) {
159            return toString(array, "{}");
160        }
161    
162        /**
163         * <p>Outputs an array as a String handling {@code null}s.</p>
164         *
165         * <p>Multi-dimensional arrays are handled correctly, including
166         * multi-dimensional primitive arrays.</p>
167         *
168         * <p>The format is that of Java source code, for example <code>{a,b}</code>.</p>
169         *
170         * @param array  the array to get a toString for, may be {@code null}
171         * @param stringIfNull  the String to return if the array is {@code null}
172         * @return a String representation of the array
173         */
174        public static String toString(Object array, String stringIfNull) {
175            if (array == null) {
176                return stringIfNull;
177            }
178            return new ToStringBuilder(array, ToStringStyle.SIMPLE_STYLE).append(array).toString();
179        }
180    
181        /**
182         * <p>Get a hash code for an array handling multi-dimensional arrays correctly.</p>
183         *
184         * <p>Multi-dimensional primitive arrays are also handled correctly by this method.</p>
185         *
186         * @param array  the array to get a hash code for, {@code null} returns zero
187         * @return a hash code for the array
188         */
189        public static int hashCode(Object array) {
190            return new HashCodeBuilder().append(array).toHashCode();
191        }
192    
193        /**
194         * <p>Compares two arrays, using equals(), handling multi-dimensional arrays
195         * correctly.</p>
196         *
197         * <p>Multi-dimensional primitive arrays are also handled correctly by this method.</p>
198         *
199         * @param array1  the left hand array to compare, may be {@code null}
200         * @param array2  the right hand array to compare, may be {@code null}
201         * @return {@code true} if the arrays are equal
202         */
203        public static boolean isEquals(Object array1, Object array2) {
204            return new EqualsBuilder().append(array1, array2).isEquals();
205        }
206    
207        // To map
208        //-----------------------------------------------------------------------
209        /**
210         * <p>Converts the given array into a {@link java.util.Map}. Each element of the array
211         * must be either a {@link java.util.Map.Entry} or an Array, containing at least two
212         * elements, where the first element is used as key and the second as
213         * value.</p>
214         *
215         * <p>This method can be used to initialize:</p>
216         * <pre>
217         * // Create a Map mapping colors.
218         * Map colorMap = MapUtils.toMap(new String[][] {{
219         *     {"RED", "#FF0000"},
220         *     {"GREEN", "#00FF00"},
221         *     {"BLUE", "#0000FF"}});
222         * </pre>
223         *
224         * <p>This method returns {@code null} for a {@code null} input array.</p>
225         *
226         * @param array  an array whose elements are either a {@link java.util.Map.Entry} or
227         *  an Array containing at least two elements, may be {@code null}
228         * @return a {@code Map} that was created from the array
229         * @throws IllegalArgumentException  if one element of this Array is
230         *  itself an Array containing less then two elements
231         * @throws IllegalArgumentException  if the array contains elements other
232         *  than {@link java.util.Map.Entry} and an Array
233         */
234        public static Map<Object, Object> toMap(Object[] array) {
235            if (array == null) {
236                return null;
237            }
238            final Map<Object, Object> map = new HashMap<Object, Object>((int) (array.length * 1.5));
239            for (int i = 0; i < array.length; i++) {
240                Object object = array[i];
241                if (object instanceof Map.Entry<?, ?>) {
242                    Map.Entry<?,?> entry = (Map.Entry<?,?>) object;
243                    map.put(entry.getKey(), entry.getValue());
244                } else if (object instanceof Object[]) {
245                    Object[] entry = (Object[]) object;
246                    if (entry.length < 2) {
247                        throw new IllegalArgumentException("Array element " + i + ", '"
248                            + object
249                            + "', has a length less than 2");
250                    }
251                    map.put(entry[0], entry[1]);
252                } else {
253                    throw new IllegalArgumentException("Array element " + i + ", '"
254                            + object
255                            + "', is neither of type Map.Entry nor an Array");
256                }
257            }
258            return map;
259        }
260    
261        // Generic array
262        //-----------------------------------------------------------------------
263        /**
264         * <p>Create a type-safe generic array.</p>
265         *
266         * <p>The Java language does not allow an array to be created from a generic type:</p>
267         *
268         * <pre>
269        public static &lt;T&gt; T[] createAnArray(int size) {
270            return new T[size]; // compiler error here
271        }
272        public static &lt;T&gt; T[] createAnArray(int size) {
273            return (T[])new Object[size]; // ClassCastException at runtime
274        }
275         * </pre>
276         *
277         * <p>Therefore new arrays of generic types can be created with this method.
278         * For example, an array of Strings can be created:</p>
279         *
280         * <pre>
281        String[] array = ArrayUtils.toArray("1", "2");
282        String[] emptyArray = ArrayUtils.&lt;String&gt;toArray();
283         * </pre>
284         *
285         * <p>The method is typically used in scenarios, where the caller itself uses generic types
286         * that have to be combined into an array.</p>
287         *
288         * <p>Note, this method makes only sense to provide arguments of the same type so that the
289         * compiler can deduce the type of the array itself. While it is possible to select the
290         * type explicitly like in
291         * <code>Number[] array = ArrayUtils.&lt;Number&gt;toArray(Integer.valueOf(42), Double.valueOf(Math.PI))</code>,
292         * there is no real advantage when compared to
293         * <code>new Number[] {Integer.valueOf(42), Double.valueOf(Math.PI)}</code>.</p>
294         *
295         * @param  <T>   the array's element type
296         * @param  items  the varargs array items, null allowed
297         * @return the array, not null unless a null array is passed in
298         * @since  3.0
299         */
300        public static <T> T[] toArray(final T... items) {
301            return items;
302        }
303    
304        // Clone
305        //-----------------------------------------------------------------------
306        /**
307         * <p>Shallow clones an array returning a typecast result and handling
308         * {@code null}.</p>
309         *
310         * <p>The objects in the array are not cloned, thus there is no special
311         * handling for multi-dimensional arrays.</p>
312         *
313         * <p>This method returns {@code null} for a {@code null} input array.</p>
314         *
315         * @param <T> the component type of the array
316         * @param array  the array to shallow clone, may be {@code null}
317         * @return the cloned array, {@code null} if {@code null} input
318         */
319        public static <T> T[] clone(T[] array) {
320            if (array == null) {
321                return null;
322            }
323            return array.clone();
324        }
325    
326        /**
327         * <p>Clones an array returning a typecast result and handling
328         * {@code null}.</p>
329         *
330         * <p>This method returns {@code null} for a {@code null} input array.</p>
331         *
332         * @param array  the array to clone, may be {@code null}
333         * @return the cloned array, {@code null} if {@code null} input
334         */
335        public static long[] clone(long[] array) {
336            if (array == null) {
337                return null;
338            }
339            return array.clone();
340        }
341    
342        /**
343         * <p>Clones an array returning a typecast result and handling
344         * {@code null}.</p>
345         *
346         * <p>This method returns {@code null} for a {@code null} input array.</p>
347         *
348         * @param array  the array to clone, may be {@code null}
349         * @return the cloned array, {@code null} if {@code null} input
350         */
351        public static int[] clone(int[] array) {
352            if (array == null) {
353                return null;
354            }
355            return array.clone();
356        }
357    
358        /**
359         * <p>Clones an array returning a typecast result and handling
360         * {@code null}.</p>
361         *
362         * <p>This method returns {@code null} for a {@code null} input array.</p>
363         *
364         * @param array  the array to clone, may be {@code null}
365         * @return the cloned array, {@code null} if {@code null} input
366         */
367        public static short[] clone(short[] array) {
368            if (array == null) {
369                return null;
370            }
371            return array.clone();
372        }
373    
374        /**
375         * <p>Clones an array returning a typecast result and handling
376         * {@code null}.</p>
377         *
378         * <p>This method returns {@code null} for a {@code null} input array.</p>
379         *
380         * @param array  the array to clone, may be {@code null}
381         * @return the cloned array, {@code null} if {@code null} input
382         */
383        public static char[] clone(char[] array) {
384            if (array == null) {
385                return null;
386            }
387            return array.clone();
388        }
389    
390        /**
391         * <p>Clones an array returning a typecast result and handling
392         * {@code null}.</p>
393         *
394         * <p>This method returns {@code null} for a {@code null} input array.</p>
395         *
396         * @param array  the array to clone, may be {@code null}
397         * @return the cloned array, {@code null} if {@code null} input
398         */
399        public static byte[] clone(byte[] array) {
400            if (array == null) {
401                return null;
402            }
403            return array.clone();
404        }
405    
406        /**
407         * <p>Clones an array returning a typecast result and handling
408         * {@code null}.</p>
409         *
410         * <p>This method returns {@code null} for a {@code null} input array.</p>
411         *
412         * @param array  the array to clone, may be {@code null}
413         * @return the cloned array, {@code null} if {@code null} input
414         */
415        public static double[] clone(double[] array) {
416            if (array == null) {
417                return null;
418            }
419            return array.clone();
420        }
421    
422        /**
423         * <p>Clones an array returning a typecast result and handling
424         * {@code null}.</p>
425         *
426         * <p>This method returns {@code null} for a {@code null} input array.</p>
427         *
428         * @param array  the array to clone, may be {@code null}
429         * @return the cloned array, {@code null} if {@code null} input
430         */
431        public static float[] clone(float[] array) {
432            if (array == null) {
433                return null;
434            }
435            return array.clone();
436        }
437    
438        /**
439         * <p>Clones an array returning a typecast result and handling
440         * {@code null}.</p>
441         *
442         * <p>This method returns {@code null} for a {@code null} input array.</p>
443         *
444         * @param array  the array to clone, may be {@code null}
445         * @return the cloned array, {@code null} if {@code null} input
446         */
447        public static boolean[] clone(boolean[] array) {
448            if (array == null) {
449                return null;
450            }
451            return array.clone();
452        }
453    
454        // nullToEmpty
455        //-----------------------------------------------------------------------
456        /**
457         * <p>Defensive programming technique to change a {@code null}
458         * reference to an empty one.</p>
459         *
460         * <p>This method returns an empty array for a {@code null} input array.</p>
461         *
462         * <p>As a memory optimizing technique an empty array passed in will be overridden with
463         * the empty {@code public static} references in this class.</p>
464         *
465         * @param array  the array to check for {@code null} or empty
466         * @return the same array, {@code public static} empty array if {@code null} or empty input
467         * @since 2.5
468         */
469        public static Object[] nullToEmpty(Object[] array) {
470            if (array == null || array.length == 0) {
471                return EMPTY_OBJECT_ARRAY;
472            }
473            return array;
474        }
475    
476        /**
477         * <p>Defensive programming technique to change a {@code null}
478         * reference to an empty one.</p>
479         *
480         * <p>This method returns an empty array for a {@code null} input array.</p>
481         *
482         * <p>As a memory optimizing technique an empty array passed in will be overridden with
483         * the empty {@code public static} references in this class.</p>
484         *
485         * @param array  the array to check for {@code null} or empty
486         * @return the same array, {@code public static} empty array if {@code null} or empty input
487         * @since 2.5
488         */
489        public static String[] nullToEmpty(String[] array) {
490            if (array == null || array.length == 0) {
491                return EMPTY_STRING_ARRAY;
492            }
493            return array;
494        }
495    
496        /**
497         * <p>Defensive programming technique to change a {@code null}
498         * reference to an empty one.</p>
499         *
500         * <p>This method returns an empty array for a {@code null} input array.</p>
501         *
502         * <p>As a memory optimizing technique an empty array passed in will be overridden with
503         * the empty {@code public static} references in this class.</p>
504         *
505         * @param array  the array to check for {@code null} or empty
506         * @return the same array, {@code public static} empty array if {@code null} or empty input
507         * @since 2.5
508         */
509        public static long[] nullToEmpty(long[] array) {
510            if (array == null || array.length == 0) {
511                return EMPTY_LONG_ARRAY;
512            }
513            return array;
514        }
515    
516        /**
517         * <p>Defensive programming technique to change a {@code null}
518         * reference to an empty one.</p>
519         *
520         * <p>This method returns an empty array for a {@code null} input array.</p>
521         *
522         * <p>As a memory optimizing technique an empty array passed in will be overridden with
523         * the empty {@code public static} references in this class.</p>
524         *
525         * @param array  the array to check for {@code null} or empty
526         * @return the same array, {@code public static} empty array if {@code null} or empty input
527         * @since 2.5
528         */
529        public static int[] nullToEmpty(int[] array) {
530            if (array == null || array.length == 0) {
531                return EMPTY_INT_ARRAY;
532            }
533            return array;
534        }
535    
536        /**
537         * <p>Defensive programming technique to change a {@code null}
538         * reference to an empty one.</p>
539         *
540         * <p>This method returns an empty array for a {@code null} input array.</p>
541         *
542         * <p>As a memory optimizing technique an empty array passed in will be overridden with
543         * the empty {@code public static} references in this class.</p>
544         *
545         * @param array  the array to check for {@code null} or empty
546         * @return the same array, {@code public static} empty array if {@code null} or empty input
547         * @since 2.5
548         */
549        public static short[] nullToEmpty(short[] array) {
550            if (array == null || array.length == 0) {
551                return EMPTY_SHORT_ARRAY;
552            }
553            return array;
554        }
555    
556        /**
557         * <p>Defensive programming technique to change a {@code null}
558         * reference to an empty one.</p>
559         *
560         * <p>This method returns an empty array for a {@code null} input array.</p>
561         *
562         * <p>As a memory optimizing technique an empty array passed in will be overridden with
563         * the empty {@code public static} references in this class.</p>
564         *
565         * @param array  the array to check for {@code null} or empty
566         * @return the same array, {@code public static} empty array if {@code null} or empty input
567         * @since 2.5
568         */
569        public static char[] nullToEmpty(char[] array) {
570            if (array == null || array.length == 0) {
571                return EMPTY_CHAR_ARRAY;
572            }
573            return array;
574        }
575    
576        /**
577         * <p>Defensive programming technique to change a {@code null}
578         * reference to an empty one.</p>
579         *
580         * <p>This method returns an empty array for a {@code null} input array.</p>
581         *
582         * <p>As a memory optimizing technique an empty array passed in will be overridden with
583         * the empty {@code public static} references in this class.</p>
584         *
585         * @param array  the array to check for {@code null} or empty
586         * @return the same array, {@code public static} empty array if {@code null} or empty input
587         * @since 2.5
588         */
589        public static byte[] nullToEmpty(byte[] array) {
590            if (array == null || array.length == 0) {
591                return EMPTY_BYTE_ARRAY;
592            }
593            return array;
594        }
595    
596        /**
597         * <p>Defensive programming technique to change a {@code null}
598         * reference to an empty one.</p>
599         *
600         * <p>This method returns an empty array for a {@code null} input array.</p>
601         *
602         * <p>As a memory optimizing technique an empty array passed in will be overridden with
603         * the empty {@code public static} references in this class.</p>
604         *
605         * @param array  the array to check for {@code null} or empty
606         * @return the same array, {@code public static} empty array if {@code null} or empty input
607         * @since 2.5
608         */
609        public static double[] nullToEmpty(double[] array) {
610            if (array == null || array.length == 0) {
611                return EMPTY_DOUBLE_ARRAY;
612            }
613            return array;
614        }
615    
616        /**
617         * <p>Defensive programming technique to change a {@code null}
618         * reference to an empty one.</p>
619         *
620         * <p>This method returns an empty array for a {@code null} input array.</p>
621         *
622         * <p>As a memory optimizing technique an empty array passed in will be overridden with
623         * the empty {@code public static} references in this class.</p>
624         *
625         * @param array  the array to check for {@code null} or empty
626         * @return the same array, {@code public static} empty array if {@code null} or empty input
627         * @since 2.5
628         */
629        public static float[] nullToEmpty(float[] array) {
630            if (array == null || array.length == 0) {
631                return EMPTY_FLOAT_ARRAY;
632            }
633            return array;
634        }
635    
636        /**
637         * <p>Defensive programming technique to change a {@code null}
638         * reference to an empty one.</p>
639         *
640         * <p>This method returns an empty array for a {@code null} input array.</p>
641         *
642         * <p>As a memory optimizing technique an empty array passed in will be overridden with
643         * the empty {@code public static} references in this class.</p>
644         *
645         * @param array  the array to check for {@code null} or empty
646         * @return the same array, {@code public static} empty array if {@code null} or empty input
647         * @since 2.5
648         */
649        public static boolean[] nullToEmpty(boolean[] array) {
650            if (array == null || array.length == 0) {
651                return EMPTY_BOOLEAN_ARRAY;
652            }
653            return array;
654        }
655    
656        /**
657         * <p>Defensive programming technique to change a {@code null}
658         * reference to an empty one.</p>
659         *
660         * <p>This method returns an empty array for a {@code null} input array.</p>
661         *
662         * <p>As a memory optimizing technique an empty array passed in will be overridden with
663         * the empty {@code public static} references in this class.</p>
664         *
665         * @param array  the array to check for {@code null} or empty
666         * @return the same array, {@code public static} empty array if {@code null} or empty input
667         * @since 2.5
668         */
669        public static Long[] nullToEmpty(Long[] array) {
670            if (array == null || array.length == 0) {
671                return EMPTY_LONG_OBJECT_ARRAY;
672            }
673            return array;
674        }
675    
676        /**
677         * <p>Defensive programming technique to change a {@code null}
678         * reference to an empty one.</p>
679         *
680         * <p>This method returns an empty array for a {@code null} input array.</p>
681         *
682         * <p>As a memory optimizing technique an empty array passed in will be overridden with
683         * the empty {@code public static} references in this class.</p>
684         *
685         * @param array  the array to check for {@code null} or empty
686         * @return the same array, {@code public static} empty array if {@code null} or empty input
687         * @since 2.5
688         */
689        public static Integer[] nullToEmpty(Integer[] array) {
690            if (array == null || array.length == 0) {
691                return EMPTY_INTEGER_OBJECT_ARRAY;
692            }
693            return array;
694        }
695    
696        /**
697         * <p>Defensive programming technique to change a {@code null}
698         * reference to an empty one.</p>
699         *
700         * <p>This method returns an empty array for a {@code null} input array.</p>
701         *
702         * <p>As a memory optimizing technique an empty array passed in will be overridden with
703         * the empty {@code public static} references in this class.</p>
704         *
705         * @param array  the array to check for {@code null} or empty
706         * @return the same array, {@code public static} empty array if {@code null} or empty input
707         * @since 2.5
708         */
709        public static Short[] nullToEmpty(Short[] array) {
710            if (array == null || array.length == 0) {
711                return EMPTY_SHORT_OBJECT_ARRAY;
712            }
713            return array;
714        }
715    
716        /**
717         * <p>Defensive programming technique to change a {@code null}
718         * reference to an empty one.</p>
719         *
720         * <p>This method returns an empty array for a {@code null} input array.</p>
721         *
722         * <p>As a memory optimizing technique an empty array passed in will be overridden with
723         * the empty {@code public static} references in this class.</p>
724         *
725         * @param array  the array to check for {@code null} or empty
726         * @return the same array, {@code public static} empty array if {@code null} or empty input
727         * @since 2.5
728         */
729        public static Character[] nullToEmpty(Character[] array) {
730            if (array == null || array.length == 0) {
731                return EMPTY_CHARACTER_OBJECT_ARRAY;
732            }
733            return array;
734        }
735    
736        /**
737         * <p>Defensive programming technique to change a {@code null}
738         * reference to an empty one.</p>
739         *
740         * <p>This method returns an empty array for a {@code null} input array.</p>
741         *
742         * <p>As a memory optimizing technique an empty array passed in will be overridden with
743         * the empty {@code public static} references in this class.</p>
744         *
745         * @param array  the array to check for {@code null} or empty
746         * @return the same array, {@code public static} empty array if {@code null} or empty input
747         * @since 2.5
748         */
749        public static Byte[] nullToEmpty(Byte[] array) {
750            if (array == null || array.length == 0) {
751                return EMPTY_BYTE_OBJECT_ARRAY;
752            }
753            return array;
754        }
755    
756        /**
757         * <p>Defensive programming technique to change a {@code null}
758         * reference to an empty one.</p>
759         *
760         * <p>This method returns an empty array for a {@code null} input array.</p>
761         *
762         * <p>As a memory optimizing technique an empty array passed in will be overridden with
763         * the empty {@code public static} references in this class.</p>
764         *
765         * @param array  the array to check for {@code null} or empty
766         * @return the same array, {@code public static} empty array if {@code null} or empty input
767         * @since 2.5
768         */
769        public static Double[] nullToEmpty(Double[] array) {
770            if (array == null || array.length == 0) {
771                return EMPTY_DOUBLE_OBJECT_ARRAY;
772            }
773            return array;
774        }
775    
776        /**
777         * <p>Defensive programming technique to change a {@code null}
778         * reference to an empty one.</p>
779         *
780         * <p>This method returns an empty array for a {@code null} input array.</p>
781         *
782         * <p>As a memory optimizing technique an empty array passed in will be overridden with
783         * the empty {@code public static} references in this class.</p>
784         *
785         * @param array  the array to check for {@code null} or empty
786         * @return the same array, {@code public static} empty array if {@code null} or empty input
787         * @since 2.5
788         */
789        public static Float[] nullToEmpty(Float[] array) {
790            if (array == null || array.length == 0) {
791                return EMPTY_FLOAT_OBJECT_ARRAY;
792            }
793            return array;
794        }
795    
796        /**
797         * <p>Defensive programming technique to change a {@code null}
798         * reference to an empty one.</p>
799         *
800         * <p>This method returns an empty array for a {@code null} input array.</p>
801         *
802         * <p>As a memory optimizing technique an empty array passed in will be overridden with
803         * the empty {@code public static} references in this class.</p>
804         *
805         * @param array  the array to check for {@code null} or empty
806         * @return the same array, {@code public static} empty array if {@code null} or empty input
807         * @since 2.5
808         */
809        public static Boolean[] nullToEmpty(Boolean[] array) {
810            if (array == null || array.length == 0) {
811                return EMPTY_BOOLEAN_OBJECT_ARRAY;
812            }
813            return array;
814        }
815    
816        // Subarrays
817        //-----------------------------------------------------------------------
818        /**
819         * <p>Produces a new array containing the elements between
820         * the start and end indices.</p>
821         *
822         * <p>The start index is inclusive, the end index exclusive.
823         * Null array input produces null output.</p>
824         *
825         * <p>The component type of the subarray is always the same as
826         * that of the input array. Thus, if the input is an array of type
827         * {@code Date}, the following usage is envisaged:</p>
828         *
829         * <pre>
830         * Date[] someDates = (Date[])ArrayUtils.subarray(allDates, 2, 5);
831         * </pre>
832         *
833         * @param <T> the component type of the array
834         * @param array  the array
835         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
836         *      is promoted to 0, overvalue (&gt;array.length) results
837         *      in an empty array.
838         * @param endIndexExclusive  elements up to endIndex-1 are present in the
839         *      returned subarray. Undervalue (&lt; startIndex) produces
840         *      empty array, overvalue (&gt;array.length) is demoted to
841         *      array length.
842         * @return a new array containing the elements between
843         *      the start and end indices.
844         * @since 2.1
845         */
846        public static <T> T[] subarray(T[] array, int startIndexInclusive, int endIndexExclusive) {
847            if (array == null) {
848                return null;
849            }
850            if (startIndexInclusive < 0) {
851                startIndexInclusive = 0;
852            }
853            if (endIndexExclusive > array.length) {
854                endIndexExclusive = array.length;
855            }
856            int newSize = endIndexExclusive - startIndexInclusive;
857            Class<?> type = array.getClass().getComponentType();
858            if (newSize <= 0) {
859                @SuppressWarnings("unchecked") // OK, because array is of type T
860                final T[] emptyArray = (T[]) Array.newInstance(type, 0);
861                return emptyArray;
862            }
863            @SuppressWarnings("unchecked") // OK, because array is of type T
864            T[] subarray = (T[]) Array.newInstance(type, newSize);
865            System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
866            return subarray;
867        }
868    
869        /**
870         * <p>Produces a new {@code long} array containing the elements
871         * between the start and end indices.</p>
872         *
873         * <p>The start index is inclusive, the end index exclusive.
874         * Null array input produces null output.</p>
875         *
876         * @param array  the array
877         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
878         *      is promoted to 0, overvalue (&gt;array.length) results
879         *      in an empty array.
880         * @param endIndexExclusive  elements up to endIndex-1 are present in the
881         *      returned subarray. Undervalue (&lt; startIndex) produces
882         *      empty array, overvalue (&gt;array.length) is demoted to
883         *      array length.
884         * @return a new array containing the elements between
885         *      the start and end indices.
886         * @since 2.1
887         */
888        public static long[] subarray(long[] array, int startIndexInclusive, int endIndexExclusive) {
889            if (array == null) {
890                return null;
891            }
892            if (startIndexInclusive < 0) {
893                startIndexInclusive = 0;
894            }
895            if (endIndexExclusive > array.length) {
896                endIndexExclusive = array.length;
897            }
898            int newSize = endIndexExclusive - startIndexInclusive;
899            if (newSize <= 0) {
900                return EMPTY_LONG_ARRAY;
901            }
902    
903            long[] subarray = new long[newSize];
904            System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
905            return subarray;
906        }
907    
908        /**
909         * <p>Produces a new {@code int} array containing the elements
910         * between the start and end indices.</p>
911         *
912         * <p>The start index is inclusive, the end index exclusive.
913         * Null array input produces null output.</p>
914         *
915         * @param array  the array
916         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
917         *      is promoted to 0, overvalue (&gt;array.length) results
918         *      in an empty array.
919         * @param endIndexExclusive  elements up to endIndex-1 are present in the
920         *      returned subarray. Undervalue (&lt; startIndex) produces
921         *      empty array, overvalue (&gt;array.length) is demoted to
922         *      array length.
923         * @return a new array containing the elements between
924         *      the start and end indices.
925         * @since 2.1
926         */
927        public static int[] subarray(int[] array, int startIndexInclusive, int endIndexExclusive) {
928            if (array == null) {
929                return null;
930            }
931            if (startIndexInclusive < 0) {
932                startIndexInclusive = 0;
933            }
934            if (endIndexExclusive > array.length) {
935                endIndexExclusive = array.length;
936            }
937            int newSize = endIndexExclusive - startIndexInclusive;
938            if (newSize <= 0) {
939                return EMPTY_INT_ARRAY;
940            }
941    
942            int[] subarray = new int[newSize];
943            System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
944            return subarray;
945        }
946    
947        /**
948         * <p>Produces a new {@code short} array containing the elements
949         * between the start and end indices.</p>
950         *
951         * <p>The start index is inclusive, the end index exclusive.
952         * Null array input produces null output.</p>
953         *
954         * @param array  the array
955         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
956         *      is promoted to 0, overvalue (&gt;array.length) results
957         *      in an empty array.
958         * @param endIndexExclusive  elements up to endIndex-1 are present in the
959         *      returned subarray. Undervalue (&lt; startIndex) produces
960         *      empty array, overvalue (&gt;array.length) is demoted to
961         *      array length.
962         * @return a new array containing the elements between
963         *      the start and end indices.
964         * @since 2.1
965         */
966        public static short[] subarray(short[] array, int startIndexInclusive, int endIndexExclusive) {
967            if (array == null) {
968                return null;
969            }
970            if (startIndexInclusive < 0) {
971                startIndexInclusive = 0;
972            }
973            if (endIndexExclusive > array.length) {
974                endIndexExclusive = array.length;
975            }
976            int newSize = endIndexExclusive - startIndexInclusive;
977            if (newSize <= 0) {
978                return EMPTY_SHORT_ARRAY;
979            }
980    
981            short[] subarray = new short[newSize];
982            System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
983            return subarray;
984        }
985    
986        /**
987         * <p>Produces a new {@code char} array containing the elements
988         * between the start and end indices.</p>
989         *
990         * <p>The start index is inclusive, the end index exclusive.
991         * Null array input produces null output.</p>
992         *
993         * @param array  the array
994         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
995         *      is promoted to 0, overvalue (&gt;array.length) results
996         *      in an empty array.
997         * @param endIndexExclusive  elements up to endIndex-1 are present in the
998         *      returned subarray. Undervalue (&lt; startIndex) produces
999         *      empty array, overvalue (&gt;array.length) is demoted to
1000         *      array length.
1001         * @return a new array containing the elements between
1002         *      the start and end indices.
1003         * @since 2.1
1004         */
1005        public static char[] subarray(char[] array, int startIndexInclusive, int endIndexExclusive) {
1006            if (array == null) {
1007                return null;
1008            }
1009            if (startIndexInclusive < 0) {
1010                startIndexInclusive = 0;
1011            }
1012            if (endIndexExclusive > array.length) {
1013                endIndexExclusive = array.length;
1014            }
1015            int newSize = endIndexExclusive - startIndexInclusive;
1016            if (newSize <= 0) {
1017                return EMPTY_CHAR_ARRAY;
1018            }
1019    
1020            char[] subarray = new char[newSize];
1021            System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1022            return subarray;
1023        }
1024    
1025        /**
1026         * <p>Produces a new {@code byte} array containing the elements
1027         * between the start and end indices.</p>
1028         *
1029         * <p>The start index is inclusive, the end index exclusive.
1030         * Null array input produces null output.</p>
1031         *
1032         * @param array  the array
1033         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
1034         *      is promoted to 0, overvalue (&gt;array.length) results
1035         *      in an empty array.
1036         * @param endIndexExclusive  elements up to endIndex-1 are present in the
1037         *      returned subarray. Undervalue (&lt; startIndex) produces
1038         *      empty array, overvalue (&gt;array.length) is demoted to
1039         *      array length.
1040         * @return a new array containing the elements between
1041         *      the start and end indices.
1042         * @since 2.1
1043         */
1044        public static byte[] subarray(byte[] array, int startIndexInclusive, int endIndexExclusive) {
1045            if (array == null) {
1046                return null;
1047            }
1048            if (startIndexInclusive < 0) {
1049                startIndexInclusive = 0;
1050            }
1051            if (endIndexExclusive > array.length) {
1052                endIndexExclusive = array.length;
1053            }
1054            int newSize = endIndexExclusive - startIndexInclusive;
1055            if (newSize <= 0) {
1056                return EMPTY_BYTE_ARRAY;
1057            }
1058    
1059            byte[] subarray = new byte[newSize];
1060            System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1061            return subarray;
1062        }
1063    
1064        /**
1065         * <p>Produces a new {@code double} array containing the elements
1066         * between the start and end indices.</p>
1067         *
1068         * <p>The start index is inclusive, the end index exclusive.
1069         * Null array input produces null output.</p>
1070         *
1071         * @param array  the array
1072         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
1073         *      is promoted to 0, overvalue (&gt;array.length) results
1074         *      in an empty array.
1075         * @param endIndexExclusive  elements up to endIndex-1 are present in the
1076         *      returned subarray. Undervalue (&lt; startIndex) produces
1077         *      empty array, overvalue (&gt;array.length) is demoted to
1078         *      array length.
1079         * @return a new array containing the elements between
1080         *      the start and end indices.
1081         * @since 2.1
1082         */
1083        public static double[] subarray(double[] array, int startIndexInclusive, int endIndexExclusive) {
1084            if (array == null) {
1085                return null;
1086            }
1087            if (startIndexInclusive < 0) {
1088                startIndexInclusive = 0;
1089            }
1090            if (endIndexExclusive > array.length) {
1091                endIndexExclusive = array.length;
1092            }
1093            int newSize = endIndexExclusive - startIndexInclusive;
1094            if (newSize <= 0) {
1095                return EMPTY_DOUBLE_ARRAY;
1096            }
1097    
1098            double[] subarray = new double[newSize];
1099            System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1100            return subarray;
1101        }
1102    
1103        /**
1104         * <p>Produces a new {@code float} array containing the elements
1105         * between the start and end indices.</p>
1106         *
1107         * <p>The start index is inclusive, the end index exclusive.
1108         * Null array input produces null output.</p>
1109         *
1110         * @param array  the array
1111         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
1112         *      is promoted to 0, overvalue (&gt;array.length) results
1113         *      in an empty array.
1114         * @param endIndexExclusive  elements up to endIndex-1 are present in the
1115         *      returned subarray. Undervalue (&lt; startIndex) produces
1116         *      empty array, overvalue (&gt;array.length) is demoted to
1117         *      array length.
1118         * @return a new array containing the elements between
1119         *      the start and end indices.
1120         * @since 2.1
1121         */
1122        public static float[] subarray(float[] array, int startIndexInclusive, int endIndexExclusive) {
1123            if (array == null) {
1124                return null;
1125            }
1126            if (startIndexInclusive < 0) {
1127                startIndexInclusive = 0;
1128            }
1129            if (endIndexExclusive > array.length) {
1130                endIndexExclusive = array.length;
1131            }
1132            int newSize = endIndexExclusive - startIndexInclusive;
1133            if (newSize <= 0) {
1134                return EMPTY_FLOAT_ARRAY;
1135            }
1136    
1137            float[] subarray = new float[newSize];
1138            System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1139            return subarray;
1140        }
1141    
1142        /**
1143         * <p>Produces a new {@code boolean} array containing the elements
1144         * between the start and end indices.</p>
1145         *
1146         * <p>The start index is inclusive, the end index exclusive.
1147         * Null array input produces null output.</p>
1148         *
1149         * @param array  the array
1150         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
1151         *      is promoted to 0, overvalue (&gt;array.length) results
1152         *      in an empty array.
1153         * @param endIndexExclusive  elements up to endIndex-1 are present in the
1154         *      returned subarray. Undervalue (&lt; startIndex) produces
1155         *      empty array, overvalue (&gt;array.length) is demoted to
1156         *      array length.
1157         * @return a new array containing the elements between
1158         *      the start and end indices.
1159         * @since 2.1
1160         */
1161        public static boolean[] subarray(boolean[] array, int startIndexInclusive, int endIndexExclusive) {
1162            if (array == null) {
1163                return null;
1164            }
1165            if (startIndexInclusive < 0) {
1166                startIndexInclusive = 0;
1167            }
1168            if (endIndexExclusive > array.length) {
1169                endIndexExclusive = array.length;
1170            }
1171            int newSize = endIndexExclusive - startIndexInclusive;
1172            if (newSize <= 0) {
1173                return EMPTY_BOOLEAN_ARRAY;
1174            }
1175    
1176            boolean[] subarray = new boolean[newSize];
1177            System.arraycopy(array, startIndexInclusive, subarray, 0, newSize);
1178            return subarray;
1179        }
1180    
1181        // Is same length
1182        //-----------------------------------------------------------------------
1183        /**
1184         * <p>Checks whether two arrays are the same length, treating
1185         * {@code null} arrays as length {@code 0}.
1186         *
1187         * <p>Any multi-dimensional aspects of the arrays are ignored.</p>
1188         *
1189         * @param array1 the first array, may be {@code null}
1190         * @param array2 the second array, may be {@code null}
1191         * @return {@code true} if length of arrays matches, treating
1192         *  {@code null} as an empty array
1193         */
1194        public static boolean isSameLength(Object[] array1, Object[] array2) {
1195            if ((array1 == null && array2 != null && array2.length > 0) ||
1196                (array2 == null && array1 != null && array1.length > 0) ||
1197                (array1 != null && array2 != null && array1.length != array2.length)) {
1198                    return false;
1199            }
1200            return true;
1201        }
1202    
1203        /**
1204         * <p>Checks whether two arrays are the same length, treating
1205         * {@code null} arrays as length {@code 0}.</p>
1206         *
1207         * @param array1 the first array, may be {@code null}
1208         * @param array2 the second array, may be {@code null}
1209         * @return {@code true} if length of arrays matches, treating
1210         *  {@code null} as an empty array
1211         */
1212        public static boolean isSameLength(long[] array1, long[] array2) {
1213            if ((array1 == null && array2 != null && array2.length > 0) ||
1214                (array2 == null && array1 != null && array1.length > 0) ||
1215                (array1 != null && array2 != null && array1.length != array2.length)) {
1216                    return false;
1217            }
1218            return true;
1219        }
1220    
1221        /**
1222         * <p>Checks whether two arrays are the same length, treating
1223         * {@code null} arrays as length {@code 0}.</p>
1224         *
1225         * @param array1 the first array, may be {@code null}
1226         * @param array2 the second array, may be {@code null}
1227         * @return {@code true} if length of arrays matches, treating
1228         *  {@code null} as an empty array
1229         */
1230        public static boolean isSameLength(int[] array1, int[] array2) {
1231            if ((array1 == null && array2 != null && array2.length > 0) ||
1232                (array2 == null && array1 != null && array1.length > 0) ||
1233                (array1 != null && array2 != null && array1.length != array2.length)) {
1234                    return false;
1235            }
1236            return true;
1237        }
1238    
1239        /**
1240         * <p>Checks whether two arrays are the same length, treating
1241         * {@code null} arrays as length {@code 0}.</p>
1242         *
1243         * @param array1 the first array, may be {@code null}
1244         * @param array2 the second array, may be {@code null}
1245         * @return {@code true} if length of arrays matches, treating
1246         *  {@code null} as an empty array
1247         */
1248        public static boolean isSameLength(short[] array1, short[] array2) {
1249            if ((array1 == null && array2 != null && array2.length > 0) ||
1250                (array2 == null && array1 != null && array1.length > 0) ||
1251                (array1 != null && array2 != null && array1.length != array2.length)) {
1252                    return false;
1253            }
1254            return true;
1255        }
1256    
1257        /**
1258         * <p>Checks whether two arrays are the same length, treating
1259         * {@code null} arrays as length {@code 0}.</p>
1260         *
1261         * @param array1 the first array, may be {@code null}
1262         * @param array2 the second array, may be {@code null}
1263         * @return {@code true} if length of arrays matches, treating
1264         *  {@code null} as an empty array
1265         */
1266        public static boolean isSameLength(char[] array1, char[] array2) {
1267            if ((array1 == null && array2 != null && array2.length > 0) ||
1268                (array2 == null && array1 != null && array1.length > 0) ||
1269                (array1 != null && array2 != null && array1.length != array2.length)) {
1270                    return false;
1271            }
1272            return true;
1273        }
1274    
1275        /**
1276         * <p>Checks whether two arrays are the same length, treating
1277         * {@code null} arrays as length {@code 0}.</p>
1278         *
1279         * @param array1 the first array, may be {@code null}
1280         * @param array2 the second array, may be {@code null}
1281         * @return {@code true} if length of arrays matches, treating
1282         *  {@code null} as an empty array
1283         */
1284        public static boolean isSameLength(byte[] array1, byte[] array2) {
1285            if ((array1 == null && array2 != null && array2.length > 0) ||
1286                (array2 == null && array1 != null && array1.length > 0) ||
1287                (array1 != null && array2 != null && array1.length != array2.length)) {
1288                    return false;
1289            }
1290            return true;
1291        }
1292    
1293        /**
1294         * <p>Checks whether two arrays are the same length, treating
1295         * {@code null} arrays as length {@code 0}.</p>
1296         *
1297         * @param array1 the first array, may be {@code null}
1298         * @param array2 the second array, may be {@code null}
1299         * @return {@code true} if length of arrays matches, treating
1300         *  {@code null} as an empty array
1301         */
1302        public static boolean isSameLength(double[] array1, double[] array2) {
1303            if ((array1 == null && array2 != null && array2.length > 0) ||
1304                (array2 == null && array1 != null && array1.length > 0) ||
1305                (array1 != null && array2 != null && array1.length != array2.length)) {
1306                    return false;
1307            }
1308            return true;
1309        }
1310    
1311        /**
1312         * <p>Checks whether two arrays are the same length, treating
1313         * {@code null} arrays as length {@code 0}.</p>
1314         *
1315         * @param array1 the first array, may be {@code null}
1316         * @param array2 the second array, may be {@code null}
1317         * @return {@code true} if length of arrays matches, treating
1318         *  {@code null} as an empty array
1319         */
1320        public static boolean isSameLength(float[] array1, float[] array2) {
1321            if ((array1 == null && array2 != null && array2.length > 0) ||
1322                (array2 == null && array1 != null && array1.length > 0) ||
1323                (array1 != null && array2 != null && array1.length != array2.length)) {
1324                    return false;
1325            }
1326            return true;
1327        }
1328    
1329        /**
1330         * <p>Checks whether two arrays are the same length, treating
1331         * {@code null} arrays as length {@code 0}.</p>
1332         *
1333         * @param array1 the first array, may be {@code null}
1334         * @param array2 the second array, may be {@code null}
1335         * @return {@code true} if length of arrays matches, treating
1336         *  {@code null} as an empty array
1337         */
1338        public static boolean isSameLength(boolean[] array1, boolean[] array2) {
1339            if ((array1 == null && array2 != null && array2.length > 0) ||
1340                (array2 == null && array1 != null && array1.length > 0) ||
1341                (array1 != null && array2 != null && array1.length != array2.length)) {
1342                    return false;
1343            }
1344            return true;
1345        }
1346    
1347        //-----------------------------------------------------------------------
1348        /**
1349         * <p>Returns the length of the specified array.
1350         * This method can deal with {@code Object} arrays and with primitive arrays.</p>
1351         *
1352         * <p>If the input array is {@code null}, {@code 0} is returned.</p>
1353         *
1354         * <pre>
1355         * ArrayUtils.getLength(null)            = 0
1356         * ArrayUtils.getLength([])              = 0
1357         * ArrayUtils.getLength([null])          = 1
1358         * ArrayUtils.getLength([true, false])   = 2
1359         * ArrayUtils.getLength([1, 2, 3])       = 3
1360         * ArrayUtils.getLength(["a", "b", "c"]) = 3
1361         * </pre>
1362         *
1363         * @param array  the array to retrieve the length from, may be null
1364         * @return The length of the array, or {@code 0} if the array is {@code null}
1365         * @throws IllegalArgumentException if the object arguement is not an array.
1366         * @since 2.1
1367         */
1368        public static int getLength(Object array) {
1369            if (array == null) {
1370                return 0;
1371            }
1372            return Array.getLength(array);
1373        }
1374    
1375        /**
1376         * <p>Checks whether two arrays are the same type taking into account
1377         * multi-dimensional arrays.</p>
1378         *
1379         * @param array1 the first array, must not be {@code null}
1380         * @param array2 the second array, must not be {@code null}
1381         * @return {@code true} if type of arrays matches
1382         * @throws IllegalArgumentException if either array is {@code null}
1383         */
1384        public static boolean isSameType(Object array1, Object array2) {
1385            if (array1 == null || array2 == null) {
1386                throw new IllegalArgumentException("The Array must not be null");
1387            }
1388            return array1.getClass().getName().equals(array2.getClass().getName());
1389        }
1390    
1391        // Reverse
1392        //-----------------------------------------------------------------------
1393        /**
1394         * <p>Reverses the order of the given array.</p>
1395         *
1396         * <p>There is no special handling for multi-dimensional arrays.</p>
1397         *
1398         * <p>This method does nothing for a {@code null} input array.</p>
1399         *
1400         * @param array  the array to reverse, may be {@code null}
1401         */
1402        public static void reverse(Object[] array) {
1403            if (array == null) {
1404                return;
1405            }
1406            int i = 0;
1407            int j = array.length - 1;
1408            Object tmp;
1409            while (j > i) {
1410                tmp = array[j];
1411                array[j] = array[i];
1412                array[i] = tmp;
1413                j--;
1414                i++;
1415            }
1416        }
1417    
1418        /**
1419         * <p>Reverses the order of the given array.</p>
1420         *
1421         * <p>This method does nothing for a {@code null} input array.</p>
1422         *
1423         * @param array  the array to reverse, may be {@code null}
1424         */
1425        public static void reverse(long[] array) {
1426            if (array == null) {
1427                return;
1428            }
1429            int i = 0;
1430            int j = array.length - 1;
1431            long tmp;
1432            while (j > i) {
1433                tmp = array[j];
1434                array[j] = array[i];
1435                array[i] = tmp;
1436                j--;
1437                i++;
1438            }
1439        }
1440    
1441        /**
1442         * <p>Reverses the order of the given array.</p>
1443         *
1444         * <p>This method does nothing for a {@code null} input array.</p>
1445         *
1446         * @param array  the array to reverse, may be {@code null}
1447         */
1448        public static void reverse(int[] array) {
1449            if (array == null) {
1450                return;
1451            }
1452            int i = 0;
1453            int j = array.length - 1;
1454            int tmp;
1455            while (j > i) {
1456                tmp = array[j];
1457                array[j] = array[i];
1458                array[i] = tmp;
1459                j--;
1460                i++;
1461            }
1462        }
1463    
1464        /**
1465         * <p>Reverses the order of the given array.</p>
1466         *
1467         * <p>This method does nothing for a {@code null} input array.</p>
1468         *
1469         * @param array  the array to reverse, may be {@code null}
1470         */
1471        public static void reverse(short[] array) {
1472            if (array == null) {
1473                return;
1474            }
1475            int i = 0;
1476            int j = array.length - 1;
1477            short tmp;
1478            while (j > i) {
1479                tmp = array[j];
1480                array[j] = array[i];
1481                array[i] = tmp;
1482                j--;
1483                i++;
1484            }
1485        }
1486    
1487        /**
1488         * <p>Reverses the order of the given array.</p>
1489         *
1490         * <p>This method does nothing for a {@code null} input array.</p>
1491         *
1492         * @param array  the array to reverse, may be {@code null}
1493         */
1494        public static void reverse(char[] array) {
1495            if (array == null) {
1496                return;
1497            }
1498            int i = 0;
1499            int j = array.length - 1;
1500            char tmp;
1501            while (j > i) {
1502                tmp = array[j];
1503                array[j] = array[i];
1504                array[i] = tmp;
1505                j--;
1506                i++;
1507            }
1508        }
1509    
1510        /**
1511         * <p>Reverses the order of the given array.</p>
1512         *
1513         * <p>This method does nothing for a {@code null} input array.</p>
1514         *
1515         * @param array  the array to reverse, may be {@code null}
1516         */
1517        public static void reverse(byte[] array) {
1518            if (array == null) {
1519                return;
1520            }
1521            int i = 0;
1522            int j = array.length - 1;
1523            byte tmp;
1524            while (j > i) {
1525                tmp = array[j];
1526                array[j] = array[i];
1527                array[i] = tmp;
1528                j--;
1529                i++;
1530            }
1531        }
1532    
1533        /**
1534         * <p>Reverses the order of the given array.</p>
1535         *
1536         * <p>This method does nothing for a {@code null} input array.</p>
1537         *
1538         * @param array  the array to reverse, may be {@code null}
1539         */
1540        public static void reverse(double[] array) {
1541            if (array == null) {
1542                return;
1543            }
1544            int i = 0;
1545            int j = array.length - 1;
1546            double tmp;
1547            while (j > i) {
1548                tmp = array[j];
1549                array[j] = array[i];
1550                array[i] = tmp;
1551                j--;
1552                i++;
1553            }
1554        }
1555    
1556        /**
1557         * <p>Reverses the order of the given array.</p>
1558         *
1559         * <p>This method does nothing for a {@code null} input array.</p>
1560         *
1561         * @param array  the array to reverse, may be {@code null}
1562         */
1563        public static void reverse(float[] array) {
1564            if (array == null) {
1565                return;
1566            }
1567            int i = 0;
1568            int j = array.length - 1;
1569            float tmp;
1570            while (j > i) {
1571                tmp = array[j];
1572                array[j] = array[i];
1573                array[i] = tmp;
1574                j--;
1575                i++;
1576            }
1577        }
1578    
1579        /**
1580         * <p>Reverses the order of the given array.</p>
1581         *
1582         * <p>This method does nothing for a {@code null} input array.</p>
1583         *
1584         * @param array  the array to reverse, may be {@code null}
1585         */
1586        public static void reverse(boolean[] array) {
1587            if (array == null) {
1588                return;
1589            }
1590            int i = 0;
1591            int j = array.length - 1;
1592            boolean tmp;
1593            while (j > i) {
1594                tmp = array[j];
1595                array[j] = array[i];
1596                array[i] = tmp;
1597                j--;
1598                i++;
1599            }
1600        }
1601    
1602        // IndexOf search
1603        // ----------------------------------------------------------------------
1604    
1605        // Object IndexOf
1606        //-----------------------------------------------------------------------
1607        /**
1608         * <p>Finds the index of the given object in the array.</p>
1609         *
1610         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1611         *
1612         * @param array  the array to search through for the object, may be {@code null}
1613         * @param objectToFind  the object to find, may be {@code null}
1614         * @return the index of the object within the array,
1615         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1616         */
1617        public static int indexOf(Object[] array, Object objectToFind) {
1618            return indexOf(array, objectToFind, 0);
1619        }
1620    
1621        /**
1622         * <p>Finds the index of the given object in the array starting at the given index.</p>
1623         *
1624         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1625         *
1626         * <p>A negative startIndex is treated as zero. A startIndex larger than the array
1627         * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
1628         *
1629         * @param array  the array to search through for the object, may be {@code null}
1630         * @param objectToFind  the object to find, may be {@code null}
1631         * @param startIndex  the index to start searching at
1632         * @return the index of the object within the array starting at the index,
1633         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1634         */
1635        public static int indexOf(Object[] array, Object objectToFind, int startIndex) {
1636            if (array == null) {
1637                return INDEX_NOT_FOUND;
1638            }
1639            if (startIndex < 0) {
1640                startIndex = 0;
1641            }
1642            if (objectToFind == null) {
1643                for (int i = startIndex; i < array.length; i++) {
1644                    if (array[i] == null) {
1645                        return i;
1646                    }
1647                }
1648            } else if (array.getClass().getComponentType().isInstance(objectToFind)) {
1649                for (int i = startIndex; i < array.length; i++) {
1650                    if (objectToFind.equals(array[i])) {
1651                        return i;
1652                    }
1653                }
1654            }
1655            return INDEX_NOT_FOUND;
1656        }
1657    
1658        /**
1659         * <p>Finds the last index of the given object within the array.</p>
1660         *
1661         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1662         *
1663         * @param array  the array to travers backwords looking for the object, may be {@code null}
1664         * @param objectToFind  the object to find, may be {@code null}
1665         * @return the last index of the object within the array,
1666         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1667         */
1668        public static int lastIndexOf(Object[] array, Object objectToFind) {
1669            return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
1670        }
1671    
1672        /**
1673         * <p>Finds the last index of the given object in the array starting at the given index.</p>
1674         *
1675         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1676         *
1677         * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than
1678         * the array length will search from the end of the array.</p>
1679         *
1680         * @param array  the array to traverse for looking for the object, may be {@code null}
1681         * @param objectToFind  the object to find, may be {@code null}
1682         * @param startIndex  the start index to travers backwards from
1683         * @return the last index of the object within the array,
1684         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1685         */
1686        public static int lastIndexOf(Object[] array, Object objectToFind, int startIndex) {
1687            if (array == null) {
1688                return INDEX_NOT_FOUND;
1689            }
1690            if (startIndex < 0) {
1691                return INDEX_NOT_FOUND;
1692            } else if (startIndex >= array.length) {
1693                startIndex = array.length - 1;
1694            }
1695            if (objectToFind == null) {
1696                for (int i = startIndex; i >= 0; i--) {
1697                    if (array[i] == null) {
1698                        return i;
1699                    }
1700                }
1701            } else if (array.getClass().getComponentType().isInstance(objectToFind)) {
1702                for (int i = startIndex; i >= 0; i--) {
1703                    if (objectToFind.equals(array[i])) {
1704                        return i;
1705                    }
1706                }
1707            }
1708            return INDEX_NOT_FOUND;
1709        }
1710    
1711        /**
1712         * <p>Checks if the object is in the given array.</p>
1713         *
1714         * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
1715         *
1716         * @param array  the array to search through
1717         * @param objectToFind  the object to find
1718         * @return {@code true} if the array contains the object
1719         */
1720        public static boolean contains(Object[] array, Object objectToFind) {
1721            return indexOf(array, objectToFind) != INDEX_NOT_FOUND;
1722        }
1723    
1724        // long IndexOf
1725        //-----------------------------------------------------------------------
1726        /**
1727         * <p>Finds the index of the given value in the array.</p>
1728         *
1729         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1730         *
1731         * @param array  the array to search through for the object, may be {@code null}
1732         * @param valueToFind  the value to find
1733         * @return the index of the value within the array,
1734         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1735         */
1736        public static int indexOf(long[] array, long valueToFind) {
1737            return indexOf(array, valueToFind, 0);
1738        }
1739    
1740        /**
1741         * <p>Finds the index of the given value in the array starting at the given index.</p>
1742         *
1743         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) 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 {@link #INDEX_NOT_FOUND} ({@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 the index of the value within the array,
1752         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1753         */
1754        public static int indexOf(long[] array, long valueToFind, int startIndex) {
1755            if (array == null) {
1756                return INDEX_NOT_FOUND;
1757            }
1758            if (startIndex < 0) {
1759                startIndex = 0;
1760            }
1761            for (int i = startIndex; i < array.length; i++) {
1762                if (valueToFind == array[i]) {
1763                    return i;
1764                }
1765            }
1766            return INDEX_NOT_FOUND;
1767        }
1768    
1769        /**
1770         * <p>Finds the last index of the given value within the array.</p>
1771         *
1772         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1773         *
1774         * @param array  the array to travers backwords looking for the object, may be {@code null}
1775         * @param valueToFind  the object to find
1776         * @return the last index of the value within the array,
1777         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1778         */
1779        public static int lastIndexOf(long[] array, long valueToFind) {
1780            return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
1781        }
1782    
1783        /**
1784         * <p>Finds the last index of the given value in the array starting at the given index.</p>
1785         *
1786         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1787         *
1788         * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
1789         * array length will search from the end of the array.</p>
1790         *
1791         * @param array  the array to traverse for looking for the object, may be {@code null}
1792         * @param valueToFind  the value to find
1793         * @param startIndex  the start index to travers backwards from
1794         * @return the last index of the value within the array,
1795         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1796         */
1797        public static int lastIndexOf(long[] array, long valueToFind, int startIndex) {
1798            if (array == null) {
1799                return INDEX_NOT_FOUND;
1800            }
1801            if (startIndex < 0) {
1802                return INDEX_NOT_FOUND;
1803            } else if (startIndex >= array.length) {
1804                startIndex = array.length - 1;
1805            }
1806            for (int i = startIndex; i >= 0; i--) {
1807                if (valueToFind == array[i]) {
1808                    return i;
1809                }
1810            }
1811            return INDEX_NOT_FOUND;
1812        }
1813    
1814        /**
1815         * <p>Checks if the value is in the given array.</p>
1816         *
1817         * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
1818         *
1819         * @param array  the array to search through
1820         * @param valueToFind  the value to find
1821         * @return {@code true} if the array contains the object
1822         */
1823        public static boolean contains(long[] array, long valueToFind) {
1824            return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1825        }
1826    
1827        // int IndexOf
1828        //-----------------------------------------------------------------------
1829        /**
1830         * <p>Finds the index of the given value in the array.</p>
1831         *
1832         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1833         *
1834         * @param array  the array to search through for the object, may be {@code null}
1835         * @param valueToFind  the value to find
1836         * @return the index of the value within the array,
1837         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1838         */
1839        public static int indexOf(int[] array, int valueToFind) {
1840            return indexOf(array, valueToFind, 0);
1841        }
1842    
1843        /**
1844         * <p>Finds the index of the given value in the array starting at the given index.</p>
1845         *
1846         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) 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 {@link #INDEX_NOT_FOUND} ({@code -1}).</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 the index of the value within the array,
1855         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1856         */
1857        public static int indexOf(int[] array, int valueToFind, int startIndex) {
1858            if (array == null) {
1859                return INDEX_NOT_FOUND;
1860            }
1861            if (startIndex < 0) {
1862                startIndex = 0;
1863            }
1864            for (int i = startIndex; i < array.length; i++) {
1865                if (valueToFind == array[i]) {
1866                    return i;
1867                }
1868            }
1869            return INDEX_NOT_FOUND;
1870        }
1871    
1872        /**
1873         * <p>Finds the last index of the given value within the array.</p>
1874         *
1875         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1876         *
1877         * @param array  the array to travers backwords looking for the object, may be {@code null}
1878         * @param valueToFind  the object to find
1879         * @return the last index of the value within the array,
1880         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1881         */
1882        public static int lastIndexOf(int[] array, int valueToFind) {
1883            return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
1884        }
1885    
1886        /**
1887         * <p>Finds the last index of the given value in the array starting at the given index.</p>
1888         *
1889         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1890         *
1891         * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
1892         * array length will search from the end of the array.</p>
1893         *
1894         * @param array  the array to traverse for looking for the object, may be {@code null}
1895         * @param valueToFind  the value to find
1896         * @param startIndex  the start index to travers backwards from
1897         * @return the last index of the value within the array,
1898         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1899         */
1900        public static int lastIndexOf(int[] array, int valueToFind, int startIndex) {
1901            if (array == null) {
1902                return INDEX_NOT_FOUND;
1903            }
1904            if (startIndex < 0) {
1905                return INDEX_NOT_FOUND;
1906            } else if (startIndex >= array.length) {
1907                startIndex = array.length - 1;
1908            }
1909            for (int i = startIndex; i >= 0; i--) {
1910                if (valueToFind == array[i]) {
1911                    return i;
1912                }
1913            }
1914            return INDEX_NOT_FOUND;
1915        }
1916    
1917        /**
1918         * <p>Checks if the value is in the given array.</p>
1919         *
1920         * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
1921         *
1922         * @param array  the array to search through
1923         * @param valueToFind  the value to find
1924         * @return {@code true} if the array contains the object
1925         */
1926        public static boolean contains(int[] array, int valueToFind) {
1927            return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
1928        }
1929    
1930        // short IndexOf
1931        //-----------------------------------------------------------------------
1932        /**
1933         * <p>Finds the index of the given value in the array.</p>
1934         *
1935         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1936         *
1937         * @param array  the array to search through for the object, may be {@code null}
1938         * @param valueToFind  the value to find
1939         * @return the index of the value within the array,
1940         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1941         */
1942        public static int indexOf(short[] array, short valueToFind) {
1943            return indexOf(array, valueToFind, 0);
1944        }
1945    
1946        /**
1947         * <p>Finds the index of the given value in the array starting at the given index.</p>
1948         *
1949         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1950         *
1951         * <p>A negative startIndex is treated as zero. A startIndex larger than the array
1952         * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
1953         *
1954         * @param array  the array to search through for the object, may be {@code null}
1955         * @param valueToFind  the value to find
1956         * @param startIndex  the index to start searching at
1957         * @return the index of the value within the array,
1958         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1959         */
1960        public static int indexOf(short[] array, short valueToFind, int startIndex) {
1961            if (array == null) {
1962                return INDEX_NOT_FOUND;
1963            }
1964            if (startIndex < 0) {
1965                startIndex = 0;
1966            }
1967            for (int i = startIndex; i < array.length; i++) {
1968                if (valueToFind == array[i]) {
1969                    return i;
1970                }
1971            }
1972            return INDEX_NOT_FOUND;
1973        }
1974    
1975        /**
1976         * <p>Finds the last index of the given value within the array.</p>
1977         *
1978         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1979         *
1980         * @param array  the array to travers backwords looking for the object, may be {@code null}
1981         * @param valueToFind  the object to find
1982         * @return the last index of the value within the array,
1983         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
1984         */
1985        public static int lastIndexOf(short[] array, short valueToFind) {
1986            return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
1987        }
1988    
1989        /**
1990         * <p>Finds the last index of the given value in the array starting at the given index.</p>
1991         *
1992         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
1993         *
1994         * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
1995         * array length will search from the end of the array.</p>
1996         *
1997         * @param array  the array to traverse for looking for the object, may be {@code null}
1998         * @param valueToFind  the value to find
1999         * @param startIndex  the start index to travers backwards from
2000         * @return the last index of the value within the array,
2001         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2002         */
2003        public static int lastIndexOf(short[] array, short valueToFind, int startIndex) {
2004            if (array == null) {
2005                return INDEX_NOT_FOUND;
2006            }
2007            if (startIndex < 0) {
2008                return INDEX_NOT_FOUND;
2009            } else if (startIndex >= array.length) {
2010                startIndex = array.length - 1;
2011            }
2012            for (int i = startIndex; i >= 0; i--) {
2013                if (valueToFind == array[i]) {
2014                    return i;
2015                }
2016            }
2017            return INDEX_NOT_FOUND;
2018        }
2019    
2020        /**
2021         * <p>Checks if the value is in the given array.</p>
2022         *
2023         * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
2024         *
2025         * @param array  the array to search through
2026         * @param valueToFind  the value to find
2027         * @return {@code true} if the array contains the object
2028         */
2029        public static boolean contains(short[] array, short valueToFind) {
2030            return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2031        }
2032    
2033        // char IndexOf
2034        //-----------------------------------------------------------------------
2035        /**
2036         * <p>Finds the index of the given value in the array.</p>
2037         *
2038         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2039         *
2040         * @param array  the array to search through for the object, may be {@code null}
2041         * @param valueToFind  the value to find
2042         * @return the index of the value within the array,
2043         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2044         * @since 2.1
2045         */
2046        public static int indexOf(char[] array, char valueToFind) {
2047            return indexOf(array, valueToFind, 0);
2048        }
2049    
2050        /**
2051         * <p>Finds the index of the given value in the array starting at the given index.</p>
2052         *
2053         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2054         *
2055         * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2056         * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
2057         *
2058         * @param array  the array to search through for the object, may be {@code null}
2059         * @param valueToFind  the value to find
2060         * @param startIndex  the index to start searching at
2061         * @return the index of the value within the array,
2062         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2063         * @since 2.1
2064         */
2065        public static int indexOf(char[] array, char valueToFind, int startIndex) {
2066            if (array == null) {
2067                return INDEX_NOT_FOUND;
2068            }
2069            if (startIndex < 0) {
2070                startIndex = 0;
2071            }
2072            for (int i = startIndex; i < array.length; i++) {
2073                if (valueToFind == array[i]) {
2074                    return i;
2075                }
2076            }
2077            return INDEX_NOT_FOUND;
2078        }
2079    
2080        /**
2081         * <p>Finds the last index of the given value within the array.</p>
2082         *
2083         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2084         *
2085         * @param array  the array to travers backwords looking for the object, may be {@code null}
2086         * @param valueToFind  the object to find
2087         * @return the last index of the value within the array,
2088         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2089         * @since 2.1
2090         */
2091        public static int lastIndexOf(char[] array, char valueToFind) {
2092            return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
2093        }
2094    
2095        /**
2096         * <p>Finds the last index of the given value in the array starting at the given index.</p>
2097         *
2098         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2099         *
2100         * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
2101         * array length will search from the end of the array.</p>
2102         *
2103         * @param array  the array to traverse for looking for the object, may be {@code null}
2104         * @param valueToFind  the value to find
2105         * @param startIndex  the start index to travers backwards from
2106         * @return the last index of the value within the array,
2107         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2108         * @since 2.1
2109         */
2110        public static int lastIndexOf(char[] array, char valueToFind, int startIndex) {
2111            if (array == null) {
2112                return INDEX_NOT_FOUND;
2113            }
2114            if (startIndex < 0) {
2115                return INDEX_NOT_FOUND;
2116            } else if (startIndex >= array.length) {
2117                startIndex = array.length - 1;
2118            }
2119            for (int i = startIndex; i >= 0; i--) {
2120                if (valueToFind == array[i]) {
2121                    return i;
2122                }
2123            }
2124            return INDEX_NOT_FOUND;
2125        }
2126    
2127        /**
2128         * <p>Checks if the value is in the given array.</p>
2129         *
2130         * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
2131         *
2132         * @param array  the array to search through
2133         * @param valueToFind  the value to find
2134         * @return {@code true} if the array contains the object
2135         * @since 2.1
2136         */
2137        public static boolean contains(char[] array, char valueToFind) {
2138            return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2139        }
2140    
2141        // byte IndexOf
2142        //-----------------------------------------------------------------------
2143        /**
2144         * <p>Finds the index of the given value in the array.</p>
2145         *
2146         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2147         *
2148         * @param array  the array to search through for the object, may be {@code null}
2149         * @param valueToFind  the value to find
2150         * @return the index of the value within the array,
2151         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2152         */
2153        public static int indexOf(byte[] array, byte valueToFind) {
2154            return indexOf(array, valueToFind, 0);
2155        }
2156    
2157        /**
2158         * <p>Finds the index of the given value in the array starting at the given index.</p>
2159         *
2160         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2161         *
2162         * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2163         * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
2164         *
2165         * @param array  the array to search through for the object, may be {@code null}
2166         * @param valueToFind  the value to find
2167         * @param startIndex  the index to start searching at
2168         * @return the index of the value within the array,
2169         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2170         */
2171        public static int indexOf(byte[] array, byte valueToFind, int startIndex) {
2172            if (array == null) {
2173                return INDEX_NOT_FOUND;
2174            }
2175            if (startIndex < 0) {
2176                startIndex = 0;
2177            }
2178            for (int i = startIndex; i < array.length; i++) {
2179                if (valueToFind == array[i]) {
2180                    return i;
2181                }
2182            }
2183            return INDEX_NOT_FOUND;
2184        }
2185    
2186        /**
2187         * <p>Finds the last index of the given value within the array.</p>
2188         *
2189         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2190         *
2191         * @param array  the array to travers backwords looking for the object, may be {@code null}
2192         * @param valueToFind  the object to find
2193         * @return the last index of the value within the array,
2194         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2195         */
2196        public static int lastIndexOf(byte[] array, byte valueToFind) {
2197            return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
2198        }
2199    
2200        /**
2201         * <p>Finds the last index of the given value in the array starting at the given index.</p>
2202         *
2203         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2204         *
2205         * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
2206         * array length will search from the end of the array.</p>
2207         *
2208         * @param array  the array to traverse for looking for the object, may be {@code null}
2209         * @param valueToFind  the value to find
2210         * @param startIndex  the start index to travers backwards from
2211         * @return the last index of the value within the array,
2212         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2213         */
2214        public static int lastIndexOf(byte[] array, byte valueToFind, int startIndex) {
2215            if (array == null) {
2216                return INDEX_NOT_FOUND;
2217            }
2218            if (startIndex < 0) {
2219                return INDEX_NOT_FOUND;
2220            } else if (startIndex >= array.length) {
2221                startIndex = array.length - 1;
2222            }
2223            for (int i = startIndex; i >= 0; i--) {
2224                if (valueToFind == array[i]) {
2225                    return i;
2226                }
2227            }
2228            return INDEX_NOT_FOUND;
2229        }
2230    
2231        /**
2232         * <p>Checks if the value is in the given array.</p>
2233         *
2234         * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
2235         *
2236         * @param array  the array to search through
2237         * @param valueToFind  the value to find
2238         * @return {@code true} if the array contains the object
2239         */
2240        public static boolean contains(byte[] array, byte valueToFind) {
2241            return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2242        }
2243    
2244        // double IndexOf
2245        //-----------------------------------------------------------------------
2246        /**
2247         * <p>Finds the index of the given value in the array.</p>
2248         *
2249         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2250         *
2251         * @param array  the array to search through for the object, may be {@code null}
2252         * @param valueToFind  the value to find
2253         * @return the index of the value within the array,
2254         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2255         */
2256        public static int indexOf(double[] array, double valueToFind) {
2257            return indexOf(array, valueToFind, 0);
2258        }
2259    
2260        /**
2261         * <p>Finds the index of the given value within a given tolerance in the array.
2262         * This method will return the index of the first value which falls between the region
2263         * defined by valueToFind - tolerance and valueToFind + tolerance.</p>
2264         *
2265         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2266         *
2267         * @param array  the array to search through for the object, may be {@code null}
2268         * @param valueToFind  the value to find
2269         * @param tolerance tolerance of the search
2270         * @return the index of the value within the array,
2271         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2272         */
2273        public static int indexOf(double[] array, double valueToFind, double tolerance) {
2274            return indexOf(array, valueToFind, 0, tolerance);
2275        }
2276    
2277        /**
2278         * <p>Finds the index of the given value in the array starting at the given index.</p>
2279         *
2280         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2281         *
2282         * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2283         * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
2284         *
2285         * @param array  the array to search through for the object, may be {@code null}
2286         * @param valueToFind  the value to find
2287         * @param startIndex  the index to start searching at
2288         * @return the index of the value within the array,
2289         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2290         */
2291        public static int indexOf(double[] array, double valueToFind, int startIndex) {
2292            if (ArrayUtils.isEmpty(array)) {
2293                return INDEX_NOT_FOUND;
2294            }
2295            if (startIndex < 0) {
2296                startIndex = 0;
2297            }
2298            for (int i = startIndex; i < array.length; i++) {
2299                if (valueToFind == array[i]) {
2300                    return i;
2301                }
2302            }
2303            return INDEX_NOT_FOUND;
2304        }
2305    
2306        /**
2307         * <p>Finds the index of the given value in the array starting at the given index.
2308         * This method will return the index of the first value which falls between the region
2309         * defined by valueToFind - tolerance and valueToFind + tolerance.</p>
2310         *
2311         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2312         *
2313         * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2314         * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
2315         *
2316         * @param array  the array to search through for the object, may be {@code null}
2317         * @param valueToFind  the value to find
2318         * @param startIndex  the index to start searching at
2319         * @param tolerance tolerance of the search
2320         * @return the index of the value within the array,
2321         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2322         */
2323        public static int indexOf(double[] array, double valueToFind, int startIndex, double tolerance) {
2324            if (ArrayUtils.isEmpty(array)) {
2325                return INDEX_NOT_FOUND;
2326            }
2327            if (startIndex < 0) {
2328                startIndex = 0;
2329            }
2330            double min = valueToFind - tolerance;
2331            double max = valueToFind + tolerance;
2332            for (int i = startIndex; i < array.length; i++) {
2333                if (array[i] >= min && array[i] <= max) {
2334                    return i;
2335                }
2336            }
2337            return INDEX_NOT_FOUND;
2338        }
2339    
2340        /**
2341         * <p>Finds the last index of the given value within the array.</p>
2342         *
2343         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2344         *
2345         * @param array  the array to travers backwords looking for the object, may be {@code null}
2346         * @param valueToFind  the object to find
2347         * @return the last index of the value within the array,
2348         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2349         */
2350        public static int lastIndexOf(double[] array, double valueToFind) {
2351            return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
2352        }
2353    
2354        /**
2355         * <p>Finds the last index of the given value within a given tolerance in the array.
2356         * This method will return the index of the last value which falls between the region
2357         * defined by valueToFind - tolerance and valueToFind + tolerance.</p>
2358         *
2359         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2360         *
2361         * @param array  the array to search through for the object, may be {@code null}
2362         * @param valueToFind  the value to find
2363         * @param tolerance tolerance of the search
2364         * @return the index of the value within the array,
2365         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2366         */
2367        public static int lastIndexOf(double[] array, double valueToFind, double tolerance) {
2368            return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance);
2369        }
2370    
2371        /**
2372         * <p>Finds the last index of the given value in the array starting at the given index.</p>
2373         *
2374         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2375         *
2376         * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
2377         * array length will search from the end of the array.</p>
2378         *
2379         * @param array  the array to traverse for looking for the object, may be {@code null}
2380         * @param valueToFind  the value to find
2381         * @param startIndex  the start index to travers backwards from
2382         * @return the last index of the value within the array,
2383         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2384         */
2385        public static int lastIndexOf(double[] array, double valueToFind, int startIndex) {
2386            if (ArrayUtils.isEmpty(array)) {
2387                return INDEX_NOT_FOUND;
2388            }
2389            if (startIndex < 0) {
2390                return INDEX_NOT_FOUND;
2391            } else if (startIndex >= array.length) {
2392                startIndex = array.length - 1;
2393            }
2394            for (int i = startIndex; i >= 0; i--) {
2395                if (valueToFind == array[i]) {
2396                    return i;
2397                }
2398            }
2399            return INDEX_NOT_FOUND;
2400        }
2401    
2402        /**
2403         * <p>Finds the last index of the given value in the array starting at the given index.
2404         * This method will return the index of the last value which falls between the region
2405         * defined by valueToFind - tolerance and valueToFind + tolerance.</p>
2406         *
2407         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2408         *
2409         * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
2410         * array length will search from the end of the array.</p>
2411         *
2412         * @param array  the array to traverse for looking for the object, may be {@code null}
2413         * @param valueToFind  the value to find
2414         * @param startIndex  the start index to travers backwards from
2415         * @param tolerance  search for value within plus/minus this amount
2416         * @return the last index of the value within the array,
2417         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2418         */
2419        public static int lastIndexOf(double[] array, double valueToFind, int startIndex, double tolerance) {
2420            if (ArrayUtils.isEmpty(array)) {
2421                return INDEX_NOT_FOUND;
2422            }
2423            if (startIndex < 0) {
2424                return INDEX_NOT_FOUND;
2425            } else if (startIndex >= array.length) {
2426                startIndex = array.length - 1;
2427            }
2428            double min = valueToFind - tolerance;
2429            double max = valueToFind + tolerance;
2430            for (int i = startIndex; i >= 0; i--) {
2431                if (array[i] >= min && array[i] <= max) {
2432                    return i;
2433                }
2434            }
2435            return INDEX_NOT_FOUND;
2436        }
2437    
2438        /**
2439         * <p>Checks if the value is in the given array.</p>
2440         *
2441         * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
2442         *
2443         * @param array  the array to search through
2444         * @param valueToFind  the value to find
2445         * @return {@code true} if the array contains the object
2446         */
2447        public static boolean contains(double[] array, double valueToFind) {
2448            return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2449        }
2450    
2451        /**
2452         * <p>Checks if a value falling within the given tolerance is in the
2453         * given array.  If the array contains a value within the inclusive range
2454         * defined by (value - tolerance) to (value + tolerance).</p>
2455         *
2456         * <p>The method returns {@code false} if a {@code null} array
2457         * is passed in.</p>
2458         *
2459         * @param array  the array to search
2460         * @param valueToFind  the value to find
2461         * @param tolerance  the array contains the tolerance of the search
2462         * @return true if value falling within tolerance is in array
2463         */
2464        public static boolean contains(double[] array, double valueToFind, double tolerance) {
2465            return indexOf(array, valueToFind, 0, tolerance) != INDEX_NOT_FOUND;
2466        }
2467    
2468        // float IndexOf
2469        //-----------------------------------------------------------------------
2470        /**
2471         * <p>Finds the index of the given value in the array.</p>
2472         *
2473         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2474         *
2475         * @param array  the array to search through for the object, may be {@code null}
2476         * @param valueToFind  the value to find
2477         * @return the index of the value within the array,
2478         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2479         */
2480        public static int indexOf(float[] array, float valueToFind) {
2481            return indexOf(array, valueToFind, 0);
2482        }
2483    
2484        /**
2485         * <p>Finds the index of the given value in the array starting at the given index.</p>
2486         *
2487         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2488         *
2489         * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2490         * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
2491         *
2492         * @param array  the array to search through for the object, may be {@code null}
2493         * @param valueToFind  the value to find
2494         * @param startIndex  the index to start searching at
2495         * @return the index of the value within the array,
2496         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2497         */
2498        public static int indexOf(float[] array, float valueToFind, int startIndex) {
2499            if (ArrayUtils.isEmpty(array)) {
2500                return INDEX_NOT_FOUND;
2501            }
2502            if (startIndex < 0) {
2503                startIndex = 0;
2504            }
2505            for (int i = startIndex; i < array.length; i++) {
2506                if (valueToFind == array[i]) {
2507                    return i;
2508                }
2509            }
2510            return INDEX_NOT_FOUND;
2511        }
2512    
2513        /**
2514         * <p>Finds the last index of the given value within the array.</p>
2515         *
2516         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2517         *
2518         * @param array  the array to travers backwords looking for the object, may be {@code null}
2519         * @param valueToFind  the object to find
2520         * @return the last index of the value within the array,
2521         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2522         */
2523        public static int lastIndexOf(float[] array, float valueToFind) {
2524            return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
2525        }
2526    
2527        /**
2528         * <p>Finds the last index of the given value in the array starting at the given index.</p>
2529         *
2530         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2531         *
2532         * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than the
2533         * array length will search from the end of the array.</p>
2534         *
2535         * @param array  the array to traverse for looking for the object, may be {@code null}
2536         * @param valueToFind  the value to find
2537         * @param startIndex  the start index to travers backwards from
2538         * @return the last index of the value within the array,
2539         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2540         */
2541        public static int lastIndexOf(float[] array, float valueToFind, int startIndex) {
2542            if (ArrayUtils.isEmpty(array)) {
2543                return INDEX_NOT_FOUND;
2544            }
2545            if (startIndex < 0) {
2546                return INDEX_NOT_FOUND;
2547            } else if (startIndex >= array.length) {
2548                startIndex = array.length - 1;
2549            }
2550            for (int i = startIndex; i >= 0; i--) {
2551                if (valueToFind == array[i]) {
2552                    return i;
2553                }
2554            }
2555            return INDEX_NOT_FOUND;
2556        }
2557    
2558        /**
2559         * <p>Checks if the value is in the given array.</p>
2560         *
2561         * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
2562         *
2563         * @param array  the array to search through
2564         * @param valueToFind  the value to find
2565         * @return {@code true} if the array contains the object
2566         */
2567        public static boolean contains(float[] array, float valueToFind) {
2568            return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2569        }
2570    
2571        // boolean IndexOf
2572        //-----------------------------------------------------------------------
2573        /**
2574         * <p>Finds the index of the given value in the array.</p>
2575         *
2576         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2577         *
2578         * @param array  the array to search through for the object, may be {@code null}
2579         * @param valueToFind  the value to find
2580         * @return the index of the value within the array,
2581         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2582         */
2583        public static int indexOf(boolean[] array, boolean valueToFind) {
2584            return indexOf(array, valueToFind, 0);
2585        }
2586    
2587        /**
2588         * <p>Finds the index of the given value in the array starting at the given index.</p>
2589         *
2590         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2591         *
2592         * <p>A negative startIndex is treated as zero. A startIndex larger than the array
2593         * length will return {@link #INDEX_NOT_FOUND} ({@code -1}).</p>
2594         *
2595         * @param array  the array to search through for the object, may be {@code null}
2596         * @param valueToFind  the value to find
2597         * @param startIndex  the index to start searching at
2598         * @return the index of the value within the array,
2599         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null}
2600         *  array input
2601         */
2602        public static int indexOf(boolean[] array, boolean valueToFind, int startIndex) {
2603            if (ArrayUtils.isEmpty(array)) {
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        /**
2618         * <p>Finds the last index of the given value within the array.</p>
2619         *
2620         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) if
2621         * {@code null} array input.</p>
2622         *
2623         * @param array  the array to travers backwords looking for the object, may be {@code null}
2624         * @param valueToFind  the object to find
2625         * @return the last index of the value within the array,
2626         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2627         */
2628        public static int lastIndexOf(boolean[] array, boolean valueToFind) {
2629            return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
2630        }
2631    
2632        /**
2633         * <p>Finds the last index of the given value in the array starting at the given index.</p>
2634         *
2635         * <p>This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array.</p>
2636         *
2637         * <p>A negative startIndex will return {@link #INDEX_NOT_FOUND} ({@code -1}). A startIndex larger than
2638         * the array length will search from the end of the array.</p>
2639         *
2640         * @param array  the array to traverse for looking for the object, may be {@code null}
2641         * @param valueToFind  the value to find
2642         * @param startIndex  the start index to travers backwards from
2643         * @return the last index of the value within the array,
2644         *  {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input
2645         */
2646        public static int lastIndexOf(boolean[] array, boolean valueToFind, int startIndex) {
2647            if (ArrayUtils.isEmpty(array)) {
2648                return INDEX_NOT_FOUND;
2649            }
2650            if (startIndex < 0) {
2651                return INDEX_NOT_FOUND;
2652            } else if (startIndex >= array.length) {
2653                startIndex = array.length - 1;
2654            }
2655            for (int i = startIndex; i >= 0; i--) {
2656                if (valueToFind == array[i]) {
2657                    return i;
2658                }
2659            }
2660            return INDEX_NOT_FOUND;
2661        }
2662    
2663        /**
2664         * <p>Checks if the value is in the given array.</p>
2665         *
2666         * <p>The method returns {@code false} if a {@code null} array is passed in.</p>
2667         *
2668         * @param array  the array to search through
2669         * @param valueToFind  the value to find
2670         * @return {@code true} if the array contains the object
2671         */
2672        public static boolean contains(boolean[] array, boolean valueToFind) {
2673            return indexOf(array, valueToFind) != INDEX_NOT_FOUND;
2674        }
2675    
2676        // Primitive/Object array converters
2677        // ----------------------------------------------------------------------
2678    
2679        // Character array converters
2680        // ----------------------------------------------------------------------
2681        /**
2682         * <p>Converts an array of object Characters to primitives.</p>
2683         *
2684         * <p>This method returns {@code null} for a {@code null} input array.</p>
2685         *
2686         * @param array  a {@code Character} array, may be {@code null}
2687         * @return a {@code char} array, {@code null} if null array input
2688         * @throws NullPointerException if array content is {@code null}
2689         */
2690        public static char[] toPrimitive(Character[] array) {
2691            if (array == null) {
2692                return null;
2693            } else if (array.length == 0) {
2694                return EMPTY_CHAR_ARRAY;
2695            }
2696            final char[] result = new char[array.length];
2697            for (int i = 0; i < array.length; i++) {
2698                result[i] = array[i].charValue();
2699            }
2700            return result;
2701        }
2702    
2703        /**
2704         * <p>Converts an array of object Character to primitives handling {@code null}.</p>
2705         *
2706         * <p>This method returns {@code null} for a {@code null} input array.</p>
2707         *
2708         * @param array  a {@code Character} array, may be {@code null}
2709         * @param valueForNull  the value to insert if {@code null} found
2710         * @return a {@code char} array, {@code null} if null array input
2711         */
2712        public static char[] toPrimitive(Character[] array, char valueForNull) {
2713            if (array == null) {
2714                return null;
2715            } else if (array.length == 0) {
2716                return EMPTY_CHAR_ARRAY;
2717            }
2718            final char[] result = new char[array.length];
2719            for (int i = 0; i < array.length; i++) {
2720                Character b = array[i];
2721                result[i] = (b == null ? valueForNull : b.charValue());
2722            }
2723            return result;
2724        }
2725    
2726        /**
2727         * <p>Converts an array of primitive chars to objects.</p>
2728         *
2729         * <p>This method returns {@code null} for a {@code null} input array.</p>
2730         *
2731         * @param array a {@code char} array
2732         * @return a {@code Character} array, {@code null} if null array input
2733         */
2734        public static Character[] toObject(char[] array) {
2735            if (array == null) {
2736                return null;
2737            } else if (array.length == 0) {
2738                return EMPTY_CHARACTER_OBJECT_ARRAY;
2739            }
2740            final Character[] result = new Character[array.length];
2741            for (int i = 0; i < array.length; i++) {
2742                result[i] = Character.valueOf(array[i]);
2743            }
2744            return result;
2745         }
2746    
2747        // Long array converters
2748        // ----------------------------------------------------------------------
2749        /**
2750         * <p>Converts an array of object Longs to primitives.</p>
2751         *
2752         * <p>This method returns {@code null} for a {@code null} input array.</p>
2753         *
2754         * @param array  a {@code Long} array, may be {@code null}
2755         * @return a {@code long} array, {@code null} if null array input
2756         * @throws NullPointerException if array content is {@code null}
2757         */
2758        public static long[] toPrimitive(Long[] array) {
2759            if (array == null) {
2760                return null;
2761            } else if (array.length == 0) {
2762                return EMPTY_LONG_ARRAY;
2763            }
2764            final long[] result = new long[array.length];
2765            for (int i = 0; i < array.length; i++) {
2766                result[i] = array[i].longValue();
2767            }
2768            return result;
2769        }
2770    
2771        /**
2772         * <p>Converts an array of object Long to primitives handling {@code null}.</p>
2773         *
2774         * <p>This method returns {@code null} for a {@code null} input array.</p>
2775         *
2776         * @param array  a {@code Long} array, may be {@code null}
2777         * @param valueForNull  the value to insert if {@code null} found
2778         * @return a {@code long} array, {@code null} if null array input
2779         */
2780        public static long[] toPrimitive(Long[] array, long valueForNull) {
2781            if (array == null) {
2782                return null;
2783            } else if (array.length == 0) {
2784                return EMPTY_LONG_ARRAY;
2785            }
2786            final long[] result = new long[array.length];
2787            for (int i = 0; i < array.length; i++) {
2788                Long b = array[i];
2789                result[i] = (b == null ? valueForNull : b.longValue());
2790            }
2791            return result;
2792        }
2793    
2794        /**
2795         * <p>Converts an array of primitive longs to objects.</p>
2796         *
2797         * <p>This method returns {@code null} for a {@code null} input array.</p>
2798         *
2799         * @param array  a {@code long} array
2800         * @return a {@code Long} array, {@code null} if null array input
2801         */
2802        public static Long[] toObject(long[] array) {
2803            if (array == null) {
2804                return null;
2805            } else if (array.length == 0) {
2806                return EMPTY_LONG_OBJECT_ARRAY;
2807            }
2808            final Long[] result = new Long[array.length];
2809            for (int i = 0; i < array.length; i++) {
2810                result[i] = Long.valueOf(array[i]);
2811            }
2812            return result;
2813        }
2814    
2815        // Int array converters
2816        // ----------------------------------------------------------------------
2817        /**
2818         * <p>Converts an array of object Integers to primitives.</p>
2819         *
2820         * <p>This method returns {@code null} for a {@code null} input array.</p>
2821         *
2822         * @param array  a {@code Integer} array, may be {@code null}
2823         * @return an {@code int} array, {@code null} if null array input
2824         * @throws NullPointerException if array content is {@code null}
2825         */
2826        public static int[] toPrimitive(Integer[] array) {
2827            if (array == null) {
2828                return null;
2829            } else if (array.length == 0) {
2830                return EMPTY_INT_ARRAY;
2831            }
2832            final int[] result = new int[array.length];
2833            for (int i = 0; i < array.length; i++) {
2834                result[i] = array[i].intValue();
2835            }
2836            return result;
2837        }
2838    
2839        /**
2840         * <p>Converts an array of object Integer to primitives handling {@code null}.</p>
2841         *
2842         * <p>This method returns {@code null} for a {@code null} input array.</p>
2843         *
2844         * @param array  a {@code Integer} array, may be {@code null}
2845         * @param valueForNull  the value to insert if {@code null} found
2846         * @return an {@code int} array, {@code null} if null array input
2847         */
2848        public static int[] toPrimitive(Integer[] array, int valueForNull) {
2849            if (array == null) {
2850                return null;
2851            } else if (array.length == 0) {
2852                return EMPTY_INT_ARRAY;
2853            }
2854            final int[] result = new int[array.length];
2855            for (int i = 0; i < array.length; i++) {
2856                Integer b = array[i];
2857                result[i] = (b == null ? valueForNull : b.intValue());
2858            }
2859            return result;
2860        }
2861    
2862        /**
2863         * <p>Converts an array of primitive ints to objects.</p>
2864         *
2865         * <p>This method returns {@code null} for a {@code null} input array.</p>
2866         *
2867         * @param array  an {@code int} array
2868         * @return an {@code Integer} array, {@code null} if null array input
2869         */
2870        public static Integer[] toObject(int[] array) {
2871            if (array == null) {
2872                return null;
2873            } else if (array.length == 0) {
2874                return EMPTY_INTEGER_OBJECT_ARRAY;
2875            }
2876            final Integer[] result = new Integer[array.length];
2877            for (int i = 0; i < array.length; i++) {
2878                result[i] = Integer.valueOf(array[i]);
2879            }
2880            return result;
2881        }
2882    
2883        // Short array converters
2884        // ----------------------------------------------------------------------
2885        /**
2886         * <p>Converts an array of object Shorts to primitives.</p>
2887         *
2888         * <p>This method returns {@code null} for a {@code null} input array.</p>
2889         *
2890         * @param array  a {@code Short} array, may be {@code null}
2891         * @return a {@code byte} array, {@code null} if null array input
2892         * @throws NullPointerException if array content is {@code null}
2893         */
2894        public static short[] toPrimitive(Short[] array) {
2895            if (array == null) {
2896                return null;
2897            } else if (array.length == 0) {
2898                return EMPTY_SHORT_ARRAY;
2899            }
2900            final short[] result = new short[array.length];
2901            for (int i = 0; i < array.length; i++) {
2902                result[i] = array[i].shortValue();
2903            }
2904            return result;
2905        }
2906    
2907        /**
2908         * <p>Converts an array of object Short to primitives handling {@code null}.</p>
2909         *
2910         * <p>This method returns {@code null} for a {@code null} input array.</p>
2911         *
2912         * @param array  a {@code Short} array, may be {@code null}
2913         * @param valueForNull  the value to insert if {@code null} found
2914         * @return a {@code byte} array, {@code null} if null array input
2915         */
2916        public static short[] toPrimitive(Short[] array, short valueForNull) {
2917            if (array == null) {
2918                return null;
2919            } else if (array.length == 0) {
2920                return EMPTY_SHORT_ARRAY;
2921            }
2922            final short[] result = new short[array.length];
2923            for (int i = 0; i < array.length; i++) {
2924                Short b = array[i];
2925                result[i] = (b == null ? valueForNull : b.shortValue());
2926            }
2927            return result;
2928        }
2929    
2930        /**
2931         * <p>Converts an array of primitive shorts to objects.</p>
2932         *
2933         * <p>This method returns {@code null} for a {@code null} input array.</p>
2934         *
2935         * @param array  a {@code short} array
2936         * @return a {@code Short} array, {@code null} if null array input
2937         */
2938        public static Short[] toObject(short[] array) {
2939            if (array == null) {
2940                return null;
2941            } else if (array.length == 0) {
2942                return EMPTY_SHORT_OBJECT_ARRAY;
2943            }
2944            final Short[] result = new Short[array.length];
2945            for (int i = 0; i < array.length; i++) {
2946                result[i] = Short.valueOf(array[i]);
2947            }
2948            return result;
2949        }
2950    
2951        // Byte array converters
2952        // ----------------------------------------------------------------------
2953        /**
2954         * <p>Converts an array of object Bytes to primitives.</p>
2955         *
2956         * <p>This method returns {@code null} for a {@code null} input array.</p>
2957         *
2958         * @param array  a {@code Byte} array, may be {@code null}
2959         * @return a {@code byte} array, {@code null} if null array input
2960         * @throws NullPointerException if array content is {@code null}
2961         */
2962        public static byte[] toPrimitive(Byte[] array) {
2963            if (array == null) {
2964                return null;
2965            } else if (array.length == 0) {
2966                return EMPTY_BYTE_ARRAY;
2967            }
2968            final byte[] result = new byte[array.length];
2969            for (int i = 0; i < array.length; i++) {
2970                result[i] = array[i].byteValue();
2971            }
2972            return result;
2973        }
2974    
2975        /**
2976         * <p>Converts an array of object Bytes to primitives handling {@code null}.</p>
2977         *
2978         * <p>This method returns {@code null} for a {@code null} input array.</p>
2979         *
2980         * @param array  a {@code Byte} array, may be {@code null}
2981         * @param valueForNull  the value to insert if {@code null} found
2982         * @return a {@code byte} array, {@code null} if null array input
2983         */
2984        public static byte[] toPrimitive(Byte[] array, byte valueForNull) {
2985            if (array == null) {
2986                return null;
2987            } else if (array.length == 0) {
2988                return EMPTY_BYTE_ARRAY;
2989            }
2990            final byte[] result = new byte[array.length];
2991            for (int i = 0; i < array.length; i++) {
2992                Byte b = array[i];
2993                result[i] = (b == null ? valueForNull : b.byteValue());
2994            }
2995            return result;
2996        }
2997    
2998        /**
2999         * <p>Converts an array of primitive bytes to objects.</p>
3000         *
3001         * <p>This method returns {@code null} for a {@code null} input array.</p>
3002         *
3003         * @param array  a {@code byte} array
3004         * @return a {@code Byte} array, {@code null} if null array input
3005         */
3006        public static Byte[] toObject(byte[] array) {
3007            if (array == null) {
3008                return null;
3009            } else if (array.length == 0) {
3010                return EMPTY_BYTE_OBJECT_ARRAY;
3011            }
3012            final Byte[] result = new Byte[array.length];
3013            for (int i = 0; i < array.length; i++) {
3014                result[i] = Byte.valueOf(array[i]);
3015            }
3016            return result;
3017        }
3018    
3019        // Double array converters
3020        // ----------------------------------------------------------------------
3021        /**
3022         * <p>Converts an array of object Doubles to primitives.</p>
3023         *
3024         * <p>This method returns {@code null} for a {@code null} input array.</p>
3025         *
3026         * @param array  a {@code Double} array, may be {@code null}
3027         * @return a {@code double} array, {@code null} if null array input
3028         * @throws NullPointerException if array content is {@code null}
3029         */
3030        public static double[] toPrimitive(Double[] array) {
3031            if (array == null) {
3032                return null;
3033            } else if (array.length == 0) {
3034                return EMPTY_DOUBLE_ARRAY;
3035            }
3036            final double[] result = new double[array.length];
3037            for (int i = 0; i < array.length; i++) {
3038                result[i] = array[i].doubleValue();
3039            }
3040            return result;
3041        }
3042    
3043        /**
3044         * <p>Converts an array of object Doubles to primitives handling {@code null}.</p>
3045         *
3046         * <p>This method returns {@code null} for a {@code null} input array.</p>
3047         *
3048         * @param array  a {@code Double} array, may be {@code null}
3049         * @param valueForNull  the value to insert if {@code null} found
3050         * @return a {@code double} array, {@code null} if null array input
3051         */
3052        public static double[] toPrimitive(Double[] array, double valueForNull) {
3053            if (array == null) {
3054                return null;
3055            } else if (array.length == 0) {
3056                return EMPTY_DOUBLE_ARRAY;
3057            }
3058            final double[] result = new double[array.length];
3059            for (int i = 0; i < array.length; i++) {
3060                Double b = array[i];
3061                result[i] = (b == null ? valueForNull : b.doubleValue());
3062            }
3063            return result;
3064        }
3065    
3066        /**
3067         * <p>Converts an array of primitive doubles to objects.</p>
3068         *
3069         * <p>This method returns {@code null} for a {@code null} input array.</p>
3070         *
3071         * @param array  a {@code double} array
3072         * @return a {@code Double} array, {@code null} if null array input
3073         */
3074        public static Double[] toObject(double[] array) {
3075            if (array == null) {
3076                return null;
3077            } else if (array.length == 0) {
3078                return EMPTY_DOUBLE_OBJECT_ARRAY;
3079            }
3080            final Double[] result = new Double[array.length];
3081            for (int i = 0; i < array.length; i++) {
3082                result[i] = Double.valueOf(array[i]);
3083            }
3084            return result;
3085        }
3086    
3087        //   Float array converters
3088        // ----------------------------------------------------------------------
3089        /**
3090         * <p>Converts an array of object Floats to primitives.</p>
3091         *
3092         * <p>This method returns {@code null} for a {@code null} input array.</p>
3093         *
3094         * @param array  a {@code Float} array, may be {@code null}
3095         * @return a {@code float} array, {@code null} if null array input
3096         * @throws NullPointerException if array content is {@code null}
3097         */
3098        public static float[] toPrimitive(Float[] array) {
3099            if (array == null) {
3100                return null;
3101            } else if (array.length == 0) {
3102                return EMPTY_FLOAT_ARRAY;
3103            }
3104            final float[] result = new float[array.length];
3105            for (int i = 0; i < array.length; i++) {
3106                result[i] = array[i].floatValue();
3107            }
3108            return result;
3109        }
3110    
3111        /**
3112         * <p>Converts an array of object Floats to primitives handling {@code null}.</p>
3113         *
3114         * <p>This method returns {@code null} for a {@code null} input array.</p>
3115         *
3116         * @param array  a {@code Float} array, may be {@code null}
3117         * @param valueForNull  the value to insert if {@code null} found
3118         * @return a {@code float} array, {@code null} if null array input
3119         */
3120        public static float[] toPrimitive(Float[] array, float valueForNull) {
3121            if (array == null) {
3122                return null;
3123            } else if (array.length == 0) {
3124                return EMPTY_FLOAT_ARRAY;
3125            }
3126            final float[] result = new float[array.length];
3127            for (int i = 0; i < array.length; i++) {
3128                Float b = array[i];
3129                result[i] = (b == null ? valueForNull : b.floatValue());
3130            }
3131            return result;
3132        }
3133    
3134        /**
3135         * <p>Converts an array of primitive floats to objects.</p>
3136         *
3137         * <p>This method returns {@code null} for a {@code null} input array.</p>
3138         *
3139         * @param array  a {@code float} array
3140         * @return a {@code Float} array, {@code null} if null array input
3141         */
3142        public static Float[] toObject(float[] array) {
3143            if (array == null) {
3144                return null;
3145            } else if (array.length == 0) {
3146                return EMPTY_FLOAT_OBJECT_ARRAY;
3147            }
3148            final Float[] result = new Float[array.length];
3149            for (int i = 0; i < array.length; i++) {
3150                result[i] = Float.valueOf(array[i]);
3151            }
3152            return result;
3153        }
3154    
3155        // Boolean array converters
3156        // ----------------------------------------------------------------------
3157        /**
3158         * <p>Converts an array of object Booleans to primitives.</p>
3159         *
3160         * <p>This method returns {@code null} for a {@code null} input array.</p>
3161         *
3162         * @param array  a {@code Boolean} array, may be {@code null}
3163         * @return a {@code boolean} array, {@code null} if null array input
3164         * @throws NullPointerException if array content is {@code null}
3165         */
3166        public static boolean[] toPrimitive(Boolean[] array) {
3167            if (array == null) {
3168                return null;
3169            } else if (array.length == 0) {
3170                return EMPTY_BOOLEAN_ARRAY;
3171            }
3172            final boolean[] result = new boolean[array.length];
3173            for (int i = 0; i < array.length; i++) {
3174                result[i] = array[i].booleanValue();
3175            }
3176            return result;
3177        }
3178    
3179        /**
3180         * <p>Converts an array of object Booleans to primitives handling {@code null}.</p>
3181         *
3182         * <p>This method returns {@code null} for a {@code null} input array.</p>
3183         *
3184         * @param array  a {@code Boolean} array, may be {@code null}
3185         * @param valueForNull  the value to insert if {@code null} found
3186         * @return a {@code boolean} array, {@code null} if null array input
3187         */
3188        public static boolean[] toPrimitive(Boolean[] array, boolean valueForNull) {
3189            if (array == null) {
3190                return null;
3191            } else if (array.length == 0) {
3192                return EMPTY_BOOLEAN_ARRAY;
3193            }
3194            final boolean[] result = new boolean[array.length];
3195            for (int i = 0; i < array.length; i++) {
3196                Boolean b = array[i];
3197                result[i] = (b == null ? valueForNull : b.booleanValue());
3198            }
3199            return result;
3200        }
3201    
3202        /**
3203         * <p>Converts an array of primitive booleans to objects.</p>
3204         *
3205         * <p>This method returns {@code null} for a {@code null} input array.</p>
3206         *
3207         * @param array  a {@code boolean} array
3208         * @return a {@code Boolean} array, {@code null} if null array input
3209         */
3210        public static Boolean[] toObject(boolean[] array) {
3211            if (array == null) {
3212                return null;
3213            } else if (array.length == 0) {
3214                return EMPTY_BOOLEAN_OBJECT_ARRAY;
3215            }
3216            final Boolean[] result = new Boolean[array.length];
3217            for (int i = 0; i < array.length; i++) {
3218                result[i] = (array[i] ? Boolean.TRUE : Boolean.FALSE);
3219            }
3220            return result;
3221        }
3222    
3223        // ----------------------------------------------------------------------
3224        /**
3225         * <p>Checks if an array of Objects is empty or {@code null}.</p>
3226         *
3227         * @param array  the array to test
3228         * @return {@code true} if the array is empty or {@code null}
3229         * @since 2.1
3230         */
3231        public static boolean isEmpty(Object[] array) {
3232            return array == null || array.length == 0;
3233        }
3234    
3235        /**
3236         * <p>Checks if an array of primitive longs is empty or {@code null}.</p>
3237         *
3238         * @param array  the array to test
3239         * @return {@code true} if the array is empty or {@code null}
3240         * @since 2.1
3241         */
3242        public static boolean isEmpty(long[] array) {
3243            return array == null || array.length == 0;
3244        }
3245    
3246        /**
3247         * <p>Checks if an array of primitive ints is empty or {@code null}.</p>
3248         *
3249         * @param array  the array to test
3250         * @return {@code true} if the array is empty or {@code null}
3251         * @since 2.1
3252         */
3253        public static boolean isEmpty(int[] array) {
3254            return array == null || array.length == 0;
3255        }
3256    
3257        /**
3258         * <p>Checks if an array of primitive shorts is empty or {@code null}.</p>
3259         *
3260         * @param array  the array to test
3261         * @return {@code true} if the array is empty or {@code null}
3262         * @since 2.1
3263         */
3264        public static boolean isEmpty(short[] array) {
3265            return array == null || array.length == 0;
3266        }
3267    
3268        /**
3269         * <p>Checks if an array of primitive chars is empty or {@code null}.</p>
3270         *
3271         * @param array  the array to test
3272         * @return {@code true} if the array is empty or {@code null}
3273         * @since 2.1
3274         */
3275        public static boolean isEmpty(char[] array) {
3276            return array == null || array.length == 0;
3277        }
3278    
3279        /**
3280         * <p>Checks if an array of primitive bytes is empty or {@code null}.</p>
3281         *
3282         * @param array  the array to test
3283         * @return {@code true} if the array is empty or {@code null}
3284         * @since 2.1
3285         */
3286        public static boolean isEmpty(byte[] array) {
3287            return array == null || array.length == 0;
3288        }
3289    
3290        /**
3291         * <p>Checks if an array of primitive doubles is empty or {@code null}.</p>
3292         *
3293         * @param array  the array to test
3294         * @return {@code true} if the array is empty or {@code null}
3295         * @since 2.1
3296         */
3297        public static boolean isEmpty(double[] array) {
3298            return array == null || array.length == 0;
3299        }
3300    
3301        /**
3302         * <p>Checks if an array of primitive floats is empty or {@code null}.</p>
3303         *
3304         * @param array  the array to test
3305         * @return {@code true} if the array is empty or {@code null}
3306         * @since 2.1
3307         */
3308        public static boolean isEmpty(float[] array) {
3309            return array == null || array.length == 0;
3310        }
3311    
3312        /**
3313         * <p>Checks if an array of primitive booleans is empty or {@code null}.</p>
3314         *
3315         * @param array  the array to test
3316         * @return {@code true} if the array is empty or {@code null}
3317         * @since 2.1
3318         */
3319        public static boolean isEmpty(boolean[] array) {
3320            return array == null || array.length == 0;
3321        }
3322    
3323        // ----------------------------------------------------------------------
3324        /**
3325         * <p>Checks if an array of Objects is not empty or not {@code null}.</p>
3326         *
3327         * @param <T> the component type of the array
3328         * @param array  the array to test
3329         * @return {@code true} if the array is not empty or not {@code null}
3330         * @since 2.5
3331         */
3332         public static <T> boolean isNotEmpty(T[] array) {
3333             return (array != null && array.length != 0);
3334         }
3335    
3336        /**
3337         * <p>Checks if an array of primitive longs is not empty or not {@code null}.</p>
3338         *
3339         * @param array  the array to test
3340         * @return {@code true} if the array is not empty or not {@code null}
3341         * @since 2.5
3342         */
3343        public static boolean isNotEmpty(long[] array) {
3344            return (array != null && array.length != 0);
3345        }
3346    
3347        /**
3348         * <p>Checks if an array of primitive ints is not empty or not {@code null}.</p>
3349         *
3350         * @param array  the array to test
3351         * @return {@code true} if the array is not empty or not {@code null}
3352         * @since 2.5
3353         */
3354        public static boolean isNotEmpty(int[] array) {
3355            return (array != null && array.length != 0);
3356        }
3357    
3358        /**
3359         * <p>Checks if an array of primitive shorts is not empty or not {@code null}.</p>
3360         *
3361         * @param array  the array to test
3362         * @return {@code true} if the array is not empty or not {@code null}
3363         * @since 2.5
3364         */
3365        public static boolean isNotEmpty(short[] array) {
3366            return (array != null && array.length != 0);
3367        }
3368    
3369        /**
3370         * <p>Checks if an array of primitive chars is not empty or not {@code null}.</p>
3371         *
3372         * @param array  the array to test
3373         * @return {@code true} if the array is not empty or not {@code null}
3374         * @since 2.5
3375         */
3376        public static boolean isNotEmpty(char[] array) {
3377            return (array != null && array.length != 0);
3378        }
3379    
3380        /**
3381         * <p>Checks if an array of primitive bytes is not empty or not {@code null}.</p>
3382         *
3383         * @param array  the array to test
3384         * @return {@code true} if the array is not empty or not {@code null}
3385         * @since 2.5
3386         */
3387        public static boolean isNotEmpty(byte[] array) {
3388            return (array != null && array.length != 0);
3389        }
3390    
3391        /**
3392         * <p>Checks if an array of primitive doubles is not empty or not {@code null}.</p>
3393         *
3394         * @param array  the array to test
3395         * @return {@code true} if the array is not empty or not {@code null}
3396         * @since 2.5
3397         */
3398        public static boolean isNotEmpty(double[] array) {
3399            return (array != null && array.length != 0);
3400        }
3401    
3402        /**
3403         * <p>Checks if an array of primitive floats is not empty or not {@code null}.</p>
3404         *
3405         * @param array  the array to test
3406         * @return {@code true} if the array is not empty or not {@code null}
3407         * @since 2.5
3408         */
3409        public static boolean isNotEmpty(float[] array) {
3410            return (array != null && array.length != 0);
3411        }
3412    
3413        /**
3414         * <p>Checks if an array of primitive booleans is not empty or not {@code null}.</p>
3415         *
3416         * @param array  the array to test
3417         * @return {@code true} if the array is not empty or not {@code null}
3418         * @since 2.5
3419         */
3420        public static boolean isNotEmpty(boolean[] array) {
3421            return (array != null && array.length != 0);
3422        }
3423    
3424        /**
3425         * <p>Adds all the elements of the given arrays into a new array.</p>
3426         * <p>The new array contains all of the element of {@code array1} followed
3427         * by all of the elements {@code array2}. When an array is returned, it is always
3428         * a new array.</p>
3429         *
3430         * <pre>
3431         * ArrayUtils.addAll(null, null)     = null
3432         * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3433         * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3434         * ArrayUtils.addAll([], [])         = []
3435         * ArrayUtils.addAll([null], [null]) = [null, null]
3436         * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
3437         * </pre>
3438         *
3439         * @param <T> the component type of the array
3440         * @param array1  the first array whose elements are added to the new array, may be {@code null}
3441         * @param array2  the second array whose elements are added to the new array, may be {@code null}
3442         * @return The new array, {@code null} if both arrays are {@code null}.
3443         *      The type of the new array is the type of the first array,
3444         *      unless the first array is null, in which case the type is the same as the second array.
3445         * @since 2.1
3446         * @throws IllegalArgumentException if the array types are incompatible
3447         */
3448        public static <T> T[] addAll(T[] array1, T... array2) {
3449            if (array1 == null) {
3450                return clone(array2);
3451            } else if (array2 == null) {
3452                return clone(array1);
3453            }
3454            final Class<?> type1 = array1.getClass().getComponentType();
3455            @SuppressWarnings("unchecked") // OK, because array is of type T
3456            T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);
3457            System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3458            try {
3459                System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3460            } catch (ArrayStoreException ase) {
3461                // Check if problem was due to incompatible types
3462                /*
3463                 * We do this here, rather than before the copy because:
3464                 * - it would be a wasted check most of the time
3465                 * - safer, in case check turns out to be too strict
3466                 */
3467                final Class<?> type2 = array2.getClass().getComponentType();
3468                if (!type1.isAssignableFrom(type2)){
3469                    throw new IllegalArgumentException("Cannot store "+type2.getName()+" in an array of "
3470                            +type1.getName(), ase);
3471                }
3472                throw ase; // No, so rethrow original
3473            }
3474            return joinedArray;
3475        }
3476    
3477        /**
3478         * <p>Adds all the elements of the given arrays into a new array.</p>
3479         * <p>The new array contains all of the element of {@code array1} followed
3480         * by all of the elements {@code array2}. When an array is returned, it is always
3481         * a new array.</p>
3482         *
3483         * <pre>
3484         * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3485         * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3486         * ArrayUtils.addAll([], [])         = []
3487         * </pre>
3488         *
3489         * @param array1  the first array whose elements are added to the new array.
3490         * @param array2  the second array whose elements are added to the new array.
3491         * @return The new boolean[] array.
3492         * @since 2.1
3493         */
3494        public static boolean[] addAll(boolean[] array1, boolean... array2) {
3495            if (array1 == null) {
3496                return clone(array2);
3497            } else if (array2 == null) {
3498                return clone(array1);
3499            }
3500            boolean[] joinedArray = new boolean[array1.length + array2.length];
3501            System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3502            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3503            return joinedArray;
3504        }
3505    
3506        /**
3507         * <p>Adds all the elements of the given arrays into a new array.</p>
3508         * <p>The new array contains all of the element of {@code array1} followed
3509         * by all of the elements {@code array2}. When an array is returned, it is always
3510         * a new array.</p>
3511         *
3512         * <pre>
3513         * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3514         * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3515         * ArrayUtils.addAll([], [])         = []
3516         * </pre>
3517         *
3518         * @param array1  the first array whose elements are added to the new array.
3519         * @param array2  the second array whose elements are added to the new array.
3520         * @return The new char[] array.
3521         * @since 2.1
3522         */
3523        public static char[] addAll(char[] array1, char... array2) {
3524            if (array1 == null) {
3525                return clone(array2);
3526            } else if (array2 == null) {
3527                return clone(array1);
3528            }
3529            char[] joinedArray = new char[array1.length + array2.length];
3530            System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3531            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3532            return joinedArray;
3533        }
3534    
3535        /**
3536         * <p>Adds all the elements of the given arrays into a new array.</p>
3537         * <p>The new array contains all of the element of {@code array1} followed
3538         * by all of the elements {@code array2}. When an array is returned, it is always
3539         * a new array.</p>
3540         *
3541         * <pre>
3542         * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3543         * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3544         * ArrayUtils.addAll([], [])         = []
3545         * </pre>
3546         *
3547         * @param array1  the first array whose elements are added to the new array.
3548         * @param array2  the second array whose elements are added to the new array.
3549         * @return The new byte[] array.
3550         * @since 2.1
3551         */
3552        public static byte[] addAll(byte[] array1, byte... array2) {
3553            if (array1 == null) {
3554                return clone(array2);
3555            } else if (array2 == null) {
3556                return clone(array1);
3557            }
3558            byte[] joinedArray = new byte[array1.length + array2.length];
3559            System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3560            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3561            return joinedArray;
3562        }
3563    
3564        /**
3565         * <p>Adds all the elements of the given arrays into a new array.</p>
3566         * <p>The new array contains all of the element of {@code array1} followed
3567         * by all of the elements {@code array2}. When an array is returned, it is always
3568         * a new array.</p>
3569         *
3570         * <pre>
3571         * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3572         * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3573         * ArrayUtils.addAll([], [])         = []
3574         * </pre>
3575         *
3576         * @param array1  the first array whose elements are added to the new array.
3577         * @param array2  the second array whose elements are added to the new array.
3578         * @return The new short[] array.
3579         * @since 2.1
3580         */
3581        public static short[] addAll(short[] array1, short... array2) {
3582            if (array1 == null) {
3583                return clone(array2);
3584            } else if (array2 == null) {
3585                return clone(array1);
3586            }
3587            short[] joinedArray = new short[array1.length + array2.length];
3588            System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3589            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3590            return joinedArray;
3591        }
3592    
3593        /**
3594         * <p>Adds all the elements of the given arrays into a new array.</p>
3595         * <p>The new array contains all of the element of {@code array1} followed
3596         * by all of the elements {@code array2}. When an array is returned, it is always
3597         * a new array.</p>
3598         *
3599         * <pre>
3600         * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3601         * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3602         * ArrayUtils.addAll([], [])         = []
3603         * </pre>
3604         *
3605         * @param array1  the first array whose elements are added to the new array.
3606         * @param array2  the second array whose elements are added to the new array.
3607         * @return The new int[] array.
3608         * @since 2.1
3609         */
3610        public static int[] addAll(int[] array1, int... array2) {
3611            if (array1 == null) {
3612                return clone(array2);
3613            } else if (array2 == null) {
3614                return clone(array1);
3615            }
3616            int[] joinedArray = new int[array1.length + array2.length];
3617            System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3618            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3619            return joinedArray;
3620        }
3621    
3622        /**
3623         * <p>Adds all the elements of the given arrays into a new array.</p>
3624         * <p>The new array contains all of the element of {@code array1} followed
3625         * by all of the elements {@code array2}. When an array is returned, it is always
3626         * a new array.</p>
3627         *
3628         * <pre>
3629         * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3630         * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3631         * ArrayUtils.addAll([], [])         = []
3632         * </pre>
3633         *
3634         * @param array1  the first array whose elements are added to the new array.
3635         * @param array2  the second array whose elements are added to the new array.
3636         * @return The new long[] array.
3637         * @since 2.1
3638         */
3639        public static long[] addAll(long[] array1, long... array2) {
3640            if (array1 == null) {
3641                return clone(array2);
3642            } else if (array2 == null) {
3643                return clone(array1);
3644            }
3645            long[] joinedArray = new long[array1.length + array2.length];
3646            System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3647            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3648            return joinedArray;
3649        }
3650    
3651        /**
3652         * <p>Adds all the elements of the given arrays into a new array.</p>
3653         * <p>The new array contains all of the element of {@code array1} followed
3654         * by all of the elements {@code array2}. When an array is returned, it is always
3655         * a new array.</p>
3656         *
3657         * <pre>
3658         * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3659         * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3660         * ArrayUtils.addAll([], [])         = []
3661         * </pre>
3662         *
3663         * @param array1  the first array whose elements are added to the new array.
3664         * @param array2  the second array whose elements are added to the new array.
3665         * @return The new float[] array.
3666         * @since 2.1
3667         */
3668        public static float[] addAll(float[] array1, float... array2) {
3669            if (array1 == null) {
3670                return clone(array2);
3671            } else if (array2 == null) {
3672                return clone(array1);
3673            }
3674            float[] joinedArray = new float[array1.length + array2.length];
3675            System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3676            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3677            return joinedArray;
3678        }
3679    
3680        /**
3681         * <p>Adds all the elements of the given arrays into a new array.</p>
3682         * <p>The new array contains all of the element of {@code array1} followed
3683         * by all of the elements {@code array2}. When an array is returned, it is always
3684         * a new array.</p>
3685         *
3686         * <pre>
3687         * ArrayUtils.addAll(array1, null)   = cloned copy of array1
3688         * ArrayUtils.addAll(null, array2)   = cloned copy of array2
3689         * ArrayUtils.addAll([], [])         = []
3690         * </pre>
3691         *
3692         * @param array1  the first array whose elements are added to the new array.
3693         * @param array2  the second array whose elements are added to the new array.
3694         * @return The new double[] array.
3695         * @since 2.1
3696         */
3697        public static double[] addAll(double[] array1, double... array2) {
3698            if (array1 == null) {
3699                return clone(array2);
3700            } else if (array2 == null) {
3701                return clone(array1);
3702            }
3703            double[] joinedArray = new double[array1.length + array2.length];
3704            System.arraycopy(array1, 0, joinedArray, 0, array1.length);
3705            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
3706            return joinedArray;
3707        }
3708    
3709        /**
3710         * <p>Copies the given array and adds the given element at the end of the new array.</p>
3711         *
3712         * <p>The new array contains the same elements of the input
3713         * array plus the given element in the last position. The component type of
3714         * the new array is the same as that of the input array.</p>
3715         *
3716         * <p>If the input array is {@code null}, a new one element array is returned
3717         *  whose component type is the same as the element, unless the element itself is null,
3718         *  in which case the return type is Object[]</p>
3719         *
3720         * <pre>
3721         * ArrayUtils.add(null, null)      = [null]
3722         * ArrayUtils.add(null, "a")       = ["a"]
3723         * ArrayUtils.add(["a"], null)     = ["a", null]
3724         * ArrayUtils.add(["a"], "b")      = ["a", "b"]
3725         * ArrayUtils.add(["a", "b"], "c") = ["a", "b", "c"]
3726         * </pre>
3727         *
3728         * @param <T> the component type of the array
3729         * @param array  the array to "add" the element to, may be {@code null}
3730         * @param element  the object to add, may be {@code null}
3731         * @return A new array containing the existing elements plus the new element
3732         * The returned array type will be that of the input array (unless null),
3733         * in which case it will have the same type as the element.
3734         * If both are null, an IllegalArgumentException is thrown
3735         * @since 2.1
3736         * @throws IllegalArgumentException if both arguments are null
3737         */
3738        public static <T> T[] add(T[] array, T element) {
3739            Class<?> type;
3740            if (array != null){
3741                type = array.getClass();
3742            } else if (element != null) {
3743                type = element.getClass();
3744            } else {
3745                throw new IllegalArgumentException("Arguments cannot both be null");
3746            }
3747            @SuppressWarnings("unchecked") // type must be T
3748            T[] newArray = (T[]) copyArrayGrow1(array, type);
3749            newArray[newArray.length - 1] = element;
3750            return newArray;
3751        }
3752    
3753        /**
3754         * <p>Copies the given array and adds the given element at the end of the new array.</p>
3755         *
3756         * <p>The new array contains the same elements of the input
3757         * array plus the given element in the last position. The component type of
3758         * the new array is the same as that of the input array.</p>
3759         *
3760         * <p>If the input array is {@code null}, a new one element array is returned
3761         *  whose component type is the same as the element.</p>
3762         *
3763         * <pre>
3764         * ArrayUtils.add(null, true)          = [true]
3765         * ArrayUtils.add([true], false)       = [true, false]
3766         * ArrayUtils.add([true, false], true) = [true, false, true]
3767         * </pre>
3768         *
3769         * @param array  the array to copy and add the element to, may be {@code null}
3770         * @param element  the object to add at the last index of the new array
3771         * @return A new array containing the existing elements plus the new element
3772         * @since 2.1
3773         */
3774        public static boolean[] add(boolean[] array, boolean element) {
3775            boolean[] newArray = (boolean[])copyArrayGrow1(array, Boolean.TYPE);
3776            newArray[newArray.length - 1] = element;
3777            return newArray;
3778        }
3779    
3780        /**
3781         * <p>Copies the given array and adds the given element at the end of the new array.</p>
3782         *
3783         * <p>The new array contains the same elements of the input
3784         * array plus the given element in the last position. The component type of
3785         * the new array is the same as that of the input array.</p>
3786         *
3787         * <p>If the input array is {@code null}, a new one element array is returned
3788         *  whose component type is the same as the element.</p>
3789         *
3790         * <pre>
3791         * ArrayUtils.add(null, 0)   = [0]
3792         * ArrayUtils.add([1], 0)    = [1, 0]
3793         * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
3794         * </pre>
3795         *
3796         * @param array  the array to copy and add the element to, may be {@code null}
3797         * @param element  the object to add at the last index of the new array
3798         * @return A new array containing the existing elements plus the new element
3799         * @since 2.1
3800         */
3801        public static byte[] add(byte[] array, byte element) {
3802            byte[] newArray = (byte[])copyArrayGrow1(array, Byte.TYPE);
3803            newArray[newArray.length - 1] = element;
3804            return newArray;
3805        }
3806    
3807        /**
3808         * <p>Copies the given array and adds the given element at the end of the new array.</p>
3809         *
3810         * <p>The new array contains the same elements of the input
3811         * array plus the given element in the last position. The component type of
3812         * the new array is the same as that of the input array.</p>
3813         *
3814         * <p>If the input array is {@code null}, a new one element array is returned
3815         *  whose component type is the same as the element.</p>
3816         *
3817         * <pre>
3818         * ArrayUtils.add(null, '0')       = ['0']
3819         * ArrayUtils.add(['1'], '0')      = ['1', '0']
3820         * ArrayUtils.add(['1', '0'], '1') = ['1', '0', '1']
3821         * </pre>
3822         *
3823         * @param array  the array to copy and add the element to, may be {@code null}
3824         * @param element  the object to add at the last index of the new array
3825         * @return A new array containing the existing elements plus the new element
3826         * @since 2.1
3827         */
3828        public static char[] add(char[] array, char element) {
3829            char[] newArray = (char[])copyArrayGrow1(array, Character.TYPE);
3830            newArray[newArray.length - 1] = element;
3831            return newArray;
3832        }
3833    
3834        /**
3835         * <p>Copies the given array and adds the given element at the end of the new array.</p>
3836         *
3837         * <p>The new array contains the same elements of the input
3838         * array plus the given element in the last position. The component type of
3839         * the new array is the same as that of the input array.</p>
3840         *
3841         * <p>If the input array is {@code null}, a new one element array is returned
3842         *  whose component type is the same as the element.</p>
3843         *
3844         * <pre>
3845         * ArrayUtils.add(null, 0)   = [0]
3846         * ArrayUtils.add([1], 0)    = [1, 0]
3847         * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
3848         * </pre>
3849         *
3850         * @param array  the array to copy and add the element to, may be {@code null}
3851         * @param element  the object to add at the last index of the new array
3852         * @return A new array containing the existing elements plus the new element
3853         * @since 2.1
3854         */
3855        public static double[] add(double[] array, double element) {
3856            double[] newArray = (double[])copyArrayGrow1(array, Double.TYPE);
3857            newArray[newArray.length - 1] = element;
3858            return newArray;
3859        }
3860    
3861        /**
3862         * <p>Copies the given array and adds the given element at the end of the new array.</p>
3863         *
3864         * <p>The new array contains the same elements of the input
3865         * array plus the given element in the last position. The component type of
3866         * the new array is the same as that of the input array.</p>
3867         *
3868         * <p>If the input array is {@code null}, a new one element array is returned
3869         *  whose component type is the same as the element.</p>
3870         *
3871         * <pre>
3872         * ArrayUtils.add(null, 0)   = [0]
3873         * ArrayUtils.add([1], 0)    = [1, 0]
3874         * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
3875         * </pre>
3876         *
3877         * @param array  the array to copy and add the element to, may be {@code null}
3878         * @param element  the object to add at the last index of the new array
3879         * @return A new array containing the existing elements plus the new element
3880         * @since 2.1
3881         */
3882        public static float[] add(float[] array, float element) {
3883            float[] newArray = (float[])copyArrayGrow1(array, Float.TYPE);
3884            newArray[newArray.length - 1] = element;
3885            return newArray;
3886        }
3887    
3888        /**
3889         * <p>Copies the given array and adds the given element at the end of the new array.</p>
3890         *
3891         * <p>The new array contains the same elements of the input
3892         * array plus the given element in the last position. The component type of
3893         * the new array is the same as that of the input array.</p>
3894         *
3895         * <p>If the input array is {@code null}, a new one element array is returned
3896         *  whose component type is the same as the element.</p>
3897         *
3898         * <pre>
3899         * ArrayUtils.add(null, 0)   = [0]
3900         * ArrayUtils.add([1], 0)    = [1, 0]
3901         * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
3902         * </pre>
3903         *
3904         * @param array  the array to copy and add the element to, may be {@code null}
3905         * @param element  the object to add at the last index of the new array
3906         * @return A new array containing the existing elements plus the new element
3907         * @since 2.1
3908         */
3909        public static int[] add(int[] array, int element) {
3910            int[] newArray = (int[])copyArrayGrow1(array, Integer.TYPE);
3911            newArray[newArray.length - 1] = element;
3912            return newArray;
3913        }
3914    
3915        /**
3916         * <p>Copies the given array and adds the given element at the end of the new array.</p>
3917         *
3918         * <p>The new array contains the same elements of the input
3919         * array plus the given element in the last position. The component type of
3920         * the new array is the same as that of the input array.</p>
3921         *
3922         * <p>If the input array is {@code null}, a new one element array is returned
3923         *  whose component type is the same as the element.</p>
3924         *
3925         * <pre>
3926         * ArrayUtils.add(null, 0)   = [0]
3927         * ArrayUtils.add([1], 0)    = [1, 0]
3928         * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
3929         * </pre>
3930         *
3931         * @param array  the array to copy and add the element to, may be {@code null}
3932         * @param element  the object to add at the last index of the new array
3933         * @return A new array containing the existing elements plus the new element
3934         * @since 2.1
3935         */
3936        public static long[] add(long[] array, long element) {
3937            long[] newArray = (long[])copyArrayGrow1(array, Long.TYPE);
3938            newArray[newArray.length - 1] = element;
3939            return newArray;
3940        }
3941    
3942        /**
3943         * <p>Copies the given array and adds the given element at the end of the new array.</p>
3944         *
3945         * <p>The new array contains the same elements of the input
3946         * array plus the given element in the last position. The component type of
3947         * the new array is the same as that of the input array.</p>
3948         *
3949         * <p>If the input array is {@code null}, a new one element array is returned
3950         *  whose component type is the same as the element.</p>
3951         *
3952         * <pre>
3953         * ArrayUtils.add(null, 0)   = [0]
3954         * ArrayUtils.add([1], 0)    = [1, 0]
3955         * ArrayUtils.add([1, 0], 1) = [1, 0, 1]
3956         * </pre>
3957         *
3958         * @param array  the array to copy and add the element to, may be {@code null}
3959         * @param element  the object to add at the last index of the new array
3960         * @return A new array containing the existing elements plus the new element
3961         * @since 2.1
3962         */
3963        public static short[] add(short[] array, short element) {
3964            short[] newArray = (short[])copyArrayGrow1(array, Short.TYPE);
3965            newArray[newArray.length - 1] = element;
3966            return newArray;
3967        }
3968    
3969        /**
3970         * Returns a copy of the given array of size 1 greater than the argument.
3971         * The last value of the array is left to the default value.
3972         *
3973         * @param array The array to copy, must not be {@code null}.
3974         * @param newArrayComponentType If {@code array} is {@code null}, create a
3975         * size 1 array of this type.
3976         * @return A new copy of the array of size 1 greater than the input.
3977         */
3978        private static Object copyArrayGrow1(Object array, Class<?> newArrayComponentType) {
3979            if (array != null) {
3980                int arrayLength = Array.getLength(array);
3981                Object newArray = Array.newInstance(array.getClass().getComponentType(), arrayLength + 1);
3982                System.arraycopy(array, 0, newArray, 0, arrayLength);
3983                return newArray;
3984            }
3985            return Array.newInstance(newArrayComponentType, 1);
3986        }
3987    
3988        /**
3989         * <p>Inserts the specified element at the specified position in the array.
3990         * Shifts the element currently at that position (if any) and any subsequent
3991         * elements to the right (adds one to their indices).</p>
3992         *
3993         * <p>This method returns a new array with the same elements of the input
3994         * array plus the given element on the specified position. The component
3995         * type of the returned array is always the same as that of the input
3996         * array.</p>
3997         *
3998         * <p>If the input array is {@code null}, a new one element array is returned
3999         *  whose component type is the same as the element.</p>
4000         *
4001         * <pre>
4002         * ArrayUtils.add(null, 0, null)      = [null]
4003         * ArrayUtils.add(null, 0, "a")       = ["a"]
4004         * ArrayUtils.add(["a"], 1, null)     = ["a", null]
4005         * ArrayUtils.add(["a"], 1, "b")      = ["a", "b"]
4006         * ArrayUtils.add(["a", "b"], 3, "c") = ["a", "b", "c"]
4007         * </pre>
4008         *
4009         * @param <T> the component type of the array
4010         * @param array  the array to add the element to, may be {@code null}
4011         * @param index  the position of the new object
4012         * @param element  the object to add
4013         * @return A new array containing the existing elements and the new element
4014         * @throws IndexOutOfBoundsException if the index is out of range
4015         * (index < 0 || index > array.length).
4016         * @throws IllegalArgumentException if both array and element are null
4017         */
4018        public static <T> T[] add(T[] array, int index, T element) {
4019            Class<?> clss = null;
4020            if (array != null) {
4021                clss = array.getClass().getComponentType();
4022            } else if (element != null) {
4023                clss = element.getClass();
4024            } else {
4025                throw new IllegalArgumentException("Array and element cannot both be null");
4026            }
4027            @SuppressWarnings("unchecked") // the add method creates an array of type clss, which is type T
4028            final T[] newArray = (T[]) add(array, index, element, clss);
4029            return newArray;
4030        }
4031    
4032        /**
4033         * <p>Inserts the specified element at the specified position in the array.
4034         * Shifts the element currently at that position (if any) and any subsequent
4035         * elements to the right (adds one to their indices).</p>
4036         *
4037         * <p>This method returns a new array with the same elements of the input
4038         * array plus the given element on the specified position. The component
4039         * type of the returned array is always the same as that of the input
4040         * array.</p>
4041         *
4042         * <p>If the input array is {@code null}, a new one element array is returned
4043         *  whose component type is the same as the element.</p>
4044         *
4045         * <pre>
4046         * ArrayUtils.add(null, 0, true)          = [true]
4047         * ArrayUtils.add([true], 0, false)       = [false, true]
4048         * ArrayUtils.add([false], 1, true)       = [false, true]
4049         * ArrayUtils.add([true, false], 1, true) = [true, true, false]
4050         * </pre>
4051         *
4052         * @param array  the array to add the element to, may be {@code null}
4053         * @param index  the position of the new object
4054         * @param element  the object to add
4055         * @return A new array containing the existing elements and the new element
4056         * @throws IndexOutOfBoundsException if the index is out of range
4057         * (index < 0 || index > array.length).
4058         */
4059        public static boolean[] add(boolean[] array, int index, boolean element) {
4060            return (boolean[]) add(array, index, Boolean.valueOf(element), Boolean.TYPE);
4061        }
4062    
4063        /**
4064         * <p>Inserts the specified element at the specified position in the array.
4065         * Shifts the element currently at that position (if any) and any subsequent
4066         * elements to the right (adds one to their indices).</p>
4067         *
4068         * <p>This method returns a new array with the same elements of the input
4069         * array plus the given element on the specified position. The component
4070         * type of the returned array is always the same as that of the input
4071         * array.</p>
4072         *
4073         * <p>If the input array is {@code null}, a new one element array is returned
4074         *  whose component type is the same as the element.</p>
4075         *
4076         * <pre>
4077         * ArrayUtils.add(null, 0, 'a')            = ['a']
4078         * ArrayUtils.add(['a'], 0, 'b')           = ['b', 'a']
4079         * ArrayUtils.add(['a', 'b'], 0, 'c')      = ['c', 'a', 'b']
4080         * ArrayUtils.add(['a', 'b'], 1, 'k')      = ['a', 'k', 'b']
4081         * ArrayUtils.add(['a', 'b', 'c'], 1, 't') = ['a', 't', 'b', 'c']
4082         * </pre>
4083         *
4084         * @param array  the array to add the element to, may be {@code null}
4085         * @param index  the position of the new object
4086         * @param element  the object to add
4087         * @return A new array containing the existing elements and the new element
4088         * @throws IndexOutOfBoundsException if the index is out of range
4089         * (index < 0 || index > array.length).
4090         */
4091        public static char[] add(char[] array, int index, char element) {
4092            return (char[]) add(array, index, Character.valueOf(element), Character.TYPE);
4093        }
4094    
4095        /**
4096         * <p>Inserts the specified element at the specified position in the array.
4097         * Shifts the element currently at that position (if any) and any subsequent
4098         * elements to the right (adds one to their indices).</p>
4099         *
4100         * <p>This method returns a new array with the same elements of the input
4101         * array plus the given element on the specified position. The component
4102         * type of the returned array is always the same as that of the input
4103         * array.</p>
4104         *
4105         * <p>If the input array is {@code null}, a new one element array is returned
4106         *  whose component type is the same as the element.</p>
4107         *
4108         * <pre>
4109         * ArrayUtils.add([1], 0, 2)         = [2, 1]
4110         * ArrayUtils.add([2, 6], 2, 3)      = [2, 6, 3]
4111         * ArrayUtils.add([2, 6], 0, 1)      = [1, 2, 6]
4112         * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
4113         * </pre>
4114         *
4115         * @param array  the array to add the element to, may be {@code null}
4116         * @param index  the position of the new object
4117         * @param element  the object to add
4118         * @return A new array containing the existing elements and the new element
4119         * @throws IndexOutOfBoundsException if the index is out of range
4120         * (index < 0 || index > array.length).
4121         */
4122        public static byte[] add(byte[] array, int index, byte element) {
4123            return (byte[]) add(array, index, Byte.valueOf(element), Byte.TYPE);
4124        }
4125    
4126        /**
4127         * <p>Inserts the specified element at the specified position in the array.
4128         * Shifts the element currently at that position (if any) and any subsequent
4129         * elements to the right (adds one to their indices).</p>
4130         *
4131         * <p>This method returns a new array with the same elements of the input
4132         * array plus the given element on the specified position. The component
4133         * type of the returned array is always the same as that of the input
4134         * array.</p>
4135         *
4136         * <p>If the input array is {@code null}, a new one element array is returned
4137         *  whose component type is the same as the element.</p>
4138         *
4139         * <pre>
4140         * ArrayUtils.add([1], 0, 2)         = [2, 1]
4141         * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
4142         * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
4143         * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
4144         * </pre>
4145         *
4146         * @param array  the array to add the element to, may be {@code null}
4147         * @param index  the position of the new object
4148         * @param element  the object to add
4149         * @return A new array containing the existing elements and the new element
4150         * @throws IndexOutOfBoundsException if the index is out of range
4151         * (index < 0 || index > array.length).
4152         */
4153        public static short[] add(short[] array, int index, short element) {
4154            return (short[]) add(array, index, Short.valueOf(element), Short.TYPE);
4155        }
4156    
4157        /**
4158         * <p>Inserts the specified element at the specified position in the array.
4159         * Shifts the element currently at that position (if any) and any subsequent
4160         * elements to the right (adds one to their indices).</p>
4161         *
4162         * <p>This method returns a new array with the same elements of the input
4163         * array plus the given element on the specified position. The component
4164         * type of the returned array is always the same as that of the input
4165         * array.</p>
4166         *
4167         * <p>If the input array is {@code null}, a new one element array is returned
4168         *  whose component type is the same as the element.</p>
4169         *
4170         * <pre>
4171         * ArrayUtils.add([1], 0, 2)         = [2, 1]
4172         * ArrayUtils.add([2, 6], 2, 10)     = [2, 6, 10]
4173         * ArrayUtils.add([2, 6], 0, -4)     = [-4, 2, 6]
4174         * ArrayUtils.add([2, 6, 3], 2, 1)   = [2, 6, 1, 3]
4175         * </pre>
4176         *
4177         * @param array  the array to add the element to, may be {@code null}
4178         * @param index  the position of the new object
4179         * @param element  the object to add
4180         * @return A new array containing the existing elements and the new element
4181         * @throws IndexOutOfBoundsException if the index is out of range
4182         * (index < 0 || index > array.length).
4183         */
4184        public static int[] add(int[] array, int index, int element) {
4185            return (int[]) add(array, index, Integer.valueOf(element), Integer.TYPE);
4186        }
4187    
4188        /**
4189         * <p>Inserts the specified element at the specified position in the array.
4190         * Shifts the element currently at that position (if any) and any subsequent
4191         * elements to the right (adds one to their indices).</p>
4192         *
4193         * <p>This method returns a new array with the same elements of the input
4194         * array plus the given element on the specified position. The component
4195         * type of the returned array is always the same as that of the input
4196         * array.</p>
4197         *
4198         * <p>If the input array is {@code null}, a new one element array is returned
4199         *  whose component type is the same as the element.</p>
4200         *
4201         * <pre>
4202         * ArrayUtils.add([1L], 0, 2L)           = [2L, 1L]
4203         * ArrayUtils.add([2L, 6L], 2, 10L)      = [2L, 6L, 10L]
4204         * ArrayUtils.add([2L, 6L], 0, -4L)      = [-4L, 2L, 6L]
4205         * ArrayUtils.add([2L, 6L, 3L], 2, 1L)   = [2L, 6L, 1L, 3L]
4206         * </pre>
4207         *
4208         * @param array  the array to add the element to, may be {@code null}
4209         * @param index  the position of the new object
4210         * @param element  the object to add
4211         * @return A new array containing the existing elements and the new element
4212         * @throws IndexOutOfBoundsException if the index is out of range
4213         * (index < 0 || index > array.length).
4214         */
4215        public static long[] add(long[] array, int index, long element) {
4216            return (long[]) add(array, index, Long.valueOf(element), Long.TYPE);
4217        }
4218    
4219        /**
4220         * <p>Inserts the specified element at the specified position in the array.
4221         * Shifts the element currently at that position (if any) and any subsequent
4222         * elements to the right (adds one to their indices).</p>
4223         *
4224         * <p>This method returns a new array with the same elements of the input
4225         * array plus the given element on the specified position. The component
4226         * type of the returned array is always the same as that of the input
4227         * array.</p>
4228         *
4229         * <p>If the input array is {@code null}, a new one element array is returned
4230         *  whose component type is the same as the element.</p>
4231         *
4232         * <pre>
4233         * ArrayUtils.add([1.1f], 0, 2.2f)               = [2.2f, 1.1f]
4234         * ArrayUtils.add([2.3f, 6.4f], 2, 10.5f)        = [2.3f, 6.4f, 10.5f]
4235         * ArrayUtils.add([2.6f, 6.7f], 0, -4.8f)        = [-4.8f, 2.6f, 6.7f]
4236         * ArrayUtils.add([2.9f, 6.0f, 0.3f], 2, 1.0f)   = [2.9f, 6.0f, 1.0f, 0.3f]
4237         * </pre>
4238         *
4239         * @param array  the array to add the element to, may be {@code null}
4240         * @param index  the position of the new object
4241         * @param element  the object to add
4242         * @return A new array containing the existing elements and the new element
4243         * @throws IndexOutOfBoundsException if the index is out of range
4244         * (index < 0 || index > array.length).
4245         */
4246        public static float[] add(float[] array, int index, float element) {
4247            return (float[]) add(array, index, Float.valueOf(element), Float.TYPE);
4248        }
4249    
4250        /**
4251         * <p>Inserts the specified element at the specified position in the array.
4252         * Shifts the element currently at that position (if any) and any subsequent
4253         * elements to the right (adds one to their indices).</p>
4254         *
4255         * <p>This method returns a new array with the same elements of the input
4256         * array plus the given element on the specified position. The component
4257         * type of the returned array is always the same as that of the input
4258         * array.</p>
4259         *
4260         * <p>If the input array is {@code null}, a new one element array is returned
4261         *  whose component type is the same as the element.</p>
4262         *
4263         * <pre>
4264         * ArrayUtils.add([1.1], 0, 2.2)              = [2.2, 1.1]
4265         * ArrayUtils.add([2.3, 6.4], 2, 10.5)        = [2.3, 6.4, 10.5]
4266         * ArrayUtils.add([2.6, 6.7], 0, -4.8)        = [-4.8, 2.6, 6.7]
4267         * ArrayUtils.add([2.9, 6.0, 0.3], 2, 1.0)    = [2.9, 6.0, 1.0, 0.3]
4268         * </pre>
4269         *
4270         * @param array  the array to add the element to, may be {@code null}
4271         * @param index  the position of the new object
4272         * @param element  the object to add
4273         * @return A new array containing the existing elements and the new element
4274         * @throws IndexOutOfBoundsException if the index is out of range
4275         * (index < 0 || index > array.length).
4276         */
4277        public static double[] add(double[] array, int index, double element) {
4278            return (double[]) add(array, index, Double.valueOf(element), Double.TYPE);
4279        }
4280    
4281        /**
4282         * Underlying implementation of add(array, index, element) methods.
4283         * The last parameter is the class, which may not equal element.getClass
4284         * for primitives.
4285         *
4286         * @param array  the array to add the element to, may be {@code null}
4287         * @param index  the position of the new object
4288         * @param element  the object to add
4289         * @param clss the type of the element being added
4290         * @return A new array containing the existing elements and the new element
4291         */
4292        private static Object add(Object array, int index, Object element, Class<?> clss) {
4293            if (array == null) {
4294                if (index != 0) {
4295                    throw new IndexOutOfBoundsException("Index: " + index + ", Length: 0");
4296                }
4297                Object joinedArray = Array.newInstance(clss, 1);
4298                Array.set(joinedArray, 0, element);
4299                return joinedArray;
4300            }
4301            int length = Array.getLength(array);
4302            if (index > length || index < 0) {
4303                throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
4304            }
4305            Object result = Array.newInstance(clss, length + 1);
4306            System.arraycopy(array, 0, result, 0, index);
4307            Array.set(result, index, element);
4308            if (index < length) {
4309                System.arraycopy(array, index, result, index + 1, length - index);
4310            }
4311            return result;
4312        }
4313    
4314        /**
4315         * <p>Removes the element at the specified position from the specified array.
4316         * All subsequent elements are shifted to the left (subtracts one from
4317         * their indices).</p>
4318         *
4319         * <p>This method returns a new array with the same elements of the input
4320         * array except the element on the specified position. The component
4321         * type of the returned array is always the same as that of the input
4322         * array.</p>
4323         *
4324         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4325         * will be thrown, because in that case no valid index can be specified.</p>
4326         *
4327         * <pre>
4328         * ArrayUtils.remove(["a"], 0)           = []
4329         * ArrayUtils.remove(["a", "b"], 0)      = ["b"]
4330         * ArrayUtils.remove(["a", "b"], 1)      = ["a"]
4331         * ArrayUtils.remove(["a", "b", "c"], 1) = ["a", "c"]
4332         * </pre>
4333         *
4334         * @param <T> the component type of the array
4335         * @param array  the array to remove the element from, may not be {@code null}
4336         * @param index  the position of the element to be removed
4337         * @return A new array containing the existing elements except the element
4338         *         at the specified position.
4339         * @throws IndexOutOfBoundsException if the index is out of range
4340         * (index < 0 || index >= array.length), or if the array is {@code null}.
4341         * @since 2.1
4342         */
4343        @SuppressWarnings("unchecked") // remove() always creates an array of the same type as its input
4344        public static <T> T[] remove(T[] array, int index) {
4345            return (T[]) remove((Object) array, index);
4346        }
4347    
4348        /**
4349         * <p>Removes the first occurrence of the specified element from the
4350         * specified array. All subsequent elements are shifted to the left
4351         * (subtracts one from their indices). If the array doesn't contains
4352         * such an element, no elements are removed from the array.</p>
4353         *
4354         * <p>This method returns a new array with the same elements of the input
4355         * array except the first occurrence of the specified element. The component
4356         * type of the returned array is always the same as that of the input
4357         * array.</p>
4358         *
4359         * <pre>
4360         * ArrayUtils.removeElement(null, "a")            = null
4361         * ArrayUtils.removeElement([], "a")              = []
4362         * ArrayUtils.removeElement(["a"], "b")           = ["a"]
4363         * ArrayUtils.removeElement(["a", "b"], "a")      = ["b"]
4364         * ArrayUtils.removeElement(["a", "b", "a"], "a") = ["b", "a"]
4365         * </pre>
4366         *
4367         * @param <T> the component type of the array
4368         * @param array  the array to remove the element from, may be {@code null}
4369         * @param element  the element to be removed
4370         * @return A new array containing the existing elements except the first
4371         *         occurrence of the specified element.
4372         * @since 2.1
4373         */
4374        public static <T> T[] removeElement(T[] array, Object element) {
4375            int index = indexOf(array, element);
4376            if (index == INDEX_NOT_FOUND) {
4377                return clone(array);
4378            }
4379            return remove(array, index);
4380        }
4381    
4382        /**
4383         * <p>Removes the element at the specified position from the specified array.
4384         * All subsequent elements are shifted to the left (subtracts one from
4385         * their indices).</p>
4386         *
4387         * <p>This method returns a new array with the same elements of the input
4388         * array except the element on the specified position. The component
4389         * type of the returned array is always the same as that of the input
4390         * array.</p>
4391         *
4392         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4393         * will be thrown, because in that case no valid index can be specified.</p>
4394         *
4395         * <pre>
4396         * ArrayUtils.remove([true], 0)              = []
4397         * ArrayUtils.remove([true, false], 0)       = [false]
4398         * ArrayUtils.remove([true, false], 1)       = [true]
4399         * ArrayUtils.remove([true, true, false], 1) = [true, false]
4400         * </pre>
4401         *
4402         * @param array  the array to remove the element from, may not be {@code null}
4403         * @param index  the position of the element to be removed
4404         * @return A new array containing the existing elements except the element
4405         *         at the specified position.
4406         * @throws IndexOutOfBoundsException if the index is out of range
4407         * (index < 0 || index >= array.length), or if the array is {@code null}.
4408         * @since 2.1
4409         */
4410        public static boolean[] remove(boolean[] array, int index) {
4411            return (boolean[]) remove((Object) array, index);
4412        }
4413    
4414        /**
4415         * <p>Removes the first occurrence of the specified element from the
4416         * specified array. All subsequent elements are shifted to the left
4417         * (subtracts one from their indices). If the array doesn't contains
4418         * such an element, no elements are removed from the array.</p>
4419         *
4420         * <p>This method returns a new array with the same elements of the input
4421         * array except the first occurrence of the specified element. The component
4422         * type of the returned array is always the same as that of the input
4423         * array.</p>
4424         *
4425         * <pre>
4426         * ArrayUtils.removeElement(null, true)                = null
4427         * ArrayUtils.removeElement([], true)                  = []
4428         * ArrayUtils.removeElement([true], false)             = [true]
4429         * ArrayUtils.removeElement([true, false], false)      = [true]
4430         * ArrayUtils.removeElement([true, false, true], true) = [false, true]
4431         * </pre>
4432         *
4433         * @param array  the array to remove the element from, may be {@code null}
4434         * @param element  the element to be removed
4435         * @return A new array containing the existing elements except the first
4436         *         occurrence of the specified element.
4437         * @since 2.1
4438         */
4439        public static boolean[] removeElement(boolean[] array, boolean element) {
4440            int index = indexOf(array, element);
4441            if (index == INDEX_NOT_FOUND) {
4442                return clone(array);
4443            }
4444            return remove(array, index);
4445        }
4446    
4447        /**
4448         * <p>Removes the element at the specified position from the specified array.
4449         * All subsequent elements are shifted to the left (subtracts one from
4450         * their indices).</p>
4451         *
4452         * <p>This method returns a new array with the same elements of the input
4453         * array except the element on the specified position. The component
4454         * type of the returned array is always the same as that of the input
4455         * array.</p>
4456         *
4457         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4458         * will be thrown, because in that case no valid index can be specified.</p>
4459         *
4460         * <pre>
4461         * ArrayUtils.remove([1], 0)          = []
4462         * ArrayUtils.remove([1, 0], 0)       = [0]
4463         * ArrayUtils.remove([1, 0], 1)       = [1]
4464         * ArrayUtils.remove([1, 0, 1], 1)    = [1, 1]
4465         * </pre>
4466         *
4467         * @param array  the array to remove the element from, may not be {@code null}
4468         * @param index  the position of the element to be removed
4469         * @return A new array containing the existing elements except the element
4470         *         at the specified position.
4471         * @throws IndexOutOfBoundsException if the index is out of range
4472         * (index < 0 || index >= array.length), or if the array is {@code null}.
4473         * @since 2.1
4474         */
4475        public static byte[] remove(byte[] array, int index) {
4476            return (byte[]) remove((Object) array, index);
4477        }
4478    
4479        /**
4480         * <p>Removes the first occurrence of the specified element from the
4481         * specified array. All subsequent elements are shifted to the left
4482         * (subtracts one from their indices). If the array doesn't contains
4483         * such an element, no elements are removed from the array.</p>
4484         *
4485         * <p>This method returns a new array with the same elements of the input
4486         * array except the first occurrence of the specified element. The component
4487         * type of the returned array is always the same as that of the input
4488         * array.</p>
4489         *
4490         * <pre>
4491         * ArrayUtils.removeElement(null, 1)        = null
4492         * ArrayUtils.removeElement([], 1)          = []
4493         * ArrayUtils.removeElement([1], 0)         = [1]
4494         * ArrayUtils.removeElement([1, 0], 0)      = [1]
4495         * ArrayUtils.removeElement([1, 0, 1], 1)   = [0, 1]
4496         * </pre>
4497         *
4498         * @param array  the array to remove the element from, may be {@code null}
4499         * @param element  the element to be removed
4500         * @return A new array containing the existing elements except the first
4501         *         occurrence of the specified element.
4502         * @since 2.1
4503         */
4504        public static byte[] removeElement(byte[] array, byte element) {
4505            int index = indexOf(array, element);
4506            if (index == INDEX_NOT_FOUND) {
4507                return clone(array);
4508            }
4509            return remove(array, index);
4510        }
4511    
4512        /**
4513         * <p>Removes the element at the specified position from the specified array.
4514         * All subsequent elements are shifted to the left (subtracts one from
4515         * their indices).</p>
4516         *
4517         * <p>This method returns a new array with the same elements of the input
4518         * array except the element on the specified position. The component
4519         * type of the returned array is always the same as that of the input
4520         * array.</p>
4521         *
4522         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4523         * will be thrown, because in that case no valid index can be specified.</p>
4524         *
4525         * <pre>
4526         * ArrayUtils.remove(['a'], 0)           = []
4527         * ArrayUtils.remove(['a', 'b'], 0)      = ['b']
4528         * ArrayUtils.remove(['a', 'b'], 1)      = ['a']
4529         * ArrayUtils.remove(['a', 'b', 'c'], 1) = ['a', 'c']
4530         * </pre>
4531         *
4532         * @param array  the array to remove the element from, may not be {@code null}
4533         * @param index  the position of the element to be removed
4534         * @return A new array containing the existing elements except the element
4535         *         at the specified position.
4536         * @throws IndexOutOfBoundsException if the index is out of range
4537         * (index < 0 || index >= array.length), or if the array is {@code null}.
4538         * @since 2.1
4539         */
4540        public static char[] remove(char[] array, int index) {
4541            return (char[]) remove((Object) array, index);
4542        }
4543    
4544        /**
4545         * <p>Removes the first occurrence of the specified element from the
4546         * specified array. All subsequent elements are shifted to the left
4547         * (subtracts one from their indices). If the array doesn't contains
4548         * such an element, no elements are removed from the array.</p>
4549         *
4550         * <p>This method returns a new array with the same elements of the input
4551         * array except the first occurrence of the specified element. The component
4552         * type of the returned array is always the same as that of the input
4553         * array.</p>
4554         *
4555         * <pre>
4556         * ArrayUtils.removeElement(null, 'a')            = null
4557         * ArrayUtils.removeElement([], 'a')              = []
4558         * ArrayUtils.removeElement(['a'], 'b')           = ['a']
4559         * ArrayUtils.removeElement(['a', 'b'], 'a')      = ['b']
4560         * ArrayUtils.removeElement(['a', 'b', 'a'], 'a') = ['b', 'a']
4561         * </pre>
4562         *
4563         * @param array  the array to remove the element from, may be {@code null}
4564         * @param element  the element to be removed
4565         * @return A new array containing the existing elements except the first
4566         *         occurrence of the specified element.
4567         * @since 2.1
4568         */
4569        public static char[] removeElement(char[] array, char element) {
4570            int index = indexOf(array, element);
4571            if (index == INDEX_NOT_FOUND) {
4572                return clone(array);
4573            }
4574            return remove(array, index);
4575        }
4576    
4577        /**
4578         * <p>Removes the element at the specified position from the specified array.
4579         * All subsequent elements are shifted to the left (subtracts one from
4580         * their indices).</p>
4581         *
4582         * <p>This method returns a new array with the same elements of the input
4583         * array except the element on the specified position. The component
4584         * type of the returned array is always the same as that of the input
4585         * array.</p>
4586         *
4587         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4588         * will be thrown, because in that case no valid index can be specified.</p>
4589         *
4590         * <pre>
4591         * ArrayUtils.remove([1.1], 0)           = []
4592         * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
4593         * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
4594         * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
4595         * </pre>
4596         *
4597         * @param array  the array to remove the element from, may not be {@code null}
4598         * @param index  the position of the element to be removed
4599         * @return A new array containing the existing elements except the element
4600         *         at the specified position.
4601         * @throws IndexOutOfBoundsException if the index is out of range
4602         * (index < 0 || index >= array.length), or if the array is {@code null}.
4603         * @since 2.1
4604         */
4605        public static double[] remove(double[] array, int index) {
4606            return (double[]) remove((Object) array, index);
4607        }
4608    
4609        /**
4610         * <p>Removes the first occurrence of the specified element from the
4611         * specified array. All subsequent elements are shifted to the left
4612         * (subtracts one from their indices). If the array doesn't contains
4613         * such an element, no elements are removed from the array.</p>
4614         *
4615         * <p>This method returns a new array with the same elements of the input
4616         * array except the first occurrence of the specified element. The component
4617         * type of the returned array is always the same as that of the input
4618         * array.</p>
4619         *
4620         * <pre>
4621         * ArrayUtils.removeElement(null, 1.1)            = null
4622         * ArrayUtils.removeElement([], 1.1)              = []
4623         * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
4624         * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
4625         * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
4626         * </pre>
4627         *
4628         * @param array  the array to remove the element from, may be {@code null}
4629         * @param element  the element to be removed
4630         * @return A new array containing the existing elements except the first
4631         *         occurrence of the specified element.
4632         * @since 2.1
4633         */
4634        public static double[] removeElement(double[] array, double element) {
4635            int index = indexOf(array, element);
4636            if (index == INDEX_NOT_FOUND) {
4637                return clone(array);
4638            }
4639            return remove(array, index);
4640        }
4641    
4642        /**
4643         * <p>Removes the element at the specified position from the specified array.
4644         * All subsequent elements are shifted to the left (subtracts one from
4645         * their indices).</p>
4646         *
4647         * <p>This method returns a new array with the same elements of the input
4648         * array except the element on the specified position. The component
4649         * type of the returned array is always the same as that of the input
4650         * array.</p>
4651         *
4652         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4653         * will be thrown, because in that case no valid index can be specified.</p>
4654         *
4655         * <pre>
4656         * ArrayUtils.remove([1.1], 0)           = []
4657         * ArrayUtils.remove([2.5, 6.0], 0)      = [6.0]
4658         * ArrayUtils.remove([2.5, 6.0], 1)      = [2.5]
4659         * ArrayUtils.remove([2.5, 6.0, 3.8], 1) = [2.5, 3.8]
4660         * </pre>
4661         *
4662         * @param array  the array to remove the element from, may not be {@code null}
4663         * @param index  the position of the element to be removed
4664         * @return A new array containing the existing elements except the element
4665         *         at the specified position.
4666         * @throws IndexOutOfBoundsException if the index is out of range
4667         * (index < 0 || index >= array.length), or if the array is {@code null}.
4668         * @since 2.1
4669         */
4670        public static float[] remove(float[] array, int index) {
4671            return (float[]) remove((Object) array, index);
4672        }
4673    
4674        /**
4675         * <p>Removes the first occurrence of the specified element from the
4676         * specified array. All subsequent elements are shifted to the left
4677         * (subtracts one from their indices). If the array doesn't contains
4678         * such an element, no elements are removed from the array.</p>
4679         *
4680         * <p>This method returns a new array with the same elements of the input
4681         * array except the first occurrence of the specified element. The component
4682         * type of the returned array is always the same as that of the input
4683         * array.</p>
4684         *
4685         * <pre>
4686         * ArrayUtils.removeElement(null, 1.1)            = null
4687         * ArrayUtils.removeElement([], 1.1)              = []
4688         * ArrayUtils.removeElement([1.1], 1.2)           = [1.1]
4689         * ArrayUtils.removeElement([1.1, 2.3], 1.1)      = [2.3]
4690         * ArrayUtils.removeElement([1.1, 2.3, 1.1], 1.1) = [2.3, 1.1]
4691         * </pre>
4692         *
4693         * @param array  the array to remove the element from, may be {@code null}
4694         * @param element  the element to be removed
4695         * @return A new array containing the existing elements except the first
4696         *         occurrence of the specified element.
4697         * @since 2.1
4698         */
4699        public static float[] removeElement(float[] array, float element) {
4700            int index = indexOf(array, element);
4701            if (index == INDEX_NOT_FOUND) {
4702                return clone(array);
4703            }
4704            return remove(array, index);
4705        }
4706    
4707        /**
4708         * <p>Removes the element at the specified position from the specified array.
4709         * All subsequent elements are shifted to the left (subtracts one from
4710         * their indices).</p>
4711         *
4712         * <p>This method returns a new array with the same elements of the input
4713         * array except the element on the specified position. The component
4714         * type of the returned array is always the same as that of the input
4715         * array.</p>
4716         *
4717         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4718         * will be thrown, because in that case no valid index can be specified.</p>
4719         *
4720         * <pre>
4721         * ArrayUtils.remove([1], 0)         = []
4722         * ArrayUtils.remove([2, 6], 0)      = [6]
4723         * ArrayUtils.remove([2, 6], 1)      = [2]
4724         * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
4725         * </pre>
4726         *
4727         * @param array  the array to remove the element from, may not be {@code null}
4728         * @param index  the position of the element to be removed
4729         * @return A new array containing the existing elements except the element
4730         *         at the specified position.
4731         * @throws IndexOutOfBoundsException if the index is out of range
4732         * (index < 0 || index >= array.length), or if the array is {@code null}.
4733         * @since 2.1
4734         */
4735        public static int[] remove(int[] array, int index) {
4736            return (int[]) remove((Object) array, index);
4737        }
4738    
4739        /**
4740         * <p>Removes the first occurrence of the specified element from the
4741         * specified array. All subsequent elements are shifted to the left
4742         * (subtracts one from their indices). If the array doesn't contains
4743         * such an element, no elements are removed from the array.</p>
4744         *
4745         * <p>This method returns a new array with the same elements of the input
4746         * array except the first occurrence of the specified element. The component
4747         * type of the returned array is always the same as that of the input
4748         * array.</p>
4749         *
4750         * <pre>
4751         * ArrayUtils.removeElement(null, 1)      = null
4752         * ArrayUtils.removeElement([], 1)        = []
4753         * ArrayUtils.removeElement([1], 2)       = [1]
4754         * ArrayUtils.removeElement([1, 3], 1)    = [3]
4755         * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
4756         * </pre>
4757         *
4758         * @param array  the array to remove the element from, may be {@code null}
4759         * @param element  the element to be removed
4760         * @return A new array containing the existing elements except the first
4761         *         occurrence of the specified element.
4762         * @since 2.1
4763         */
4764        public static int[] removeElement(int[] array, int element) {
4765            int index = indexOf(array, element);
4766            if (index == INDEX_NOT_FOUND) {
4767                return clone(array);
4768            }
4769            return remove(array, index);
4770        }
4771    
4772        /**
4773         * <p>Removes the element at the specified position from the specified array.
4774         * All subsequent elements are shifted to the left (subtracts one from
4775         * their indices).</p>
4776         *
4777         * <p>This method returns a new array with the same elements of the input
4778         * array except the element on the specified position. The component
4779         * type of the returned array is always the same as that of the input
4780         * array.</p>
4781         *
4782         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4783         * will be thrown, because in that case no valid index can be specified.</p>
4784         *
4785         * <pre>
4786         * ArrayUtils.remove([1], 0)         = []
4787         * ArrayUtils.remove([2, 6], 0)      = [6]
4788         * ArrayUtils.remove([2, 6], 1)      = [2]
4789         * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
4790         * </pre>
4791         *
4792         * @param array  the array to remove the element from, may not be {@code null}
4793         * @param index  the position of the element to be removed
4794         * @return A new array containing the existing elements except the element
4795         *         at the specified position.
4796         * @throws IndexOutOfBoundsException if the index is out of range
4797         * (index < 0 || index >= array.length), or if the array is {@code null}.
4798         * @since 2.1
4799         */
4800        public static long[] remove(long[] array, int index) {
4801            return (long[]) remove((Object) array, index);
4802        }
4803    
4804        /**
4805         * <p>Removes the first occurrence of the specified element from the
4806         * specified array. All subsequent elements are shifted to the left
4807         * (subtracts one from their indices). If the array doesn't contains
4808         * such an element, no elements are removed from the array.</p>
4809         *
4810         * <p>This method returns a new array with the same elements of the input
4811         * array except the first occurrence of the specified element. The component
4812         * type of the returned array is always the same as that of the input
4813         * array.</p>
4814         *
4815         * <pre>
4816         * ArrayUtils.removeElement(null, 1)      = null
4817         * ArrayUtils.removeElement([], 1)        = []
4818         * ArrayUtils.removeElement([1], 2)       = [1]
4819         * ArrayUtils.removeElement([1, 3], 1)    = [3]
4820         * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
4821         * </pre>
4822         *
4823         * @param array  the array to remove the element from, may be {@code null}
4824         * @param element  the element to be removed
4825         * @return A new array containing the existing elements except the first
4826         *         occurrence of the specified element.
4827         * @since 2.1
4828         */
4829        public static long[] removeElement(long[] array, long element) {
4830            int index = indexOf(array, element);
4831            if (index == INDEX_NOT_FOUND) {
4832                return clone(array);
4833            }
4834            return remove(array, index);
4835        }
4836    
4837        /**
4838         * <p>Removes the element at the specified position from the specified array.
4839         * All subsequent elements are shifted to the left (subtracts one from
4840         * their indices).</p>
4841         *
4842         * <p>This method returns a new array with the same elements of the input
4843         * array except the element on the specified position. The component
4844         * type of the returned array is always the same as that of the input
4845         * array.</p>
4846         *
4847         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4848         * will be thrown, because in that case no valid index can be specified.</p>
4849         *
4850         * <pre>
4851         * ArrayUtils.remove([1], 0)         = []
4852         * ArrayUtils.remove([2, 6], 0)      = [6]
4853         * ArrayUtils.remove([2, 6], 1)      = [2]
4854         * ArrayUtils.remove([2, 6, 3], 1)   = [2, 3]
4855         * </pre>
4856         *
4857         * @param array  the array to remove the element from, may not be {@code null}
4858         * @param index  the position of the element to be removed
4859         * @return A new array containing the existing elements except the element
4860         *         at the specified position.
4861         * @throws IndexOutOfBoundsException if the index is out of range
4862         * (index < 0 || index >= array.length), or if the array is {@code null}.
4863         * @since 2.1
4864         */
4865        public static short[] remove(short[] array, int index) {
4866            return (short[]) remove((Object) array, index);
4867        }
4868    
4869        /**
4870         * <p>Removes the first occurrence of the specified element from the
4871         * specified array. All subsequent elements are shifted to the left
4872         * (subtracts one from their indices). If the array doesn't contains
4873         * such an element, no elements are removed from the array.</p>
4874         *
4875         * <p>This method returns a new array with the same elements of the input
4876         * array except the first occurrence of the specified element. The component
4877         * type of the returned array is always the same as that of the input
4878         * array.</p>
4879         *
4880         * <pre>
4881         * ArrayUtils.removeElement(null, 1)      = null
4882         * ArrayUtils.removeElement([], 1)        = []
4883         * ArrayUtils.removeElement([1], 2)       = [1]
4884         * ArrayUtils.removeElement([1, 3], 1)    = [3]
4885         * ArrayUtils.removeElement([1, 3, 1], 1) = [3, 1]
4886         * </pre>
4887         *
4888         * @param array  the array to remove the element from, may be {@code null}
4889         * @param element  the element to be removed
4890         * @return A new array containing the existing elements except the first
4891         *         occurrence of the specified element.
4892         * @since 2.1
4893         */
4894        public static short[] removeElement(short[] array, short element) {
4895            int index = indexOf(array, element);
4896            if (index == INDEX_NOT_FOUND) {
4897                return clone(array);
4898            }
4899            return remove(array, index);
4900        }
4901    
4902        /**
4903         * <p>Removes the element at the specified position from the specified array.
4904         * All subsequent elements are shifted to the left (subtracts one from
4905         * their indices).</p>
4906         *
4907         * <p>This method returns a new array with the same elements of the input
4908         * array except the element on the specified position. The component
4909         * type of the returned array is always the same as that of the input
4910         * array.</p>
4911         *
4912         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4913         * will be thrown, because in that case no valid index can be specified.</p>
4914         *
4915         * @param array  the array to remove the element from, may not be {@code null}
4916         * @param index  the position of the element to be removed
4917         * @return A new array containing the existing elements except the element
4918         *         at the specified position.
4919         * @throws IndexOutOfBoundsException if the index is out of range
4920         * (index < 0 || index >= array.length), or if the array is {@code null}.
4921         * @since 2.1
4922         */
4923        private static Object remove(Object array, int index) {
4924            int length = getLength(array);
4925            if (index < 0 || index >= length) {
4926                throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
4927            }
4928    
4929            Object result = Array.newInstance(array.getClass().getComponentType(), length - 1);
4930            System.arraycopy(array, 0, result, 0, index);
4931            if (index < length - 1) {
4932                System.arraycopy(array, index + 1, result, index, length - index - 1);
4933            }
4934    
4935            return result;
4936        }
4937    
4938        /**
4939         * <p>Removes the elements at the specified positions from the specified array.
4940         * All remaining elements are shifted to the left.</p>
4941         *
4942         * <p>This method returns a new array with the same elements of the input
4943         * array except those at the specified positions. The component
4944         * type of the returned array is always the same as that of the input
4945         * array.</p>
4946         *
4947         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
4948         * will be thrown, because in that case no valid index can be specified.</p>
4949         *
4950         * <pre>
4951         * ArrayUtils.removeAll(["a", "b", "c"], 0, 2) = ["b"]
4952         * ArrayUtils.removeAll(["a", "b", "c"], 1, 2) = ["a"]
4953         * </pre>
4954         *
4955         * @param <T> the component type of the array
4956         * @param array   the array to remove the element from, may not be {@code null}
4957         * @param indices the positions of the elements to be removed
4958         * @return A new array containing the existing elements except those
4959         *         at the specified positions.
4960         * @throws IndexOutOfBoundsException if any index is out of range
4961         * (index < 0 || index >= array.length), or if the array is {@code null}.
4962         * @since 3.0.1
4963         */
4964        @SuppressWarnings("unchecked")
4965        // removeAll() always creates an array of the same type as its input
4966        public static <T> T[] removeAll(T[] array, int... indices) {
4967            return (T[]) removeAll((Object) array, clone(indices));
4968        }
4969    
4970        /**
4971         * <p>Removes occurrences of specified elements, in specified quantities,
4972         * from the specified array. All subsequent elements are shifted left.
4973         * For any element-to-be-removed specified in greater quantities than
4974         * contained in the original array, no change occurs beyond the
4975         * removal of the existing matching items.</p>
4976         *
4977         * <p>This method returns a new array with the same elements of the input
4978         * array except for the earliest-encountered occurrences of the specified
4979         * elements. The component type of the returned array is always the same
4980         * as that of the input array.</p>
4981         *
4982         * <pre>
4983         * ArrayUtils.removeElements(null, "a", "b")            = null
4984         * ArrayUtils.removeElements([], "a", "b")              = []
4985         * ArrayUtils.removeElements(["a"], "b", "c")           = ["a"]
4986         * ArrayUtils.removeElements(["a", "b"], "a", "c")      = ["b"]
4987         * ArrayUtils.removeElements(["a", "b", "a"], "a")      = ["b", "a"]
4988         * ArrayUtils.removeElements(["a", "b", "a"], "a", "a") = ["b"]
4989         * </pre>
4990         *
4991         * @param <T> the component type of the array
4992         * @param array  the array to remove the element from, may be {@code null}
4993         * @param values the elements to be removed
4994         * @return A new array containing the existing elements except the
4995         *         earliest-encountered occurrences of the specified elements.
4996         * @since 3.0.1
4997         */
4998        public static <T> T[] removeElements(T[] array, T... values) {
4999            if (isEmpty(array) || isEmpty(values)) {
5000                return clone(array);
5001            }
5002            HashMap<T, MutableInt> occurrences = new HashMap<T, MutableInt>(values.length);
5003            for (T v : values) {
5004                MutableInt count = occurrences.get(v);
5005                if (count == null) {
5006                    occurrences.put(v, new MutableInt(1));
5007                } else {
5008                    count.increment();
5009                }
5010            }
5011            HashSet<Integer> toRemove = new HashSet<Integer>();
5012            for (Map.Entry<T, MutableInt> e : occurrences.entrySet()) {
5013                T v = e.getKey();
5014                int found = 0;
5015                for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5016                    found = indexOf(array, v, found);
5017                    if (found < 0) {
5018                        break;
5019                    }
5020                    toRemove.add(found++);
5021                }
5022            }
5023            return removeAll(array, extractIndices(toRemove));
5024        }
5025    
5026        /**
5027         * <p>Removes the elements at the specified positions from the specified array.
5028         * All remaining elements are shifted to the left.</p>
5029         *
5030         * <p>This method returns a new array with the same elements of the input
5031         * array except those at the specified positions. The component
5032         * type of the returned array is always the same as that of the input
5033         * array.</p>
5034         *
5035         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5036         * will be thrown, because in that case no valid index can be specified.</p>
5037         *
5038         * <pre>
5039         * ArrayUtils.removeAll([1], 0)             = []
5040         * ArrayUtils.removeAll([2, 6], 0)          = [6]
5041         * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5042         * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5043         * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5044         * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5045         * </pre>
5046         *
5047         * @param array   the array to remove the element from, may not be {@code null}
5048         * @param indices the positions of the elements to be removed
5049         * @return A new array containing the existing elements except those
5050         *         at the specified positions.
5051         * @throws IndexOutOfBoundsException if any index is out of range
5052         * (index < 0 || index >= array.length), or if the array is {@code null}.
5053         * @since 3.0.1
5054         */
5055        public static byte[] removeAll(byte[] array, int... indices) {
5056            return (byte[]) removeAll((Object) array, clone(indices));
5057        }
5058    
5059        /**
5060         * <p>Removes occurrences of specified elements, in specified quantities,
5061         * from the specified array. All subsequent elements are shifted left.
5062         * For any element-to-be-removed specified in greater quantities than
5063         * contained in the original array, no change occurs beyond the
5064         * removal of the existing matching items.</p>
5065         *
5066         * <p>This method returns a new array with the same elements of the input
5067         * array except for the earliest-encountered occurrences of the specified
5068         * elements. The component type of the returned array is always the same
5069         * as that of the input array.</p>
5070         *
5071         * <pre>
5072         * ArrayUtils.removeElements(null, 1, 2)      = null
5073         * ArrayUtils.removeElements([], 1, 2)        = []
5074         * ArrayUtils.removeElements([1], 2, 3)       = [1]
5075         * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5076         * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5077         * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5078         * </pre>
5079         *
5080         * @param array  the array to remove the element from, may be {@code null}
5081         * @param values the elements to be removed
5082         * @return A new array containing the existing elements except the
5083         *         earliest-encountered occurrences of the specified elements.
5084         * @since 3.0.1
5085         */
5086        public static byte[] removeElements(byte[] array, byte... values) {
5087            if (isEmpty(array) || isEmpty(values)) {
5088                return clone(array);
5089            }
5090            HashMap<Byte, MutableInt> occurrences = new HashMap<Byte, MutableInt>(values.length);
5091            for (byte v : values) {
5092                Byte boxed = Byte.valueOf(v);
5093                MutableInt count = occurrences.get(boxed);
5094                if (count == null) {
5095                    occurrences.put(boxed, new MutableInt(1));
5096                } else {
5097                    count.increment();
5098                }
5099            }
5100            HashSet<Integer> toRemove = new HashSet<Integer>();
5101            for (Map.Entry<Byte, MutableInt> e : occurrences.entrySet()) {
5102                Byte v = e.getKey();
5103                int found = 0;
5104                for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5105                    found = indexOf(array, v.byteValue(), found);
5106                    if (found < 0) {
5107                        break;
5108                    }
5109                    toRemove.add(found++);
5110                }
5111            }
5112            return removeAll(array, extractIndices(toRemove));
5113        }
5114    
5115        /**
5116         * <p>Removes the elements at the specified positions from the specified array.
5117         * All remaining elements are shifted to the left.</p>
5118         *
5119         * <p>This method returns a new array with the same elements of the input
5120         * array except those at the specified positions. The component
5121         * type of the returned array is always the same as that of the input
5122         * array.</p>
5123         *
5124         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5125         * will be thrown, because in that case no valid index can be specified.</p>
5126         *
5127         * <pre>
5128         * ArrayUtils.removeAll([1], 0)             = []
5129         * ArrayUtils.removeAll([2, 6], 0)          = [6]
5130         * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5131         * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5132         * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5133         * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5134         * </pre>
5135         *
5136         * @param array   the array to remove the element from, may not be {@code null}
5137         * @param indices the positions of the elements to be removed
5138         * @return A new array containing the existing elements except those
5139         *         at the specified positions.
5140         * @throws IndexOutOfBoundsException if any index is out of range
5141         * (index < 0 || index >= array.length), or if the array is {@code null}.
5142         * @since 3.0.1
5143         */
5144        public static short[] removeAll(short[] array, int... indices) {
5145            return (short[]) removeAll((Object) array, clone(indices));
5146        }
5147    
5148        /**
5149         * <p>Removes occurrences of specified elements, in specified quantities,
5150         * from the specified array. All subsequent elements are shifted left.
5151         * For any element-to-be-removed specified in greater quantities than
5152         * contained in the original array, no change occurs beyond the
5153         * removal of the existing matching items.</p>
5154         *
5155         * <p>This method returns a new array with the same elements of the input
5156         * array except for the earliest-encountered occurrences of the specified
5157         * elements. The component type of the returned array is always the same
5158         * as that of the input array.</p>
5159         *
5160         * <pre>
5161         * ArrayUtils.removeElements(null, 1, 2)      = null
5162         * ArrayUtils.removeElements([], 1, 2)        = []
5163         * ArrayUtils.removeElements([1], 2, 3)       = [1]
5164         * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5165         * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5166         * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5167         * </pre>
5168         *
5169         * @param array  the array to remove the element from, may be {@code null}
5170         * @param values the elements to be removed
5171         * @return A new array containing the existing elements except the
5172         *         earliest-encountered occurrences of the specified elements.
5173         * @since 3.0.1
5174         */
5175        public static short[] removeElements(short[] array, short... values) {
5176            if (isEmpty(array) || isEmpty(values)) {
5177                return clone(array);
5178            }
5179            HashMap<Short, MutableInt> occurrences = new HashMap<Short, MutableInt>(values.length);
5180            for (short v : values) {
5181                Short boxed = Short.valueOf(v);
5182                MutableInt count = occurrences.get(boxed);
5183                if (count == null) {
5184                    occurrences.put(boxed, new MutableInt(1));
5185                } else {
5186                    count.increment();
5187                }
5188            }
5189            HashSet<Integer> toRemove = new HashSet<Integer>();
5190            for (Map.Entry<Short, MutableInt> e : occurrences.entrySet()) {
5191                Short v = e.getKey();
5192                int found = 0;
5193                for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5194                    found = indexOf(array, v.shortValue(), found);
5195                    if (found < 0) {
5196                        break;
5197                    }
5198                    toRemove.add(found++);
5199                }
5200            }
5201            return removeAll(array, extractIndices(toRemove));
5202        }
5203    
5204        /**
5205         * <p>Removes the elements at the specified positions from the specified array.
5206         * All remaining elements are shifted to the left.</p>
5207         *
5208         * <p>This method returns a new array with the same elements of the input
5209         * array except those at the specified positions. The component
5210         * type of the returned array is always the same as that of the input
5211         * array.</p>
5212         *
5213         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5214         * will be thrown, because in that case no valid index can be specified.</p>
5215         *
5216         * <pre>
5217         * ArrayUtils.removeAll([1], 0)             = []
5218         * ArrayUtils.removeAll([2, 6], 0)          = [6]
5219         * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5220         * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5221         * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5222         * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5223         * </pre>
5224         *
5225         * @param array   the array to remove the element from, may not be {@code null}
5226         * @param indices the positions of the elements to be removed
5227         * @return A new array containing the existing elements except those
5228         *         at the specified positions.
5229         * @throws IndexOutOfBoundsException if any index is out of range
5230         * (index < 0 || index >= array.length), or if the array is {@code null}.
5231         * @since 3.0.1
5232         */
5233        public static int[] removeAll(int[] array, int... indices) {
5234            return (int[]) removeAll((Object) array, clone(indices));
5235        }
5236    
5237        /**
5238         * <p>Removes occurrences of specified elements, in specified quantities,
5239         * from the specified array. All subsequent elements are shifted left.
5240         * For any element-to-be-removed specified in greater quantities than
5241         * contained in the original array, no change occurs beyond the
5242         * removal of the existing matching items.</p>
5243         *
5244         * <p>This method returns a new array with the same elements of the input
5245         * array except for the earliest-encountered occurrences of the specified
5246         * elements. The component type of the returned array is always the same
5247         * as that of the input array.</p>
5248         *
5249         * <pre>
5250         * ArrayUtils.removeElements(null, 1, 2)      = null
5251         * ArrayUtils.removeElements([], 1, 2)        = []
5252         * ArrayUtils.removeElements([1], 2, 3)       = [1]
5253         * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5254         * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5255         * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5256         * </pre>
5257         *
5258         * @param array  the array to remove the element from, may be {@code null}
5259         * @param values the elements to be removed
5260         * @return A new array containing the existing elements except the
5261         *         earliest-encountered occurrences of the specified elements.
5262         * @since 3.0.1
5263         */
5264        public static int[] removeElements(int[] array, int... values) {
5265            if (isEmpty(array) || isEmpty(values)) {
5266                return clone(array);
5267            }
5268            HashMap<Integer, MutableInt> occurrences = new HashMap<Integer, MutableInt>(values.length);
5269            for (int v : values) {
5270                Integer boxed = Integer.valueOf(v);
5271                MutableInt count = occurrences.get(boxed);
5272                if (count == null) {
5273                    occurrences.put(boxed, new MutableInt(1));
5274                } else {
5275                    count.increment();
5276                }
5277            }
5278            HashSet<Integer> toRemove = new HashSet<Integer>();
5279            for (Map.Entry<Integer, MutableInt> e : occurrences.entrySet()) {
5280                Integer v = e.getKey();
5281                int found = 0;
5282                for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5283                    found = indexOf(array, v.intValue(), found);
5284                    if (found < 0) {
5285                        break;
5286                    }
5287                    toRemove.add(found++);
5288                }
5289            }
5290            return removeAll(array, extractIndices(toRemove));
5291        }
5292    
5293        /**
5294         * <p>Removes the elements at the specified positions from the specified array.
5295         * All remaining elements are shifted to the left.</p>
5296         *
5297         * <p>This method returns a new array with the same elements of the input
5298         * array except those at the specified positions. The component
5299         * type of the returned array is always the same as that of the input
5300         * array.</p>
5301         *
5302         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5303         * will be thrown, because in that case no valid index can be specified.</p>
5304         *
5305         * <pre>
5306         * ArrayUtils.removeAll([1], 0)             = []
5307         * ArrayUtils.removeAll([2, 6], 0)          = [6]
5308         * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5309         * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5310         * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5311         * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5312         * </pre>
5313         *
5314         * @param array   the array to remove the element from, may not be {@code null}
5315         * @param indices the positions of the elements to be removed
5316         * @return A new array containing the existing elements except those
5317         *         at the specified positions.
5318         * @throws IndexOutOfBoundsException if any index is out of range
5319         * (index < 0 || index >= array.length), or if the array is {@code null}.
5320         * @since 3.0.1
5321         */
5322        public static char[] removeAll(char[] array, int... indices) {
5323            return (char[]) removeAll((Object) array, clone(indices));
5324        }
5325    
5326        /**
5327         * <p>Removes occurrences of specified elements, in specified quantities,
5328         * from the specified array. All subsequent elements are shifted left.
5329         * For any element-to-be-removed specified in greater quantities than
5330         * contained in the original array, no change occurs beyond the
5331         * removal of the existing matching items.</p>
5332         *
5333         * <p>This method returns a new array with the same elements of the input
5334         * array except for the earliest-encountered occurrences of the specified
5335         * elements. The component type of the returned array is always the same
5336         * as that of the input array.</p>
5337         *
5338         * <pre>
5339         * ArrayUtils.removeElements(null, 1, 2)      = null
5340         * ArrayUtils.removeElements([], 1, 2)        = []
5341         * ArrayUtils.removeElements([1], 2, 3)       = [1]
5342         * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5343         * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5344         * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5345         * </pre>
5346         *
5347         * @param array  the array to remove the element from, may be {@code null}
5348         * @param values the elements to be removed
5349         * @return A new array containing the existing elements except the
5350         *         earliest-encountered occurrences of the specified elements.
5351         * @since 3.0.1
5352         */
5353        public static char[] removeElements(char[] array, char... values) {
5354            if (isEmpty(array) || isEmpty(values)) {
5355                return clone(array);
5356            }
5357            HashMap<Character, MutableInt> occurrences = new HashMap<Character, MutableInt>(values.length);
5358            for (char v : values) {
5359                Character boxed = Character.valueOf(v);
5360                MutableInt count = occurrences.get(boxed);
5361                if (count == null) {
5362                    occurrences.put(boxed, new MutableInt(1));
5363                } else {
5364                    count.increment();
5365                }
5366            }
5367            HashSet<Integer> toRemove = new HashSet<Integer>();
5368            for (Map.Entry<Character, MutableInt> e : occurrences.entrySet()) {
5369                Character v = e.getKey();
5370                int found = 0;
5371                for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5372                    found = indexOf(array, v.charValue(), found);
5373                    if (found < 0) {
5374                        break;
5375                    }
5376                    toRemove.add(found++);
5377                }
5378            }
5379            return removeAll(array, extractIndices(toRemove));
5380        }
5381    
5382        /**
5383         * <p>Removes the elements at the specified positions from the specified array.
5384         * All remaining elements are shifted to the left.</p>
5385         *
5386         * <p>This method returns a new array with the same elements of the input
5387         * array except those at the specified positions. The component
5388         * type of the returned array is always the same as that of the input
5389         * array.</p>
5390         *
5391         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5392         * will be thrown, because in that case no valid index can be specified.</p>
5393         *
5394         * <pre>
5395         * ArrayUtils.removeAll([1], 0)             = []
5396         * ArrayUtils.removeAll([2, 6], 0)          = [6]
5397         * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5398         * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5399         * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5400         * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5401         * </pre>
5402         *
5403         * @param array   the array to remove the element from, may not be {@code null}
5404         * @param indices the positions of the elements to be removed
5405         * @return A new array containing the existing elements except those
5406         *         at the specified positions.
5407         * @throws IndexOutOfBoundsException if any index is out of range
5408         * (index < 0 || index >= array.length), or if the array is {@code null}.
5409         * @since 3.0.1
5410         */
5411        public static long[] removeAll(long[] array, int... indices) {
5412            return (long[]) removeAll((Object) array, clone(indices));
5413        }
5414    
5415        /**
5416         * <p>Removes occurrences of specified elements, in specified quantities,
5417         * from the specified array. All subsequent elements are shifted left.
5418         * For any element-to-be-removed specified in greater quantities than
5419         * contained in the original array, no change occurs beyond the
5420         * removal of the existing matching items.</p>
5421         *
5422         * <p>This method returns a new array with the same elements of the input
5423         * array except for the earliest-encountered occurrences of the specified
5424         * elements. The component type of the returned array is always the same
5425         * as that of the input array.</p>
5426         *
5427         * <pre>
5428         * ArrayUtils.removeElements(null, 1, 2)      = null
5429         * ArrayUtils.removeElements([], 1, 2)        = []
5430         * ArrayUtils.removeElements([1], 2, 3)       = [1]
5431         * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5432         * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5433         * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5434         * </pre>
5435         *
5436         * @param array  the array to remove the element from, may be {@code null}
5437         * @param values the elements to be removed
5438         * @return A new array containing the existing elements except the
5439         *         earliest-encountered occurrences of the specified elements.
5440         * @since 3.0.1
5441         */
5442        public static long[] removeElements(long[] array, long... values) {
5443            if (isEmpty(array) || isEmpty(values)) {
5444                return clone(array);
5445            }
5446            HashMap<Long, MutableInt> occurrences = new HashMap<Long, MutableInt>(values.length);
5447            for (long v : values) {
5448                Long boxed = Long.valueOf(v);
5449                MutableInt count = occurrences.get(boxed);
5450                if (count == null) {
5451                    occurrences.put(boxed, new MutableInt(1));
5452                } else {
5453                    count.increment();
5454                }
5455            }
5456            HashSet<Integer> toRemove = new HashSet<Integer>();
5457            for (Map.Entry<Long, MutableInt> e : occurrences.entrySet()) {
5458                Long v = e.getKey();
5459                int found = 0;
5460                for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5461                    found = indexOf(array, v.longValue(), found);
5462                    if (found < 0) {
5463                        break;
5464                    }
5465                    toRemove.add(found++);
5466                }
5467            }
5468            return removeAll(array, extractIndices(toRemove));
5469        }
5470    
5471        /**
5472         * <p>Removes the elements at the specified positions from the specified array.
5473         * All remaining elements are shifted to the left.</p>
5474         *
5475         * <p>This method returns a new array with the same elements of the input
5476         * array except those at the specified positions. The component
5477         * type of the returned array is always the same as that of the input
5478         * array.</p>
5479         *
5480         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5481         * will be thrown, because in that case no valid index can be specified.</p>
5482         *
5483         * <pre>
5484         * ArrayUtils.removeAll([1], 0)             = []
5485         * ArrayUtils.removeAll([2, 6], 0)          = [6]
5486         * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5487         * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5488         * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5489         * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5490         * </pre>
5491         *
5492         * @param array   the array to remove the element from, may not be {@code null}
5493         * @param indices the positions of the elements to be removed
5494         * @return A new array containing the existing elements except those
5495         *         at the specified positions.
5496         * @throws IndexOutOfBoundsException if any index is out of range
5497         * (index < 0 || index >= array.length), or if the array is {@code null}.
5498         * @since 3.0.1
5499         */
5500        public static float[] removeAll(float[] array, int... indices) {
5501            return (float[]) removeAll((Object) array, clone(indices));
5502        }
5503    
5504        /**
5505         * <p>Removes occurrences of specified elements, in specified quantities,
5506         * from the specified array. All subsequent elements are shifted left.
5507         * For any element-to-be-removed specified in greater quantities than
5508         * contained in the original array, no change occurs beyond the
5509         * removal of the existing matching items.</p>
5510         *
5511         * <p>This method returns a new array with the same elements of the input
5512         * array except for the earliest-encountered occurrences of the specified
5513         * elements. The component type of the returned array is always the same
5514         * as that of the input array.</p>
5515         *
5516         * <pre>
5517         * ArrayUtils.removeElements(null, 1, 2)      = null
5518         * ArrayUtils.removeElements([], 1, 2)        = []
5519         * ArrayUtils.removeElements([1], 2, 3)       = [1]
5520         * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5521         * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5522         * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5523         * </pre>
5524         *
5525         * @param array  the array to remove the element from, may be {@code null}
5526         * @param values the elements to be removed
5527         * @return A new array containing the existing elements except the
5528         *         earliest-encountered occurrences of the specified elements.
5529         * @since 3.0.1
5530         */
5531        public static float[] removeElements(float[] array, float... values) {
5532            if (isEmpty(array) || isEmpty(values)) {
5533                return clone(array);
5534            }
5535            HashMap<Float, MutableInt> occurrences = new HashMap<Float, MutableInt>(values.length);
5536            for (float v : values) {
5537                Float boxed = Float.valueOf(v);
5538                MutableInt count = occurrences.get(boxed);
5539                if (count == null) {
5540                    occurrences.put(boxed, new MutableInt(1));
5541                } else {
5542                    count.increment();
5543                }
5544            }
5545            HashSet<Integer> toRemove = new HashSet<Integer>();
5546            for (Map.Entry<Float, MutableInt> e : occurrences.entrySet()) {
5547                Float v = e.getKey();
5548                int found = 0;
5549                for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5550                    found = indexOf(array, v.floatValue(), found);
5551                    if (found < 0) {
5552                        break;
5553                    }
5554                    toRemove.add(found++);
5555                }
5556            }
5557            return removeAll(array, extractIndices(toRemove));
5558        }
5559    
5560        /**
5561         * <p>Removes the elements at the specified positions from the specified array.
5562         * All remaining elements are shifted to the left.</p>
5563         *
5564         * <p>This method returns a new array with the same elements of the input
5565         * array except those at the specified positions. The component
5566         * type of the returned array is always the same as that of the input
5567         * array.</p>
5568         *
5569         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5570         * will be thrown, because in that case no valid index can be specified.</p>
5571         *
5572         * <pre>
5573         * ArrayUtils.removeAll([1], 0)             = []
5574         * ArrayUtils.removeAll([2, 6], 0)          = [6]
5575         * ArrayUtils.removeAll([2, 6], 0, 1)       = []
5576         * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
5577         * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
5578         * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
5579         * </pre>
5580         *
5581         * @param array   the array to remove the element from, may not be {@code null}
5582         * @param indices the positions of the elements to be removed
5583         * @return A new array containing the existing elements except those
5584         *         at the specified positions.
5585         * @throws IndexOutOfBoundsException if any index is out of range
5586         * (index < 0 || index >= array.length), or if the array is {@code null}.
5587         * @since 3.0.1
5588         */
5589        public static double[] removeAll(double[] array, int... indices) {
5590            return (double[]) removeAll((Object) array, clone(indices));
5591        }
5592    
5593        /**
5594         * <p>Removes occurrences of specified elements, in specified quantities,
5595         * from the specified array. All subsequent elements are shifted left.
5596         * For any element-to-be-removed specified in greater quantities than
5597         * contained in the original array, no change occurs beyond the
5598         * removal of the existing matching items.</p>
5599         *
5600         * <p>This method returns a new array with the same elements of the input
5601         * array except for the earliest-encountered occurrences of the specified
5602         * elements. The component type of the returned array is always the same
5603         * as that of the input array.</p>
5604         *
5605         * <pre>
5606         * ArrayUtils.removeElements(null, 1, 2)      = null
5607         * ArrayUtils.removeElements([], 1, 2)        = []
5608         * ArrayUtils.removeElements([1], 2, 3)       = [1]
5609         * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
5610         * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
5611         * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
5612         * </pre>
5613         *
5614         * @param array  the array to remove the element from, may be {@code null}
5615         * @param values the elements to be removed
5616         * @return A new array containing the existing elements except the
5617         *         earliest-encountered occurrences of the specified elements.
5618         * @since 3.0.1
5619         */
5620        public static double[] removeElements(double[] array, double... values) {
5621            if (isEmpty(array) || isEmpty(values)) {
5622                return clone(array);
5623            }
5624            HashMap<Double, MutableInt> occurrences = new HashMap<Double, MutableInt>(values.length);
5625            for (double v : values) {
5626                Double boxed = Double.valueOf(v);
5627                MutableInt count = occurrences.get(boxed);
5628                if (count == null) {
5629                    occurrences.put(boxed, new MutableInt(1));
5630                } else {
5631                    count.increment();
5632                }
5633            }
5634            HashSet<Integer> toRemove = new HashSet<Integer>();
5635            for (Map.Entry<Double, MutableInt> e : occurrences.entrySet()) {
5636                Double v = e.getKey();
5637                int found = 0;
5638                for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5639                    found = indexOf(array, v.doubleValue(), found);
5640                    if (found < 0) {
5641                        break;
5642                    }
5643                    toRemove.add(found++);
5644                }
5645            }
5646            return removeAll(array, extractIndices(toRemove));
5647        }
5648    
5649        /**
5650         * <p>Removes the elements at the specified positions from the specified array.
5651         * All remaining elements are shifted to the left.</p>
5652         *
5653         * <p>This method returns a new array with the same elements of the input
5654         * array except those at the specified positions. The component
5655         * type of the returned array is always the same as that of the input
5656         * array.</p>
5657         *
5658         * <p>If the input array is {@code null}, an IndexOutOfBoundsException
5659         * will be thrown, because in that case no valid index can be specified.</p>
5660         *
5661         * <pre>
5662         * ArrayUtils.removeAll([true, false, true], 0, 2) = [false]
5663         * ArrayUtils.removeAll([true, false, true], 1, 2) = [true]
5664         * </pre>
5665         *
5666         * @param array   the array to remove the element from, may not be {@code null}
5667         * @param indices the positions of the elements to be removed
5668         * @return A new array containing the existing elements except those
5669         *         at the specified positions.
5670         * @throws IndexOutOfBoundsException if any index is out of range
5671         * (index < 0 || index >= array.length), or if the array is {@code null}.
5672         * @since 3.0.1
5673         */
5674        public static boolean[] removeAll(boolean[] array, int... indices) {
5675            return (boolean[]) removeAll((Object) array, clone(indices));
5676        }
5677    
5678        /**
5679         * <p>Removes occurrences of specified elements, in specified quantities,
5680         * from the specified array. All subsequent elements are shifted left.
5681         * For any element-to-be-removed specified in greater quantities than
5682         * contained in the original array, no change occurs beyond the
5683         * removal of the existing matching items.</p>
5684         *
5685         * <p>This method returns a new array with the same elements of the input
5686         * array except for the earliest-encountered occurrences of the specified
5687         * elements. The component type of the returned array is always the same
5688         * as that of the input array.</p>
5689         *
5690         * <pre>
5691         * ArrayUtils.removeElements(null, true, false)               = null
5692         * ArrayUtils.removeElements([], true, false)                 = []
5693         * ArrayUtils.removeElements([true], false, false)            = [true]
5694         * ArrayUtils.removeElements([true, false], true, true)       = [false]
5695         * ArrayUtils.removeElements([true, false, true], true)       = [false, true]
5696         * ArrayUtils.removeElements([true, false, true], true, true) = [false]
5697         * </pre>
5698         *
5699         * @param array  the array to remove the element from, may be {@code null}
5700         * @param values the elements to be removed
5701         * @return A new array containing the existing elements except the
5702         *         earliest-encountered occurrences of the specified elements.
5703         * @since 3.0.1
5704         */
5705        public static boolean[] removeElements(boolean[] array, boolean... values) {
5706            if (isEmpty(array) || isEmpty(values)) {
5707                return clone(array);
5708            }
5709            HashMap<Boolean, MutableInt> occurrences = new HashMap<Boolean, MutableInt>(values.length);
5710            for (boolean v : values) {
5711                Boolean boxed = Boolean.valueOf(v);
5712                MutableInt count = occurrences.get(boxed);
5713                if (count == null) {
5714                    occurrences.put(boxed, new MutableInt(1));
5715                } else {
5716                    count.increment();
5717                }
5718            }
5719            HashSet<Integer> toRemove = new HashSet<Integer>();
5720            for (Map.Entry<Boolean, MutableInt> e : occurrences.entrySet()) {
5721                Boolean v = e.getKey();
5722                int found = 0;
5723                for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
5724                    found = indexOf(array, v.booleanValue(), found);
5725                    if (found < 0) {
5726                        break;
5727                    }
5728                    toRemove.add(found++);
5729                }
5730            }
5731            return removeAll(array, extractIndices(toRemove));
5732        }
5733    
5734        /**
5735         * Removes multiple array elements specified by index.
5736         * @param array source
5737         * @param indices to remove, WILL BE SORTED--so only clones of user-owned arrays!
5738         * @return new array of same type minus elements specified by unique values of {@code indices}
5739         * @since 3.0.1
5740         */
5741        private static Object removeAll(Object array, int... indices) {
5742            int length = getLength(array);
5743            int diff = 0;
5744    
5745            if (isNotEmpty(indices)) {
5746                Arrays.sort(indices);
5747    
5748                int i = indices.length;
5749                int prevIndex = length;
5750                while (--i >= 0) {
5751                    int index = indices[i];
5752                    if (index < 0 || index >= length) {
5753                        throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length);
5754                    }
5755                    if (index >= prevIndex) {
5756                        continue;
5757                    }
5758                    diff++;
5759                    prevIndex = index;
5760                }
5761            }
5762            Object result = Array.newInstance(array.getClass().getComponentType(), length - diff);
5763            if (diff < length) {
5764                int end = length;
5765                int dest = length - diff;
5766                for (int i = indices.length - 1; i >= 0; i--) {
5767                    int index = indices[i];
5768                    if (end - index > 1) {
5769                        int cp = end - index - 1;
5770                        dest -= cp;
5771                        System.arraycopy(array, index + 1, result, dest, cp);
5772                    }
5773                    end = index;
5774                }
5775                if (end > 0) {
5776                    System.arraycopy(array, 0, result, 0, end);
5777                }
5778            }
5779            return result;
5780        }
5781    
5782        /**
5783         * Extract a set of Integer indices into an int[].
5784         * @param coll {@code HashSet} of {@code Integer}
5785         * @return int[]
5786         * @since 3.0.1
5787         */
5788        private static int[] extractIndices(HashSet<Integer> coll) {
5789            int[] result = new int[coll.size()];
5790            int i = 0;
5791            for (Integer index : coll) {
5792                result[i++] = index.intValue();
5793            }
5794            return result;
5795        }
5796    }