1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package java.util;
19
20import java.io.Serializable;
21import java.lang.reflect.Array;
22
23/**
24 * {@code Arrays} contains static methods which operate on arrays.
25 *
26 * @since 1.2
27 */
28public class Arrays {
29    private static class ArrayList<E> extends AbstractList<E> implements
30            List<E>, Serializable, RandomAccess {
31
32        private static final long serialVersionUID = -2764017481108945198L;
33
34        private final E[] a;
35
36        ArrayList(E[] storage) {
37            if (storage == null) {
38                throw new NullPointerException("storage == null");
39            }
40            a = storage;
41        }
42
43        @Override
44        public boolean contains(Object object) {
45            if (object != null) {
46                for (E element : a) {
47                    if (object.equals(element)) {
48                        return true;
49                    }
50                }
51            } else {
52                for (E element : a) {
53                    if (element == null) {
54                        return true;
55                    }
56                }
57            }
58            return false;
59        }
60
61        @Override
62        public E get(int location) {
63            try {
64                return a[location];
65            } catch (ArrayIndexOutOfBoundsException e) {
66                throw java.util.ArrayList.throwIndexOutOfBoundsException(location, a.length);
67            }
68        }
69
70        @Override
71        public int indexOf(Object object) {
72            if (object != null) {
73                for (int i = 0; i < a.length; i++) {
74                    if (object.equals(a[i])) {
75                        return i;
76                    }
77                }
78            } else {
79                for (int i = 0; i < a.length; i++) {
80                    if (a[i] == null) {
81                        return i;
82                    }
83                }
84            }
85            return -1;
86        }
87
88        @Override
89        public int lastIndexOf(Object object) {
90            if (object != null) {
91                for (int i = a.length - 1; i >= 0; i--) {
92                    if (object.equals(a[i])) {
93                        return i;
94                    }
95                }
96            } else {
97                for (int i = a.length - 1; i >= 0; i--) {
98                    if (a[i] == null) {
99                        return i;
100                    }
101                }
102            }
103            return -1;
104        }
105
106        @Override
107        public E set(int location, E object) {
108            E result = a[location];
109            a[location] = object;
110            return result;
111        }
112
113        @Override
114        public int size() {
115            return a.length;
116        }
117
118        @Override
119        public Object[] toArray() {
120            return a.clone();
121        }
122
123        @Override
124        @SuppressWarnings({"unchecked", "SuspiciousSystemArraycopy"})
125        public <T> T[] toArray(T[] contents) {
126            int size = size();
127            if (size > contents.length) {
128                Class<?> ct = contents.getClass().getComponentType();
129                contents = (T[]) Array.newInstance(ct, size);
130            }
131            System.arraycopy(a, 0, contents, 0, size);
132            if (size < contents.length) {
133                contents[size] = null;
134            }
135            return contents;
136        }
137    }
138
139    private Arrays() {
140        /* empty */
141    }
142
143    /**
144     * Returns a {@code List} of the objects in the specified array. The size of the
145     * {@code List} cannot be modified, i.e. adding and removing are unsupported, but
146     * the elements can be set. Setting an element modifies the underlying
147     * array.
148     *
149     * @param array
150     *            the array.
151     * @return a {@code List} of the elements of the specified array.
152     */
153    @SafeVarargs
154    public static <T> List<T> asList(T... array) {
155        return new ArrayList<T>(array);
156    }
157
158    /**
159     * Performs a binary search for {@code value} in the ascending sorted array {@code array}.
160     * Searching in an unsorted array has an undefined result. It's also undefined which element
161     * is found if there are multiple occurrences of the same element.
162     *
163     * @param array the sorted array to search.
164     * @param value the element to find.
165     * @return the non-negative index of the element, or a negative index which
166     *         is {@code -index - 1} where the element would be inserted.
167     */
168    public static int binarySearch(byte[] array, byte value) {
169        return binarySearch(array, 0, array.length, value);
170    }
171
172    /**
173     * Performs a binary search for {@code value} in the ascending sorted array {@code array},
174     * in the range specified by fromIndex (inclusive) and toIndex (exclusive).
175     * Searching in an unsorted array has an undefined result. It's also undefined which element
176     * is found if there are multiple occurrences of the same element.
177     *
178     * @param array the sorted array to search.
179     * @param startIndex the inclusive start index.
180     * @param endIndex the exclusive start index.
181     * @param value the element to find.
182     * @return the non-negative index of the element, or a negative index which
183     *         is {@code -index - 1} where the element would be inserted.
184     * @throws IllegalArgumentException if {@code startIndex > endIndex}
185     * @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
186     * @since 1.6
187     */
188    public static int binarySearch(byte[] array, int startIndex, int endIndex, byte value) {
189        checkBinarySearchBounds(startIndex, endIndex, array.length);
190        int lo = startIndex;
191        int hi = endIndex - 1;
192
193        while (lo <= hi) {
194            int mid = (lo + hi) >>> 1;
195            byte midVal = array[mid];
196
197            if (midVal < value) {
198                lo = mid + 1;
199            } else if (midVal > value) {
200                hi = mid - 1;
201            } else {
202                return mid;  // value found
203            }
204        }
205        return ~lo;  // value not present
206    }
207
208    /**
209     * Performs a binary search for {@code value} in the ascending sorted array {@code array}.
210     * Searching in an unsorted array has an undefined result. It's also undefined which element
211     * is found if there are multiple occurrences of the same element.
212     *
213     * @param array the sorted array to search.
214     * @param value the element to find.
215     * @return the non-negative index of the element, or a negative index which
216     *         is {@code -index - 1} where the element would be inserted.
217     */
218    public static int binarySearch(char[] array, char value) {
219        return binarySearch(array, 0, array.length, value);
220    }
221
222    /**
223     * Performs a binary search for {@code value} in the ascending sorted array {@code array},
224     * in the range specified by fromIndex (inclusive) and toIndex (exclusive).
225     * Searching in an unsorted array has an undefined result. It's also undefined which element
226     * is found if there are multiple occurrences of the same element.
227     *
228     * @param array the sorted array to search.
229     * @param startIndex the inclusive start index.
230     * @param endIndex the exclusive start index.
231     * @param value the element to find.
232     * @return the non-negative index of the element, or a negative index which
233     *         is {@code -index - 1} where the element would be inserted.
234     * @throws IllegalArgumentException if {@code startIndex > endIndex}
235     * @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
236     * @since 1.6
237     */
238    public static int binarySearch(char[] array, int startIndex, int endIndex, char value) {
239        checkBinarySearchBounds(startIndex, endIndex, array.length);
240        int lo = startIndex;
241        int hi = endIndex - 1;
242
243        while (lo <= hi) {
244            int mid = (lo + hi) >>> 1;
245            char midVal = array[mid];
246
247            if (midVal < value) {
248                lo = mid + 1;
249            } else if (midVal > value) {
250                hi = mid - 1;
251            } else {
252                return mid;  // value found
253            }
254        }
255        return ~lo;  // value not present
256    }
257
258    /**
259     * Performs a binary search for {@code value} in the ascending sorted array {@code array}.
260     * Searching in an unsorted array has an undefined result. It's also undefined which element
261     * is found if there are multiple occurrences of the same element.
262     *
263     * @param array the sorted array to search.
264     * @param value the element to find.
265     * @return the non-negative index of the element, or a negative index which
266     *         is {@code -index - 1} where the element would be inserted.
267     */
268    public static int binarySearch(double[] array, double value) {
269        return binarySearch(array, 0, array.length, value);
270    }
271
272    /**
273     * Performs a binary search for {@code value} in the ascending sorted array {@code array},
274     * in the range specified by fromIndex (inclusive) and toIndex (exclusive).
275     * Searching in an unsorted array has an undefined result. It's also undefined which element
276     * is found if there are multiple occurrences of the same element.
277     *
278     * @param array the sorted array to search.
279     * @param startIndex the inclusive start index.
280     * @param endIndex the exclusive start index.
281     * @param value the element to find.
282     * @return the non-negative index of the element, or a negative index which
283     *         is {@code -index - 1} where the element would be inserted.
284     * @throws IllegalArgumentException if {@code startIndex > endIndex}
285     * @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
286     * @since 1.6
287     */
288    public static int binarySearch(double[] array, int startIndex, int endIndex, double value) {
289        checkBinarySearchBounds(startIndex, endIndex, array.length);
290        int lo = startIndex;
291        int hi = endIndex - 1;
292
293        while (lo <= hi) {
294            int mid = (lo + hi) >>> 1;
295            double midVal = array[mid];
296
297            if (midVal < value) {
298                lo = mid + 1;
299            } else if (midVal > value) {
300                hi = mid - 1;
301            } else if (midVal != 0 && midVal == value) {
302                return mid;  // value found
303            } else { // Either midVal and value are == 0 or at least one is NaN
304                long midValBits = Double.doubleToLongBits(midVal);
305                long valueBits  = Double.doubleToLongBits(value);
306
307                if (midValBits < valueBits) {
308                    lo = mid + 1; // (-0.0, 0.0) or (not NaN, NaN); midVal < val
309                } else if (midValBits > valueBits) {
310                    hi = mid - 1; // (0.0, -0.0) or (NaN, not NaN); midVal > val
311                } else {
312                    return mid; // bit patterns are equal; value found
313                }
314            }
315        }
316        return ~lo;  // value not present
317    }
318
319    /**
320     * Performs a binary search for {@code value} in the ascending sorted array {@code array}.
321     * Searching in an unsorted array has an undefined result. It's also undefined which element
322     * is found if there are multiple occurrences of the same element.
323     *
324     * @param array the sorted array to search.
325     * @param value the element to find.
326     * @return the non-negative index of the element, or a negative index which
327     *         is {@code -index - 1} where the element would be inserted.
328     */
329    public static int binarySearch(float[] array, float value) {
330        return binarySearch(array, 0, array.length, value);
331    }
332
333    /**
334     * Performs a binary search for {@code value} in the ascending sorted array {@code array},
335     * in the range specified by fromIndex (inclusive) and toIndex (exclusive).
336     * Searching in an unsorted array has an undefined result. It's also undefined which element
337     * is found if there are multiple occurrences of the same element.
338     *
339     * @param array the sorted array to search.
340     * @param startIndex the inclusive start index.
341     * @param endIndex the exclusive start index.
342     * @param value the element to find.
343     * @return the non-negative index of the element, or a negative index which
344     *         is {@code -index - 1} where the element would be inserted.
345     * @throws IllegalArgumentException if {@code startIndex > endIndex}
346     * @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
347     * @since 1.6
348     */
349    public static int binarySearch(float[] array, int startIndex, int endIndex, float value) {
350        checkBinarySearchBounds(startIndex, endIndex, array.length);
351        int lo = startIndex;
352        int hi = endIndex - 1;
353
354        while (lo <= hi) {
355            int mid = (lo + hi) >>> 1;
356            float midVal = array[mid];
357
358            if (midVal < value) {
359                lo = mid + 1;
360            } else if (midVal > value) {
361                hi = mid - 1;
362            } else if (midVal != 0 && midVal == value) {
363                return mid;  // value found
364            } else { // Either midVal and value are == 0 or at least one is NaN
365                int midValBits = Float.floatToIntBits(midVal);
366                int valueBits  = Float.floatToIntBits(value);
367
368                if (midValBits < valueBits) {
369                    lo = mid + 1; // (-0.0, 0.0) or (not NaN, NaN); midVal < val
370                } else if (midValBits > valueBits) {
371                    hi = mid - 1; // (0.0, -0.0) or (NaN, not NaN); midVal > val
372                } else {
373                    return mid; // bit patterns are equal; value found
374                }
375            }
376        }
377        return ~lo;  // value not present
378    }
379
380    /**
381     * Performs a binary search for {@code value} in the ascending sorted array {@code array}.
382     * Searching in an unsorted array has an undefined result. It's also undefined which element
383     * is found if there are multiple occurrences of the same element.
384     *
385     * @param array the sorted array to search.
386     * @param value the element to find.
387     * @return the non-negative index of the element, or a negative index which
388     *         is {@code -index - 1} where the element would be inserted.
389     */
390    public static int binarySearch(int[] array, int value) {
391        return binarySearch(array, 0, array.length, value);
392    }
393
394    /**
395     * Performs a binary search for {@code value} in the ascending sorted array {@code array},
396     * in the range specified by fromIndex (inclusive) and toIndex (exclusive).
397     * Searching in an unsorted array has an undefined result. It's also undefined which element
398     * is found if there are multiple occurrences of the same element.
399     *
400     * @param array the sorted array to search.
401     * @param startIndex the inclusive start index.
402     * @param endIndex the exclusive start index.
403     * @param value the element to find.
404     * @return the non-negative index of the element, or a negative index which
405     *         is {@code -index - 1} where the element would be inserted.
406     * @throws IllegalArgumentException if {@code startIndex > endIndex}
407     * @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
408     * @since 1.6
409     */
410    public static int binarySearch(int[] array, int startIndex, int endIndex, int value) {
411        checkBinarySearchBounds(startIndex, endIndex, array.length);
412        int lo = startIndex;
413        int hi = endIndex - 1;
414
415        while (lo <= hi) {
416            int mid = (lo + hi) >>> 1;
417            int midVal = array[mid];
418
419            if (midVal < value) {
420                lo = mid + 1;
421            } else if (midVal > value) {
422                hi = mid - 1;
423            } else {
424                return mid;  // value found
425            }
426        }
427        return ~lo;  // value not present
428    }
429
430    /**
431     * Performs a binary search for {@code value} in the ascending sorted array {@code array}.
432     * Searching in an unsorted array has an undefined result. It's also undefined which element
433     * is found if there are multiple occurrences of the same element.
434     *
435     * @param array the sorted array to search.
436     * @param value the element to find.
437     * @return the non-negative index of the element, or a negative index which
438     *         is {@code -index - 1} where the element would be inserted.
439     */
440    public static int binarySearch(long[] array, long value) {
441        return binarySearch(array, 0, array.length, value);
442    }
443
444    /**
445     * Performs a binary search for {@code value} in the ascending sorted array {@code array},
446     * in the range specified by fromIndex (inclusive) and toIndex (exclusive).
447     * Searching in an unsorted array has an undefined result. It's also undefined which element
448     * is found if there are multiple occurrences of the same element.
449     *
450     * @param array the sorted array to search.
451     * @param startIndex the inclusive start index.
452     * @param endIndex the exclusive start index.
453     * @param value the element to find.
454     * @return the non-negative index of the element, or a negative index which
455     *         is {@code -index - 1} where the element would be inserted.
456     * @throws IllegalArgumentException if {@code startIndex > endIndex}
457     * @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
458     * @since 1.6
459     */
460    public static int binarySearch(long[] array, int startIndex, int endIndex, long value) {
461        checkBinarySearchBounds(startIndex, endIndex, array.length);
462        int lo = startIndex;
463        int hi = endIndex - 1;
464
465        while (lo <= hi) {
466            int mid = (lo + hi) >>> 1;
467            long midVal = array[mid];
468
469            if (midVal < value) {
470                lo = mid + 1;
471            } else if (midVal > value) {
472                hi = mid - 1;
473            } else {
474                return mid;  // value found
475            }
476         }
477         return ~lo;  // value not present
478    }
479
480    /**
481     * Performs a binary search for {@code value} in the ascending sorted array {@code array}.
482     * Searching in an unsorted array has an undefined result. It's also undefined which element
483     * is found if there are multiple occurrences of the same element.
484     *
485     * @param array the sorted array to search.
486     * @param value the element to find.
487     * @return the non-negative index of the element, or a negative index which
488     *         is {@code -index - 1} where the element would be inserted.
489     * @throws ClassCastException
490     *         if an element in the array or the search element does not
491     *         implement {@code Comparable}, or cannot be compared to each other.
492     */
493    public static int binarySearch(Object[] array, Object value) {
494        return binarySearch(array, 0, array.length, value);
495    }
496
497    /**
498     * Performs a binary search for {@code value} in the ascending sorted array {@code array},
499     * in the range specified by fromIndex (inclusive) and toIndex (exclusive).
500     * Searching in an unsorted array has an undefined result. It's also undefined which element
501     * is found if there are multiple occurrences of the same element.
502     *
503     * @param array the sorted array to search.
504     * @param startIndex the inclusive start index.
505     * @param endIndex the exclusive start index.
506     * @param value the element to find.
507     * @return the non-negative index of the element, or a negative index which
508     *         is {@code -index - 1} where the element would be inserted.
509     * @throws ClassCastException
510     *         if an element in the array or the search element does not
511     *         implement {@code Comparable}, or cannot be compared to each other.
512     * @throws IllegalArgumentException if {@code startIndex > endIndex}
513     * @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
514     * @since 1.6
515     */
516    public static int binarySearch(Object[] array, int startIndex, int endIndex, Object value) {
517        checkBinarySearchBounds(startIndex, endIndex, array.length);
518        int lo = startIndex;
519        int hi = endIndex - 1;
520
521        while (lo <= hi) {
522            int mid = (lo + hi) >>> 1;
523            @SuppressWarnings("unchecked")
524            int midValCmp = ((Comparable) array[mid]).compareTo(value);
525
526            if (midValCmp < 0) {
527                lo = mid + 1;
528            } else if (midValCmp > 0) {
529                hi = mid - 1;
530            } else {
531                return mid;  // value found
532            }
533        }
534        return ~lo;  // value not present
535    }
536
537    /**
538     * Performs a binary search for {@code value} in the ascending sorted array {@code array},
539     * using {@code comparator} to compare elements.
540     * Searching in an unsorted array has an undefined result. It's also undefined which element
541     * is found if there are multiple occurrences of the same element.
542     *
543     * @param array the sorted array to search.
544     * @param value the element to find.
545     * @param comparator the {@code Comparator} used to compare the elements.
546     * @return the non-negative index of the element, or a negative index which
547     *         is {@code -index - 1} where the element would be inserted.
548     * @throws ClassCastException
549     *         if an element in the array or the search element does not
550     *         implement {@code Comparable}, or cannot be compared to each other.
551     */
552    public static <T> int binarySearch(T[] array, T value, Comparator<? super T> comparator) {
553        return binarySearch(array, 0, array.length, value, comparator);
554    }
555
556    /**
557     * Performs a binary search for {@code value} in the ascending sorted array {@code array},
558     * in the range specified by fromIndex (inclusive) and toIndex (exclusive),
559     * using {@code comparator} to compare elements.
560     * Searching in an unsorted array has an undefined result. It's also undefined which element
561     * is found if there are multiple occurrences of the same element.
562     *
563     * @param array the sorted array to search.
564     * @param startIndex the inclusive start index.
565     * @param endIndex the exclusive start index.
566     * @param value the element to find.
567     * @param comparator the {@code Comparator} used to compare the elements.
568     * @return the non-negative index of the element, or a negative index which
569     *         is {@code -index - 1} where the element would be inserted.
570     * @throws ClassCastException
571     *         if an element in the array or the search element does not
572     *         implement {@code Comparable}, or cannot be compared to each other.
573     * @throws IllegalArgumentException if {@code startIndex > endIndex}
574     * @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
575     * @since 1.6
576     */
577    public static <T> int binarySearch(T[] array, int startIndex, int endIndex, T value,
578            Comparator<? super T> comparator) {
579        if (comparator == null) {
580            return binarySearch(array, startIndex, endIndex, value);
581        }
582
583        checkBinarySearchBounds(startIndex, endIndex, array.length);
584        int lo = startIndex;
585        int hi = endIndex - 1;
586
587        while (lo <= hi) {
588            int mid = (lo + hi) >>> 1;
589            int midValCmp = comparator.compare(array[mid], value);
590
591            if (midValCmp < 0) {
592                lo = mid + 1;
593            } else if (midValCmp > 0) {
594                hi = mid - 1;
595            } else {
596                return mid;  // value found
597            }
598        }
599        return ~lo;  // value not present
600    }
601
602    /**
603     * Performs a binary search for {@code value} in the ascending sorted array {@code array}.
604     * Searching in an unsorted array has an undefined result. It's also undefined which element
605     * is found if there are multiple occurrences of the same element.
606     *
607     * @param array the sorted array to search.
608     * @param value the element to find.
609     * @return the non-negative index of the element, or a negative index which
610     *         is {@code -index - 1} where the element would be inserted.
611     */
612    public static int binarySearch(short[] array, short value) {
613        return binarySearch(array, 0, array.length, value);
614    }
615
616    /**
617     * Performs a binary search for {@code value} in the ascending sorted array {@code array},
618     * in the range specified by fromIndex (inclusive) and toIndex (exclusive).
619     * Searching in an unsorted array has an undefined result. It's also undefined which element
620     * is found if there are multiple occurrences of the same element.
621     *
622     * @param array the sorted array to search.
623     * @param startIndex the inclusive start index.
624     * @param endIndex the exclusive start index.
625     * @param value the element to find.
626     * @return the non-negative index of the element, or a negative index which
627     *         is {@code -index - 1} where the element would be inserted.
628     * @throws IllegalArgumentException if {@code startIndex > endIndex}
629     * @throws ArrayIndexOutOfBoundsException if {@code startIndex < 0 || endIndex > array.length}
630     * @since 1.6
631     */
632    public static int binarySearch(short[] array, int startIndex, int endIndex, short value) {
633        checkBinarySearchBounds(startIndex, endIndex, array.length);
634        int lo = startIndex;
635        int hi = endIndex - 1;
636
637        while (lo <= hi) {
638            int mid = (lo + hi) >>> 1;
639            short midVal = array[mid];
640
641            if (midVal < value) {
642                lo = mid + 1;
643            } else if (midVal > value) {
644                hi = mid - 1;
645            } else {
646                return mid;  // value found
647            }
648        }
649        return ~lo;  // value not present
650    }
651
652    private static void checkBinarySearchBounds(int startIndex, int endIndex, int length) {
653        if (startIndex > endIndex) {
654            throw new IllegalArgumentException();
655        }
656        if (startIndex < 0 || endIndex > length) {
657            throw new ArrayIndexOutOfBoundsException();
658        }
659    }
660
661    /**
662     * Fills the specified array with the specified element.
663     *
664     * @param array
665     *            the {@code byte} array to fill.
666     * @param value
667     *            the {@code byte} element.
668     */
669    public static void fill(byte[] array, byte value) {
670        for (int i = 0; i < array.length; i++) {
671            array[i] = value;
672        }
673    }
674
675    /**
676     * Fills the specified range in the array with the specified element.
677     *
678     * @param array
679     *            the {@code byte} array to fill.
680     * @param start
681     *            the first index to fill.
682     * @param end
683     *            the last + 1 index to fill.
684     * @param value
685     *            the {@code byte} element.
686     * @throws IllegalArgumentException
687     *                if {@code start > end}.
688     * @throws ArrayIndexOutOfBoundsException
689     *                if {@code start < 0} or {@code end > array.length}.
690     */
691    public static void fill(byte[] array, int start, int end, byte value) {
692        Arrays.checkStartAndEnd(array.length, start, end);
693        for (int i = start; i < end; i++) {
694            array[i] = value;
695        }
696    }
697
698    /**
699     * Fills the specified array with the specified element.
700     *
701     * @param array
702     *            the {@code short} array to fill.
703     * @param value
704     *            the {@code short} element.
705     */
706    public static void fill(short[] array, short value) {
707        for (int i = 0; i < array.length; i++) {
708            array[i] = value;
709        }
710    }
711
712    /**
713     * Fills the specified range in the array with the specified element.
714     *
715     * @param array
716     *            the {@code short} array to fill.
717     * @param start
718     *            the first index to fill.
719     * @param end
720     *            the last + 1 index to fill.
721     * @param value
722     *            the {@code short} element.
723     * @throws IllegalArgumentException
724     *                if {@code start > end}.
725     * @throws ArrayIndexOutOfBoundsException
726     *                if {@code start < 0} or {@code end > array.length}.
727     */
728    public static void fill(short[] array, int start, int end, short value) {
729        Arrays.checkStartAndEnd(array.length, start, end);
730        for (int i = start; i < end; i++) {
731            array[i] = value;
732        }
733    }
734
735    /**
736     * Fills the specified array with the specified element.
737     *
738     * @param array
739     *            the {@code char} array to fill.
740     * @param value
741     *            the {@code char} element.
742     */
743    public static void fill(char[] array, char value) {
744        for (int i = 0; i < array.length; i++) {
745            array[i] = value;
746        }
747    }
748
749    /**
750     * Fills the specified range in the array with the specified element.
751     *
752     * @param array
753     *            the {@code char} array to fill.
754     * @param start
755     *            the first index to fill.
756     * @param end
757     *            the last + 1 index to fill.
758     * @param value
759     *            the {@code char} element.
760     * @throws IllegalArgumentException
761     *                if {@code start > end}.
762     * @throws ArrayIndexOutOfBoundsException
763     *                if {@code start < 0} or {@code end > array.length}.
764     */
765    public static void fill(char[] array, int start, int end, char value) {
766        Arrays.checkStartAndEnd(array.length, start, end);
767        for (int i = start; i < end; i++) {
768            array[i] = value;
769        }
770    }
771
772    /**
773     * Fills the specified array with the specified element.
774     *
775     * @param array
776     *            the {@code int} array to fill.
777     * @param value
778     *            the {@code int} element.
779     */
780    public static void fill(int[] array, int value) {
781        for (int i = 0; i < array.length; i++) {
782            array[i] = value;
783        }
784    }
785
786    /**
787     * Fills the specified range in the array with the specified element.
788     *
789     * @param array
790     *            the {@code int} array to fill.
791     * @param start
792     *            the first index to fill.
793     * @param end
794     *            the last + 1 index to fill.
795     * @param value
796     *            the {@code int} element.
797     * @throws IllegalArgumentException
798     *                if {@code start > end}.
799     * @throws ArrayIndexOutOfBoundsException
800     *                if {@code start < 0} or {@code end > array.length}.
801     */
802    public static void fill(int[] array, int start, int end, int value) {
803        Arrays.checkStartAndEnd(array.length, start, end);
804        for (int i = start; i < end; i++) {
805            array[i] = value;
806        }
807    }
808
809    /**
810     * Fills the specified array with the specified element.
811     *
812     * @param array
813     *            the {@code long} array to fill.
814     * @param value
815     *            the {@code long} element.
816     */
817    public static void fill(long[] array, long value) {
818        for (int i = 0; i < array.length; i++) {
819            array[i] = value;
820        }
821    }
822
823    /**
824     * Fills the specified range in the array with the specified element.
825     *
826     * @param array
827     *            the {@code long} array to fill.
828     * @param start
829     *            the first index to fill.
830     * @param end
831     *            the last + 1 index to fill.
832     * @param value
833     *            the {@code long} element.
834     * @throws IllegalArgumentException
835     *                if {@code start > end}.
836     * @throws ArrayIndexOutOfBoundsException
837     *                if {@code start < 0} or {@code end > array.length}.
838     */
839    public static void fill(long[] array, int start, int end, long value) {
840        Arrays.checkStartAndEnd(array.length, start, end);
841        for (int i = start; i < end; i++) {
842            array[i] = value;
843        }
844    }
845
846    /**
847     * Fills the specified array with the specified element.
848     *
849     * @param array
850     *            the {@code float} array to fill.
851     * @param value
852     *            the {@code float} element.
853     */
854    public static void fill(float[] array, float value) {
855        for (int i = 0; i < array.length; i++) {
856            array[i] = value;
857        }
858    }
859
860    /**
861     * Fills the specified range in the array with the specified element.
862     *
863     * @param array
864     *            the {@code float} array to fill.
865     * @param start
866     *            the first index to fill.
867     * @param end
868     *            the last + 1 index to fill.
869     * @param value
870     *            the {@code float} element.
871     * @throws IllegalArgumentException
872     *                if {@code start > end}.
873     * @throws ArrayIndexOutOfBoundsException
874     *                if {@code start < 0} or {@code end > array.length}.
875     */
876    public static void fill(float[] array, int start, int end, float value) {
877        Arrays.checkStartAndEnd(array.length, start, end);
878        for (int i = start; i < end; i++) {
879            array[i] = value;
880        }
881    }
882
883    /**
884     * Fills the specified array with the specified element.
885     *
886     * @param array
887     *            the {@code double} array to fill.
888     * @param value
889     *            the {@code double} element.
890     */
891    public static void fill(double[] array, double value) {
892        for (int i = 0; i < array.length; i++) {
893            array[i] = value;
894        }
895    }
896
897    /**
898     * Fills the specified range in the array with the specified element.
899     *
900     * @param array
901     *            the {@code double} array to fill.
902     * @param start
903     *            the first index to fill.
904     * @param end
905     *            the last + 1 index to fill.
906     * @param value
907     *            the {@code double} element.
908     * @throws IllegalArgumentException
909     *                if {@code start > end}.
910     * @throws ArrayIndexOutOfBoundsException
911     *                if {@code start < 0} or {@code end > array.length}.
912     */
913    public static void fill(double[] array, int start, int end, double value) {
914        Arrays.checkStartAndEnd(array.length, start, end);
915        for (int i = start; i < end; i++) {
916            array[i] = value;
917        }
918    }
919
920    /**
921     * Fills the specified array with the specified element.
922     *
923     * @param array
924     *            the {@code boolean} array to fill.
925     * @param value
926     *            the {@code boolean} element.
927     */
928    public static void fill(boolean[] array, boolean value) {
929        for (int i = 0; i < array.length; i++) {
930            array[i] = value;
931        }
932    }
933
934    /**
935     * Fills the specified range in the array with the specified element.
936     *
937     * @param array
938     *            the {@code boolean} array to fill.
939     * @param start
940     *            the first index to fill.
941     * @param end
942     *            the last + 1 index to fill.
943     * @param value
944     *            the {@code boolean} element.
945     * @throws IllegalArgumentException
946     *                if {@code start > end}.
947     * @throws ArrayIndexOutOfBoundsException
948     *                if {@code start < 0} or {@code end > array.length}.
949     */
950    public static void fill(boolean[] array, int start, int end, boolean value) {
951        Arrays.checkStartAndEnd(array.length, start, end);
952        for (int i = start; i < end; i++) {
953            array[i] = value;
954        }
955    }
956
957    /**
958     * Fills the specified array with the specified element.
959     *
960     * @param array
961     *            the {@code Object} array to fill.
962     * @param value
963     *            the {@code Object} element.
964     */
965    public static void fill(Object[] array, Object value) {
966        for (int i = 0; i < array.length; i++) {
967            array[i] = value;
968        }
969    }
970
971    /**
972     * Fills the specified range in the array with the specified element.
973     *
974     * @param array
975     *            the {@code Object} array to fill.
976     * @param start
977     *            the first index to fill.
978     * @param end
979     *            the last + 1 index to fill.
980     * @param value
981     *            the {@code Object} element.
982     * @throws IllegalArgumentException
983     *                if {@code start > end}.
984     * @throws ArrayIndexOutOfBoundsException
985     *                if {@code start < 0} or {@code end > array.length}.
986     */
987    public static void fill(Object[] array, int start, int end, Object value) {
988        Arrays.checkStartAndEnd(array.length, start, end);
989        for (int i = start; i < end; i++) {
990            array[i] = value;
991        }
992    }
993
994    /**
995     * Returns a hash code based on the contents of the given array. For any two
996     * {@code boolean} arrays {@code a} and {@code b}, if
997     * {@code Arrays.equals(a, b)} returns {@code true}, it means
998     * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
999     * <p>
1000     * The value returned by this method is the same value as the
1001     * {@link List#hashCode()} method which is invoked on a {@link List}
1002     * containing a sequence of {@link Boolean} instances representing the
1003     * elements of array in the same order. If the array is {@code null}, the return
1004     * value is 0.
1005     *
1006     * @param array
1007     *            the array whose hash code to compute.
1008     * @return the hash code for {@code array}.
1009     */
1010    public static int hashCode(boolean[] array) {
1011        if (array == null) {
1012            return 0;
1013        }
1014        int hashCode = 1;
1015        for (boolean element : array) {
1016            // 1231, 1237 are hash code values for boolean value
1017            hashCode = 31 * hashCode + (element ? 1231 : 1237);
1018        }
1019        return hashCode;
1020    }
1021
1022    /**
1023     * Returns a hash code based on the contents of the given array. For any two
1024     * not-null {@code int} arrays {@code a} and {@code b}, if
1025     * {@code Arrays.equals(a, b)} returns {@code true}, it means
1026     * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
1027     * <p>
1028     * The value returned by this method is the same value as the
1029     * {@link List#hashCode()} method which is invoked on a {@link List}
1030     * containing a sequence of {@link Integer} instances representing the
1031     * elements of array in the same order. If the array is {@code null}, the return
1032     * value is 0.
1033     *
1034     * @param array
1035     *            the array whose hash code to compute.
1036     * @return the hash code for {@code array}.
1037     */
1038    public static int hashCode(int[] array) {
1039        if (array == null) {
1040            return 0;
1041        }
1042        int hashCode = 1;
1043        for (int element : array) {
1044            // the hash code value for integer value is integer value itself
1045            hashCode = 31 * hashCode + element;
1046        }
1047        return hashCode;
1048    }
1049
1050    /**
1051     * Returns a hash code based on the contents of the given array. For any two
1052     * {@code short} arrays {@code a} and {@code b}, if
1053     * {@code Arrays.equals(a, b)} returns {@code true}, it means
1054     * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
1055     * <p>
1056     * The value returned by this method is the same value as the
1057     * {@link List#hashCode()} method which is invoked on a {@link List}
1058     * containing a sequence of {@link Short} instances representing the
1059     * elements of array in the same order. If the array is {@code null}, the return
1060     * value is 0.
1061     *
1062     * @param array
1063     *            the array whose hash code to compute.
1064     * @return the hash code for {@code array}.
1065     */
1066    public static int hashCode(short[] array) {
1067        if (array == null) {
1068            return 0;
1069        }
1070        int hashCode = 1;
1071        for (short element : array) {
1072            // the hash code value for short value is its integer value
1073            hashCode = 31 * hashCode + element;
1074        }
1075        return hashCode;
1076    }
1077
1078    /**
1079     * Returns a hash code based on the contents of the given array. For any two
1080     * {@code char} arrays {@code a} and {@code b}, if
1081     * {@code Arrays.equals(a, b)} returns {@code true}, it means
1082     * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
1083     * <p>
1084     * The value returned by this method is the same value as the
1085     * {@link List#hashCode()} method which is invoked on a {@link List}
1086     * containing a sequence of {@link Character} instances representing the
1087     * elements of array in the same order. If the array is {@code null}, the return
1088     * value is 0.
1089     *
1090     * @param array
1091     *            the array whose hash code to compute.
1092     * @return the hash code for {@code array}.
1093     */
1094    public static int hashCode(char[] array) {
1095        if (array == null) {
1096            return 0;
1097        }
1098        int hashCode = 1;
1099        for (char element : array) {
1100            // the hash code value for char value is its integer value
1101            hashCode = 31 * hashCode + element;
1102        }
1103        return hashCode;
1104    }
1105
1106    /**
1107     * Returns a hash code based on the contents of the given array. For any two
1108     * {@code byte} arrays {@code a} and {@code b}, if
1109     * {@code Arrays.equals(a, b)} returns {@code true}, it means
1110     * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
1111     * <p>
1112     * The value returned by this method is the same value as the
1113     * {@link List#hashCode()} method which is invoked on a {@link List}
1114     * containing a sequence of {@link Byte} instances representing the
1115     * elements of array in the same order. If the array is {@code null}, the return
1116     * value is 0.
1117     *
1118     * @param array
1119     *            the array whose hash code to compute.
1120     * @return the hash code for {@code array}.
1121     */
1122    public static int hashCode(byte[] array) {
1123        if (array == null) {
1124            return 0;
1125        }
1126        int hashCode = 1;
1127        for (byte element : array) {
1128            // the hash code value for byte value is its integer value
1129            hashCode = 31 * hashCode + element;
1130        }
1131        return hashCode;
1132    }
1133
1134    /**
1135     * Returns a hash code based on the contents of the given array. For any two
1136     * {@code long} arrays {@code a} and {@code b}, if
1137     * {@code Arrays.equals(a, b)} returns {@code true}, it means
1138     * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
1139     * <p>
1140     * The value returned by this method is the same value as the
1141     * {@link List#hashCode()} method which is invoked on a {@link List}
1142     * containing a sequence of {@link Long} instances representing the
1143     * elements of array in the same order. If the array is {@code null}, the return
1144     * value is 0.
1145     *
1146     * @param array
1147     *            the array whose hash code to compute.
1148     * @return the hash code for {@code array}.
1149     */
1150    public static int hashCode(long[] array) {
1151        if (array == null) {
1152            return 0;
1153        }
1154        int hashCode = 1;
1155        for (long elementValue : array) {
1156            /*
1157             * the hash code value for long value is (int) (value ^ (value >>>
1158             * 32))
1159             */
1160            hashCode = 31 * hashCode
1161                    + (int) (elementValue ^ (elementValue >>> 32));
1162        }
1163        return hashCode;
1164    }
1165
1166    /**
1167     * Returns a hash code based on the contents of the given array. For any two
1168     * {@code float} arrays {@code a} and {@code b}, if
1169     * {@code Arrays.equals(a, b)} returns {@code true}, it means
1170     * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
1171     * <p>
1172     * The value returned by this method is the same value as the
1173     * {@link List#hashCode()} method which is invoked on a {@link List}
1174     * containing a sequence of {@link Float} instances representing the
1175     * elements of array in the same order. If the array is {@code null}, the return
1176     * value is 0.
1177     *
1178     * @param array
1179     *            the array whose hash code to compute.
1180     * @return the hash code for {@code array}.
1181     */
1182    public static int hashCode(float[] array) {
1183        if (array == null) {
1184            return 0;
1185        }
1186        int hashCode = 1;
1187        for (float element : array) {
1188            /*
1189             * the hash code value for float value is
1190             * Float.floatToIntBits(value)
1191             */
1192            hashCode = 31 * hashCode + Float.floatToIntBits(element);
1193        }
1194        return hashCode;
1195    }
1196
1197    /**
1198     * Returns a hash code based on the contents of the given array. For any two
1199     * {@code double} arrays {@code a} and {@code b}, if
1200     * {@code Arrays.equals(a, b)} returns {@code true}, it means
1201     * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
1202     * <p>
1203     * The value returned by this method is the same value as the
1204     * {@link List#hashCode()} method which is invoked on a {@link List}
1205     * containing a sequence of {@link Double} instances representing the
1206     * elements of array in the same order. If the array is {@code null}, the return
1207     * value is 0.
1208     *
1209     * @param array
1210     *            the array whose hash code to compute.
1211     * @return the hash code for {@code array}.
1212     */
1213    public static int hashCode(double[] array) {
1214        if (array == null) {
1215            return 0;
1216        }
1217        int hashCode = 1;
1218
1219        for (double element : array) {
1220            long v = Double.doubleToLongBits(element);
1221            /*
1222             * the hash code value for double value is (int) (v ^ (v >>> 32))
1223             * where v = Double.doubleToLongBits(value)
1224             */
1225            hashCode = 31 * hashCode + (int) (v ^ (v >>> 32));
1226        }
1227        return hashCode;
1228    }
1229
1230    /**
1231     * Returns a hash code based on the contents of the given array. If the
1232     * array contains other arrays as its elements, the hash code is based on
1233     * their identities not their contents. So it is acceptable to invoke this
1234     * method on an array that contains itself as an element, either directly or
1235     * indirectly.
1236     * <p>
1237     * For any two arrays {@code a} and {@code b}, if
1238     * {@code Arrays.equals(a, b)} returns {@code true}, it means
1239     * that the return value of {@code Arrays.hashCode(a)} equals
1240     * {@code Arrays.hashCode(b)}.
1241     * <p>
1242     * The value returned by this method is the same value as the method
1243     * Arrays.asList(array).hashCode(). If the array is {@code null}, the return value
1244     * is 0.
1245     *
1246     * @param array
1247     *            the array whose hash code to compute.
1248     * @return the hash code for {@code array}.
1249     */
1250    public static int hashCode(Object[] array) {
1251        if (array == null) {
1252            return 0;
1253        }
1254        int hashCode = 1;
1255        for (Object element : array) {
1256            int elementHashCode;
1257
1258            if (element == null) {
1259                elementHashCode = 0;
1260            } else {
1261                elementHashCode = (element).hashCode();
1262            }
1263            hashCode = 31 * hashCode + elementHashCode;
1264        }
1265        return hashCode;
1266    }
1267
1268    /**
1269     * Returns a hash code based on the "deep contents" of the given array. If
1270     * the array contains other arrays as its elements, the hash code is based
1271     * on their contents not their identities. So it is not acceptable to invoke
1272     * this method on an array that contains itself as an element, either
1273     * directly or indirectly.
1274     * <p>
1275     * For any two arrays {@code a} and {@code b}, if
1276     * {@code Arrays.deepEquals(a, b)} returns {@code true}, it
1277     * means that the return value of {@code Arrays.deepHashCode(a)} equals
1278     * {@code Arrays.deepHashCode(b)}.
1279     * <p>
1280     * The computation of the value returned by this method is similar to that
1281     * of the value returned by {@link List#hashCode()} invoked on a
1282     * {@link List} containing a sequence of instances representing the
1283     * elements of array in the same order. The difference is: If an element e
1284     * of array is itself an array, its hash code is computed by calling the
1285     * appropriate overloading of {@code Arrays.hashCode(e)} if e is an array of a
1286     * primitive type, or by calling {@code Arrays.deepHashCode(e)} recursively if e is
1287     * an array of a reference type. The value returned by this method is the
1288     * same value as the method {@code Arrays.asList(array).hashCode()}. If the array is
1289     * {@code null}, the return value is 0.
1290     *
1291     * @param array
1292     *            the array whose hash code to compute.
1293     * @return the hash code for {@code array}.
1294     */
1295    public static int deepHashCode(Object[] array) {
1296        if (array == null) {
1297            return 0;
1298        }
1299        int hashCode = 1;
1300        for (Object element : array) {
1301            int elementHashCode = deepHashCodeElement(element);
1302            hashCode = 31 * hashCode + elementHashCode;
1303        }
1304        return hashCode;
1305    }
1306
1307    private static int deepHashCodeElement(Object element) {
1308        Class<?> cl;
1309        if (element == null) {
1310            return 0;
1311        }
1312
1313        cl = element.getClass().getComponentType();
1314
1315        if (cl == null) {
1316            return element.hashCode();
1317        }
1318
1319        /*
1320         * element is an array
1321         */
1322        if (!cl.isPrimitive()) {
1323            return deepHashCode((Object[]) element);
1324        }
1325        if (cl.equals(int.class)) {
1326            return hashCode((int[]) element);
1327        }
1328        if (cl.equals(char.class)) {
1329            return hashCode((char[]) element);
1330        }
1331        if (cl.equals(boolean.class)) {
1332            return hashCode((boolean[]) element);
1333        }
1334        if (cl.equals(byte.class)) {
1335            return hashCode((byte[]) element);
1336        }
1337        if (cl.equals(long.class)) {
1338            return hashCode((long[]) element);
1339        }
1340        if (cl.equals(float.class)) {
1341            return hashCode((float[]) element);
1342        }
1343        if (cl.equals(double.class)) {
1344            return hashCode((double[]) element);
1345        }
1346        return hashCode((short[]) element);
1347    }
1348
1349    /**
1350     * Compares the two arrays.
1351     *
1352     * @param array1
1353     *            the first {@code byte} array.
1354     * @param array2
1355     *            the second {@code byte} array.
1356     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1357     *         same length and the elements at each index in the two arrays are
1358     *         equal, {@code false} otherwise.
1359     */
1360    public static boolean equals(byte[] array1, byte[] array2) {
1361        if (array1 == array2) {
1362            return true;
1363        }
1364        if (array1 == null || array2 == null || array1.length != array2.length) {
1365            return false;
1366        }
1367        for (int i = 0; i < array1.length; i++) {
1368            if (array1[i] != array2[i]) {
1369                return false;
1370            }
1371        }
1372        return true;
1373    }
1374
1375    /**
1376     * Compares the two arrays.
1377     *
1378     * @param array1
1379     *            the first {@code short} array.
1380     * @param array2
1381     *            the second {@code short} array.
1382     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1383     *         same length and the elements at each index in the two arrays are
1384     *         equal, {@code false} otherwise.
1385     */
1386    public static boolean equals(short[] array1, short[] array2) {
1387        if (array1 == array2) {
1388            return true;
1389        }
1390        if (array1 == null || array2 == null || array1.length != array2.length) {
1391            return false;
1392        }
1393        for (int i = 0; i < array1.length; i++) {
1394            if (array1[i] != array2[i]) {
1395                return false;
1396            }
1397        }
1398        return true;
1399    }
1400
1401    /**
1402     * Compares the two arrays.
1403     *
1404     * @param array1
1405     *            the first {@code char} array.
1406     * @param array2
1407     *            the second {@code char} array.
1408     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1409     *         same length and the elements at each index in the two arrays are
1410     *         equal, {@code false} otherwise.
1411     */
1412    public static boolean equals(char[] array1, char[] array2) {
1413        if (array1 == array2) {
1414            return true;
1415        }
1416        if (array1 == null || array2 == null || array1.length != array2.length) {
1417            return false;
1418        }
1419        for (int i = 0; i < array1.length; i++) {
1420            if (array1[i] != array2[i]) {
1421                return false;
1422            }
1423        }
1424        return true;
1425    }
1426
1427    /**
1428     * Compares the two arrays.
1429     *
1430     * @param array1
1431     *            the first {@code int} array.
1432     * @param array2
1433     *            the second {@code int} array.
1434     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1435     *         same length and the elements at each index in the two arrays are
1436     *         equal, {@code false} otherwise.
1437     */
1438    public static boolean equals(int[] array1, int[] array2) {
1439        if (array1 == array2) {
1440            return true;
1441        }
1442        if (array1 == null || array2 == null || array1.length != array2.length) {
1443            return false;
1444        }
1445        for (int i = 0; i < array1.length; i++) {
1446            if (array1[i] != array2[i]) {
1447                return false;
1448            }
1449        }
1450        return true;
1451    }
1452
1453    /**
1454     * Compares the two arrays.
1455     *
1456     * @param array1
1457     *            the first {@code long} array.
1458     * @param array2
1459     *            the second {@code long} array.
1460     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1461     *         same length and the elements at each index in the two arrays are
1462     *         equal, {@code false} otherwise.
1463     */
1464    public static boolean equals(long[] array1, long[] array2) {
1465        if (array1 == array2) {
1466            return true;
1467        }
1468        if (array1 == null || array2 == null || array1.length != array2.length) {
1469            return false;
1470        }
1471        for (int i = 0; i < array1.length; i++) {
1472            if (array1[i] != array2[i]) {
1473                return false;
1474            }
1475        }
1476        return true;
1477    }
1478
1479    /**
1480     * Compares the two arrays. The values are compared in the same manner as
1481     * {@code Float.equals()}.
1482     *
1483     * @param array1
1484     *            the first {@code float} array.
1485     * @param array2
1486     *            the second {@code float} array.
1487     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1488     *         same length and the elements at each index in the two arrays are
1489     *         equal, {@code false} otherwise.
1490     * @see Float#equals(Object)
1491     */
1492    public static boolean equals(float[] array1, float[] array2) {
1493        if (array1 == array2) {
1494            return true;
1495        }
1496        if (array1 == null || array2 == null || array1.length != array2.length) {
1497            return false;
1498        }
1499        for (int i = 0; i < array1.length; i++) {
1500            if (Float.floatToIntBits(array1[i]) != Float
1501                    .floatToIntBits(array2[i])) {
1502                return false;
1503            }
1504        }
1505        return true;
1506    }
1507
1508    /**
1509     * Compares the two arrays. The values are compared in the same manner as
1510     * {@code Double.equals()}.
1511     *
1512     * @param array1
1513     *            the first {@code double} array.
1514     * @param array2
1515     *            the second {@code double} array.
1516     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1517     *         same length and the elements at each index in the two arrays are
1518     *         equal, {@code false} otherwise.
1519     * @see Double#equals(Object)
1520     */
1521    public static boolean equals(double[] array1, double[] array2) {
1522        if (array1 == array2) {
1523            return true;
1524        }
1525        if (array1 == null || array2 == null || array1.length != array2.length) {
1526            return false;
1527        }
1528        for (int i = 0; i < array1.length; i++) {
1529            if (Double.doubleToLongBits(array1[i]) != Double
1530                    .doubleToLongBits(array2[i])) {
1531                return false;
1532            }
1533        }
1534        return true;
1535    }
1536
1537    /**
1538     * Compares the two arrays.
1539     *
1540     * @param array1
1541     *            the first {@code boolean} array.
1542     * @param array2
1543     *            the second {@code boolean} array.
1544     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1545     *         same length and the elements at each index in the two arrays are
1546     *         equal, {@code false} otherwise.
1547     */
1548    public static boolean equals(boolean[] array1, boolean[] array2) {
1549        if (array1 == array2) {
1550            return true;
1551        }
1552        if (array1 == null || array2 == null || array1.length != array2.length) {
1553            return false;
1554        }
1555        for (int i = 0; i < array1.length; i++) {
1556            if (array1[i] != array2[i]) {
1557                return false;
1558            }
1559        }
1560        return true;
1561    }
1562
1563    /**
1564     * Compares the two arrays.
1565     *
1566     * @param array1
1567     *            the first {@code Object} array.
1568     * @param array2
1569     *            the second {@code Object} array.
1570     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1571     *         same length and the elements at each index in the two arrays are
1572     *         equal according to {@code equals()}, {@code false} otherwise.
1573     */
1574    public static boolean equals(Object[] array1, Object[] array2) {
1575        if (array1 == array2) {
1576            return true;
1577        }
1578        if (array1 == null || array2 == null || array1.length != array2.length) {
1579            return false;
1580        }
1581        for (int i = 0; i < array1.length; i++) {
1582            Object e1 = array1[i], e2 = array2[i];
1583            if (!(e1 == null ? e2 == null : e1.equals(e2))) {
1584                return false;
1585            }
1586        }
1587        return true;
1588    }
1589
1590    /**
1591     * Returns {@code true} if the two given arrays are deeply equal to one another.
1592     * Unlike the method {@code equals(Object[] array1, Object[] array2)}, this method
1593     * is appropriate for use for nested arrays of arbitrary depth.
1594     * <p>
1595     * Two array references are considered deeply equal if they are both {@code null},
1596     * or if they refer to arrays that have the same length and the elements at
1597     * each index in the two arrays are equal.
1598     * <p>
1599     * Two {@code null} elements {@code element1} and {@code element2} are possibly deeply equal if any
1600     * of the following conditions satisfied:
1601     * <p>
1602     * {@code element1} and {@code element2} are both arrays of object reference types, and
1603     * {@code Arrays.deepEquals(element1, element2)} would return {@code true}.
1604     * <p>
1605     * {@code element1} and {@code element2} are arrays of the same primitive type, and the
1606     * appropriate overloading of {@code Arrays.equals(element1, element2)} would return
1607     * {@code true}.
1608     * <p>
1609     * {@code element1 == element2}
1610     * <p>
1611     * {@code element1.equals(element2)} would return {@code true}.
1612     * <p>
1613     * Note that this definition permits {@code null} elements at any depth.
1614     * <p>
1615     * If either of the given arrays contain themselves as elements, the
1616     * behavior of this method is uncertain.
1617     *
1618     * @param array1
1619     *            the first {@code Object} array.
1620     * @param array2
1621     *            the second {@code Object} array.
1622     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1623     *         same length and the elements at each index in the two arrays are
1624     *         equal according to {@code equals()}, {@code false} otherwise.
1625     */
1626    public static boolean deepEquals(Object[] array1, Object[] array2) {
1627        if (array1 == array2) {
1628            return true;
1629        }
1630        if (array1 == null || array2 == null || array1.length != array2.length) {
1631            return false;
1632        }
1633        for (int i = 0; i < array1.length; i++) {
1634            Object e1 = array1[i], e2 = array2[i];
1635
1636            if (!deepEqualsElements(e1, e2)) {
1637                return false;
1638            }
1639        }
1640        return true;
1641    }
1642
1643    private static boolean deepEqualsElements(Object e1, Object e2) {
1644        Class<?> cl1, cl2;
1645
1646        if (e1 == e2) {
1647            return true;
1648        }
1649
1650        if (e1 == null || e2 == null) {
1651            return false;
1652        }
1653
1654        cl1 = e1.getClass().getComponentType();
1655        cl2 = e2.getClass().getComponentType();
1656
1657        if (cl1 != cl2) {
1658            return false;
1659        }
1660
1661        if (cl1 == null) {
1662            return e1.equals(e2);
1663        }
1664
1665        /*
1666         * compare as arrays
1667         */
1668        if (!cl1.isPrimitive()) {
1669            return deepEquals((Object[]) e1, (Object[]) e2);
1670        }
1671
1672        if (cl1.equals(int.class)) {
1673            return equals((int[]) e1, (int[]) e2);
1674        }
1675        if (cl1.equals(char.class)) {
1676            return equals((char[]) e1, (char[]) e2);
1677        }
1678        if (cl1.equals(boolean.class)) {
1679            return equals((boolean[]) e1, (boolean[]) e2);
1680        }
1681        if (cl1.equals(byte.class)) {
1682            return equals((byte[]) e1, (byte[]) e2);
1683        }
1684        if (cl1.equals(long.class)) {
1685            return equals((long[]) e1, (long[]) e2);
1686        }
1687        if (cl1.equals(float.class)) {
1688            return equals((float[]) e1, (float[]) e2);
1689        }
1690        if (cl1.equals(double.class)) {
1691            return equals((double[]) e1, (double[]) e2);
1692        }
1693        return equals((short[]) e1, (short[]) e2);
1694    }
1695
1696    /**
1697     * Sorts the specified array in ascending numerical order.
1698     *
1699     * @param array
1700     *            the {@code byte} array to be sorted.
1701     */
1702    public static void sort(byte[] array) {
1703        DualPivotQuicksort.sort(array);
1704    }
1705
1706    /**
1707     * Sorts the specified range in the array in ascending numerical order.
1708     *
1709     * @param array
1710     *            the {@code byte} array to be sorted.
1711     * @param start
1712     *            the start index to sort.
1713     * @param end
1714     *            the last + 1 index to sort.
1715     * @throws IllegalArgumentException
1716     *                if {@code start > end}.
1717     * @throws ArrayIndexOutOfBoundsException
1718     *                if {@code start < 0} or {@code end > array.length}.
1719     */
1720    public static void sort(byte[] array, int start, int end) {
1721        DualPivotQuicksort.sort(array, start, end);
1722    }
1723
1724    /**
1725     * Checks that the range described by {@code offset} and {@code count} doesn't exceed
1726     * {@code arrayLength}.
1727     *
1728     * @hide
1729     */
1730    public static void checkOffsetAndCount(int arrayLength, int offset, int count) {
1731        if ((offset | count) < 0 || offset > arrayLength || arrayLength - offset < count) {
1732            throw new ArrayIndexOutOfBoundsException(arrayLength, offset,
1733                    count);
1734        }
1735    }
1736
1737    /**
1738     * Checks that the range described by {@code start} and {@code end} doesn't exceed
1739     * {@code len}.
1740     *
1741     * @hide
1742     */
1743    public static void checkStartAndEnd(int len, int start, int end) {
1744        if (start < 0 || end > len) {
1745            throw new ArrayIndexOutOfBoundsException("start < 0 || end > len."
1746                    + " start=" + start + ", end=" + end + ", len=" + len);
1747        }
1748        if (start > end) {
1749            throw new IllegalArgumentException("start > end: " + start + " > " + end);
1750        }
1751    }
1752
1753    /**
1754     * Sorts the specified array in ascending numerical order.
1755     *
1756     * @param array
1757     *            the {@code char} array to be sorted.
1758     */
1759    public static void sort(char[] array) {
1760        DualPivotQuicksort.sort(array);
1761    }
1762
1763    /**
1764     * Sorts the specified range in the array in ascending numerical order.
1765     *
1766     * @param array
1767     *            the {@code char} array to be sorted.
1768     * @param start
1769     *            the start index to sort.
1770     * @param end
1771     *            the last + 1 index to sort.
1772     * @throws IllegalArgumentException
1773     *                if {@code start > end}.
1774     * @throws ArrayIndexOutOfBoundsException
1775     *                if {@code start < 0} or {@code end > array.length}.
1776     */
1777    public static void sort(char[] array, int start, int end) {
1778        DualPivotQuicksort.sort(array, start, end);
1779    }
1780
1781    /**
1782     * Sorts the specified array in ascending numerical order.
1783     *
1784     * @param array
1785     *            the {@code double} array to be sorted.
1786     * @see #sort(double[], int, int)
1787     */
1788    public static void sort(double[] array) {
1789        DualPivotQuicksort.sort(array);
1790    }
1791
1792    /**
1793     * Sorts the specified range in the array in ascending numerical order. The
1794     * values are sorted according to the order imposed by {@code Double.compareTo()}.
1795     *
1796     * @param array
1797     *            the {@code double} array to be sorted.
1798     * @param start
1799     *            the start index to sort.
1800     * @param end
1801     *            the last + 1 index to sort.
1802     * @throws IllegalArgumentException
1803     *                if {@code start > end}.
1804     * @throws ArrayIndexOutOfBoundsException
1805     *                if {@code start < 0} or {@code end > array.length}.
1806     * @see Double#compareTo(Double)
1807     */
1808    public static void sort(double[] array, int start, int end) {
1809        DualPivotQuicksort.sort(array, start, end);
1810    }
1811
1812    /**
1813     * Sorts the specified array in ascending numerical order.
1814     *
1815     * @param array
1816     *            the {@code float} array to be sorted.
1817     * @see #sort(float[], int, int)
1818     */
1819    public static void sort(float[] array) {
1820        DualPivotQuicksort.sort(array);
1821    }
1822
1823    /**
1824     * Sorts the specified range in the array in ascending numerical order. The
1825     * values are sorted according to the order imposed by {@code Float.compareTo()}.
1826     *
1827     * @param array
1828     *            the {@code float} array to be sorted.
1829     * @param start
1830     *            the start index to sort.
1831     * @param end
1832     *            the last + 1 index to sort.
1833     * @throws IllegalArgumentException
1834     *                if {@code start > end}.
1835     * @throws ArrayIndexOutOfBoundsException
1836     *                if {@code start < 0} or {@code end > array.length}.
1837     * @see Float#compareTo(Float)
1838     */
1839    public static void sort(float[] array, int start, int end) {
1840        DualPivotQuicksort.sort(array, start, end);
1841    }
1842
1843    /**
1844     * Sorts the specified array in ascending numerical order.
1845     *
1846     * @param array
1847     *            the {@code int} array to be sorted.
1848     */
1849    public static void sort(int[] array) {
1850        DualPivotQuicksort.sort(array);
1851    }
1852
1853    /**
1854     * Sorts the specified range in the array in ascending numerical order.
1855     *
1856     * @param array
1857     *            the {@code int} array to be sorted.
1858     * @param start
1859     *            the start index to sort.
1860     * @param end
1861     *            the last + 1 index to sort.
1862     * @throws IllegalArgumentException
1863     *                if {@code start > end}.
1864     * @throws ArrayIndexOutOfBoundsException
1865     *                if {@code start < 0} or {@code end > array.length}.
1866     */
1867    public static void sort(int[] array, int start, int end) {
1868        DualPivotQuicksort.sort(array, start, end);
1869    }
1870
1871    /**
1872     * Sorts the specified array in ascending numerical order.
1873     *
1874     * @param array
1875     *            the {@code long} array to be sorted.
1876     */
1877    public static void sort(long[] array) {
1878        DualPivotQuicksort.sort(array);
1879    }
1880
1881    /**
1882     * Sorts the specified range in the array in ascending numerical order.
1883     *
1884     * @param array
1885     *            the {@code long} array to be sorted.
1886     * @param start
1887     *            the start index to sort.
1888     * @param end
1889     *            the last + 1 index to sort.
1890     * @throws IllegalArgumentException
1891     *                if {@code start > end}.
1892     * @throws ArrayIndexOutOfBoundsException
1893     *                if {@code start < 0} or {@code end > array.length}.
1894     */
1895    public static void sort(long[] array, int start, int end) {
1896        DualPivotQuicksort.sort(array, start, end);
1897    }
1898
1899    /**
1900     * Sorts the specified array in ascending numerical order.
1901     *
1902     * @param array
1903     *            the {@code short} array to be sorted.
1904     */
1905    public static void sort(short[] array) {
1906        DualPivotQuicksort.sort(array);
1907    }
1908
1909    /**
1910     * Sorts the specified range in the array in ascending numerical order.
1911     *
1912     * @param array
1913     *            the {@code short} array to be sorted.
1914     * @param start
1915     *            the start index to sort.
1916     * @param end
1917     *            the last + 1 index to sort.
1918     * @throws IllegalArgumentException
1919     *                if {@code start > end}.
1920     * @throws ArrayIndexOutOfBoundsException
1921     *                if {@code start < 0} or {@code end > array.length}.
1922     */
1923    public static void sort(short[] array, int start, int end) {
1924        DualPivotQuicksort.sort(array, start, end);
1925    }
1926
1927// BEGIN android-note
1928
1929    /*
1930     * <p>If this platform has an optimizing VM, check whether ComparableTimSort
1931     * offers any performance benefit over TimSort in conjunction with a
1932     * comparator that returns:
1933     *    {@code ((Comparable)first).compareTo(Second)}.
1934     * If not, you are better off deleting ComparableTimSort to eliminate the
1935     * code duplication.  In other words, the commented out code below
1936     * is the preferable implementation for sorting arrays of Comparables if it
1937     * offers sufficient performance.
1938     */
1939
1940//    /**
1941//     * A comparator that implements the natural order of a group of
1942//     * mutually comparable elements.  Using this comparator saves us
1943//     * from duplicating most of the code in this file (one version for
1944//     * Comparables, one for explicit comparators).
1945//     */
1946//    private static final Comparator<Object> NATURAL_ORDER = new Comparator<Object>() {
1947//        @SuppressWarnings("unchecked")
1948//        public int compare(Object first, Object second) {
1949//            return ((Comparable<Object>)first).compareTo(second);
1950//        }
1951//    };
1952//
1953//    public static void sort(Object[] a) {
1954//        sort(a, 0, a.length, NATURAL_ORDER);
1955//    }
1956//
1957//    public static void sort(Object[] a, int fromIndex, int toIndex) {
1958//        sort(a, fromIndex, toIndex, NATURAL_ORDER);
1959//    }
1960
1961// END android-note
1962
1963    /**
1964     * Sorts the specified array in ascending natural order.
1965     *
1966     * @throws ClassCastException if any element does not implement {@code Comparable},
1967     *     or if {@code compareTo} throws for any pair of elements.
1968     */
1969    public static void sort(Object[] array) {
1970        ComparableTimSort.sort(array);
1971    }
1972
1973    /**
1974     * Sorts the specified range in the array in ascending natural order.
1975     *
1976     * @param start
1977     *            the start index to sort.
1978     * @param end
1979     *            the last + 1 index to sort.
1980     * @throws ClassCastException if any element does not implement {@code Comparable},
1981     *     or if {@code compareTo} throws for any pair of elements.
1982     * @throws IllegalArgumentException
1983     *                if {@code start > end}.
1984     * @throws ArrayIndexOutOfBoundsException
1985     *                if {@code start < 0} or {@code end > array.length}.
1986     */
1987    public static void sort(Object[] array, int start, int end) {
1988        ComparableTimSort.sort(array, start, end);
1989    }
1990
1991    /**
1992     * Sorts the specified range in the array using the specified {@code Comparator}.
1993     * All elements must be comparable to each other without a
1994     * {@code ClassCastException} being thrown.
1995     *
1996     * @param start
1997     *            the start index to sort.
1998     * @param end
1999     *            the last + 1 index to sort.
2000     * @param comparator
2001     *            the {@code Comparator}.
2002     * @throws ClassCastException
2003     *                if elements in the array cannot be compared to each other
2004     *                using the given {@code Comparator}.
2005     * @throws IllegalArgumentException
2006     *                if {@code start > end}.
2007     * @throws ArrayIndexOutOfBoundsException
2008     *                if {@code start < 0} or {@code end > array.length}.
2009     */
2010    public static <T> void sort(T[] array, int start, int end, Comparator<? super T> comparator) {
2011        TimSort.sort(array, start, end, comparator);
2012    }
2013
2014    /**
2015     * Sorts the specified array using the specified {@code Comparator}. All elements
2016     * must be comparable to each other without a {@code ClassCastException} being thrown.
2017     *
2018     * @throws ClassCastException
2019     *                if elements in the array cannot be compared to each other
2020     *                using the {@code Comparator}.
2021     */
2022    public static <T> void sort(T[] array, Comparator<? super T> comparator) {
2023        TimSort.sort(array, comparator);
2024    }
2025
2026    /**
2027     * Creates a {@code String} representation of the {@code boolean[]} passed.
2028     * The result is surrounded by brackets ({@code "[]"}), each
2029     * element is converted to a {@code String} via the
2030     * {@link String#valueOf(boolean)} and separated by {@code ", "}.
2031     * If the array is {@code null}, then {@code "null"} is returned.
2032     *
2033     * @param array
2034     *            the {@code boolean} array to convert.
2035     * @return the {@code String} representation of {@code array}.
2036     * @since 1.5
2037     */
2038    public static String toString(boolean[] array) {
2039        if (array == null) {
2040            return "null";
2041        }
2042        if (array.length == 0) {
2043            return "[]";
2044        }
2045        StringBuilder sb = new StringBuilder(array.length * 7);
2046        sb.append('[');
2047        sb.append(array[0]);
2048        for (int i = 1; i < array.length; i++) {
2049            sb.append(", ");
2050            sb.append(array[i]);
2051        }
2052        sb.append(']');
2053        return sb.toString();
2054    }
2055
2056    /**
2057     * Creates a {@code String} representation of the {@code byte[]} passed. The
2058     * result is surrounded by brackets ({@code "[]"}), each element
2059     * is converted to a {@code String} via the {@link String#valueOf(int)} and
2060     * separated by {@code ", "}. If the array is {@code null}, then
2061     * {@code "null"} is returned.
2062     *
2063     * @param array
2064     *            the {@code byte} array to convert.
2065     * @return the {@code String} representation of {@code array}.
2066     * @since 1.5
2067     */
2068    public static String toString(byte[] array) {
2069        if (array == null) {
2070            return "null";
2071        }
2072        if (array.length == 0) {
2073            return "[]";
2074        }
2075        StringBuilder sb = new StringBuilder(array.length * 6);
2076        sb.append('[');
2077        sb.append(array[0]);
2078        for (int i = 1; i < array.length; i++) {
2079            sb.append(", ");
2080            sb.append(array[i]);
2081        }
2082        sb.append(']');
2083        return sb.toString();
2084    }
2085
2086    /**
2087     * Creates a {@code String} representation of the {@code char[]} passed. The
2088     * result is surrounded by brackets ({@code "[]"}), each element
2089     * is converted to a {@code String} via the {@link String#valueOf(char)} and
2090     * separated by {@code ", "}. If the array is {@code null}, then
2091     * {@code "null"} is returned.
2092     *
2093     * @param array
2094     *            the {@code char} array to convert.
2095     * @return the {@code String} representation of {@code array}.
2096     * @since 1.5
2097     */
2098    public static String toString(char[] array) {
2099        if (array == null) {
2100            return "null";
2101        }
2102        if (array.length == 0) {
2103            return "[]";
2104        }
2105        StringBuilder sb = new StringBuilder(array.length * 3);
2106        sb.append('[');
2107        sb.append(array[0]);
2108        for (int i = 1; i < array.length; i++) {
2109            sb.append(", ");
2110            sb.append(array[i]);
2111        }
2112        sb.append(']');
2113        return sb.toString();
2114    }
2115
2116    /**
2117     * Creates a {@code String} representation of the {@code double[]} passed.
2118     * The result is surrounded by brackets ({@code "[]"}), each
2119     * element is converted to a {@code String} via the
2120     * {@link String#valueOf(double)} and separated by {@code ", "}.
2121     * If the array is {@code null}, then {@code "null"} is returned.
2122     *
2123     * @param array
2124     *            the {@code double} array to convert.
2125     * @return the {@code String} representation of {@code array}.
2126     * @since 1.5
2127     */
2128    public static String toString(double[] array) {
2129        if (array == null) {
2130            return "null";
2131        }
2132        if (array.length == 0) {
2133            return "[]";
2134        }
2135        StringBuilder sb = new StringBuilder(array.length * 7);
2136        sb.append('[');
2137        sb.append(array[0]);
2138        for (int i = 1; i < array.length; i++) {
2139            sb.append(", ");
2140            sb.append(array[i]);
2141        }
2142        sb.append(']');
2143        return sb.toString();
2144    }
2145
2146    /**
2147     * Creates a {@code String} representation of the {@code float[]} passed.
2148     * The result is surrounded by brackets ({@code "[]"}), each
2149     * element is converted to a {@code String} via the
2150     * {@link String#valueOf(float)} and separated by {@code ", "}.
2151     * If the array is {@code null}, then {@code "null"} is returned.
2152     *
2153     * @param array
2154     *            the {@code float} array to convert.
2155     * @return the {@code String} representation of {@code array}.
2156     * @since 1.5
2157     */
2158    public static String toString(float[] array) {
2159        if (array == null) {
2160            return "null";
2161        }
2162        if (array.length == 0) {
2163            return "[]";
2164        }
2165        StringBuilder sb = new StringBuilder(array.length * 7);
2166        sb.append('[');
2167        sb.append(array[0]);
2168        for (int i = 1; i < array.length; i++) {
2169            sb.append(", ");
2170            sb.append(array[i]);
2171        }
2172        sb.append(']');
2173        return sb.toString();
2174    }
2175
2176    /**
2177     * Creates a {@code String} representation of the {@code int[]} passed. The
2178     * result is surrounded by brackets ({@code "[]"}), each element
2179     * is converted to a {@code String} via the {@link String#valueOf(int)} and
2180     * separated by {@code ", "}. If the array is {@code null}, then
2181     * {@code "null"} is returned.
2182     *
2183     * @param array
2184     *            the {@code int} array to convert.
2185     * @return the {@code String} representation of {@code array}.
2186     * @since 1.5
2187     */
2188    public static String toString(int[] array) {
2189        if (array == null) {
2190            return "null";
2191        }
2192        if (array.length == 0) {
2193            return "[]";
2194        }
2195        StringBuilder sb = new StringBuilder(array.length * 6);
2196        sb.append('[');
2197        sb.append(array[0]);
2198        for (int i = 1; i < array.length; i++) {
2199            sb.append(", ");
2200            sb.append(array[i]);
2201        }
2202        sb.append(']');
2203        return sb.toString();
2204    }
2205
2206    /**
2207     * Creates a {@code String} representation of the {@code long[]} passed. The
2208     * result is surrounded by brackets ({@code "[]"}), each element
2209     * is converted to a {@code String} via the {@link String#valueOf(long)} and
2210     * separated by {@code ", "}. If the array is {@code null}, then
2211     * {@code "null"} is returned.
2212     *
2213     * @param array
2214     *            the {@code long} array to convert.
2215     * @return the {@code String} representation of {@code array}.
2216     * @since 1.5
2217     */
2218    public static String toString(long[] array) {
2219        if (array == null) {
2220            return "null";
2221        }
2222        if (array.length == 0) {
2223            return "[]";
2224        }
2225        StringBuilder sb = new StringBuilder(array.length * 6);
2226        sb.append('[');
2227        sb.append(array[0]);
2228        for (int i = 1; i < array.length; i++) {
2229            sb.append(", ");
2230            sb.append(array[i]);
2231        }
2232        sb.append(']');
2233        return sb.toString();
2234    }
2235
2236    /**
2237     * Creates a {@code String} representation of the {@code short[]} passed.
2238     * The result is surrounded by brackets ({@code "[]"}), each
2239     * element is converted to a {@code String} via the
2240     * {@link String#valueOf(int)} and separated by {@code ", "}. If
2241     * the array is {@code null}, then {@code "null"} is returned.
2242     *
2243     * @param array
2244     *            the {@code short} array to convert.
2245     * @return the {@code String} representation of {@code array}.
2246     * @since 1.5
2247     */
2248    public static String toString(short[] array) {
2249        if (array == null) {
2250            return "null";
2251        }
2252        if (array.length == 0) {
2253            return "[]";
2254        }
2255        StringBuilder sb = new StringBuilder(array.length * 6);
2256        sb.append('[');
2257        sb.append(array[0]);
2258        for (int i = 1; i < array.length; i++) {
2259            sb.append(", ");
2260            sb.append(array[i]);
2261        }
2262        sb.append(']');
2263        return sb.toString();
2264    }
2265
2266    /**
2267     * Creates a {@code String} representation of the {@code Object[]} passed.
2268     * The result is surrounded by brackets ({@code "[]"}), each
2269     * element is converted to a {@code String} via the
2270     * {@link String#valueOf(Object)} and separated by {@code ", "}.
2271     * If the array is {@code null}, then {@code "null"} is returned.
2272     *
2273     * @param array
2274     *            the {@code Object} array to convert.
2275     * @return the {@code String} representation of {@code array}.
2276     * @since 1.5
2277     */
2278    public static String toString(Object[] array) {
2279        if (array == null) {
2280            return "null";
2281        }
2282        if (array.length == 0) {
2283            return "[]";
2284        }
2285        StringBuilder sb = new StringBuilder(array.length * 7);
2286        sb.append('[');
2287        sb.append(array[0]);
2288        for (int i = 1; i < array.length; i++) {
2289            sb.append(", ");
2290            sb.append(array[i]);
2291        }
2292        sb.append(']');
2293        return sb.toString();
2294    }
2295
2296    /**
2297     * Creates a <i>"deep"</i> {@code String} representation of the
2298     * {@code Object[]} passed, such that if the array contains other arrays,
2299     * the {@code String} representation of those arrays is generated as well.
2300     * <p>
2301     * If any of the elements are primitive arrays, the generation is delegated
2302     * to the other {@code toString} methods in this class. If any element
2303     * contains a reference to the original array, then it will be represented
2304     * as {@code "[...]"}. If an element is an {@code Object[]}, then its
2305     * representation is generated by a recursive call to this method. All other
2306     * elements are converted via the {@link String#valueOf(Object)} method.
2307     *
2308     * @param array
2309     *            the {@code Object} array to convert.
2310     * @return the {@code String} representation of {@code array}.
2311     * @since 1.5
2312     */
2313    public static String deepToString(Object[] array) {
2314        // Special case null to prevent NPE
2315        if (array == null) {
2316            return "null";
2317        }
2318        // delegate this to the recursive method
2319        StringBuilder buf = new StringBuilder(array.length * 9);
2320        deepToStringImpl(array, new Object[] { array }, buf);
2321        return buf.toString();
2322    }
2323
2324    /**
2325     * Implementation method used by {@link #deepToString(Object[])}.
2326     *
2327     * @param array
2328     *            the {@code Object[]} to dive into.
2329     * @param origArrays
2330     *            the original {@code Object[]}; used to test for self
2331     *            references.
2332     * @param sb
2333     *            the {@code StringBuilder} instance to append to or
2334     *            {@code null} one hasn't been created yet.
2335     * @return the result.
2336     * @see #deepToString(Object[])
2337     */
2338    private static void deepToStringImpl(Object[] array, Object[] origArrays,
2339            StringBuilder sb) {
2340        if (array == null) {
2341            sb.append("null");
2342            return;
2343        }
2344
2345        sb.append('[');
2346
2347        for (int i = 0; i < array.length; i++) {
2348            if (i != 0) {
2349                sb.append(", ");
2350            }
2351            // establish current element
2352            Object elem = array[i];
2353            if (elem == null) {
2354                // element is null
2355                sb.append("null");
2356            } else {
2357                // get the Class of the current element
2358                Class<?> elemClass = elem.getClass();
2359                if (elemClass.isArray()) {
2360                    // element is an array type
2361
2362                    // get the declared Class of the array (element)
2363                    Class<?> elemElemClass = elemClass.getComponentType();
2364                    if (elemElemClass.isPrimitive()) {
2365                        // element is a primitive array
2366                        if (boolean.class.equals(elemElemClass)) {
2367                            sb.append(toString((boolean[]) elem));
2368                        } else if (byte.class.equals(elemElemClass)) {
2369                            sb.append(toString((byte[]) elem));
2370                        } else if (char.class.equals(elemElemClass)) {
2371                            sb.append(toString((char[]) elem));
2372                        } else if (double.class.equals(elemElemClass)) {
2373                            sb.append(toString((double[]) elem));
2374                        } else if (float.class.equals(elemElemClass)) {
2375                            sb.append(toString((float[]) elem));
2376                        } else if (int.class.equals(elemElemClass)) {
2377                            sb.append(toString((int[]) elem));
2378                        } else if (long.class.equals(elemElemClass)) {
2379                            sb.append(toString((long[]) elem));
2380                        } else if (short.class.equals(elemElemClass)) {
2381                            sb.append(toString((short[]) elem));
2382                        } else {
2383                            // no other possible primitives, so we assert that
2384                            throw new AssertionError();
2385                        }
2386                    } else {
2387                        // element is an Object[], so we assert that
2388                        // assert elem instanceof Object[];
2389                        if (deepToStringImplContains(origArrays, elem)) {
2390                            sb.append("[...]");
2391                        } else {
2392                            Object[] newArray = (Object[]) elem;
2393                            Object[] newOrigArrays = new Object[origArrays.length + 1];
2394                            System.arraycopy(origArrays, 0, newOrigArrays, 0,
2395                                    origArrays.length);
2396                            newOrigArrays[origArrays.length] = newArray;
2397                            // make the recursive call to this method
2398                            deepToStringImpl(newArray, newOrigArrays, sb);
2399                        }
2400                    }
2401                } else { // element is NOT an array, just an Object
2402                    sb.append(array[i]);
2403                }
2404            }
2405        }
2406        sb.append(']');
2407    }
2408
2409    /**
2410     * Utility method used to assist the implementation of
2411     * {@link #deepToString(Object[])}.
2412     *
2413     * @param origArrays
2414     *            An array of Object[] references.
2415     * @param array
2416     *            An Object[] reference to look for in {@code origArrays}.
2417     * @return A value of {@code true} if {@code array} is an
2418     *         element in {@code origArrays}.
2419     */
2420    private static boolean deepToStringImplContains(Object[] origArrays,
2421            Object array) {
2422        if (origArrays == null || origArrays.length == 0) {
2423            return false;
2424        }
2425        for (Object element : origArrays) {
2426            if (element == array) {
2427                return true;
2428            }
2429        }
2430        return false;
2431    }
2432
2433    /**
2434     * Copies {@code newLength} elements from {@code original} into a new array.
2435     * If {@code newLength} is greater than {@code original.length}, the result is padded
2436     * with the value {@code false}.
2437     *
2438     * @param original the original array
2439     * @param newLength the length of the new array
2440     * @return the new array
2441     * @throws NegativeArraySizeException if {@code newLength < 0}
2442     * @throws NullPointerException if {@code original == null}
2443     * @since 1.6
2444     */
2445    public static boolean[] copyOf(boolean[] original, int newLength) {
2446        if (newLength < 0) {
2447            throw new NegativeArraySizeException(Integer.toString(newLength));
2448        }
2449        return copyOfRange(original, 0, newLength);
2450    }
2451
2452    /**
2453     * Copies {@code newLength} elements from {@code original} into a new array.
2454     * If {@code newLength} is greater than {@code original.length}, the result is padded
2455     * with the value {@code (byte) 0}.
2456     *
2457     * @param original the original array
2458     * @param newLength the length of the new array
2459     * @return the new array
2460     * @throws NegativeArraySizeException if {@code newLength < 0}
2461     * @throws NullPointerException if {@code original == null}
2462     * @since 1.6
2463     */
2464    public static byte[] copyOf(byte[] original, int newLength) {
2465        if (newLength < 0) {
2466            throw new NegativeArraySizeException(Integer.toString(newLength));
2467        }
2468        return copyOfRange(original, 0, newLength);
2469    }
2470
2471    /**
2472     * Copies {@code newLength} elements from {@code original} into a new array.
2473     * If {@code newLength} is greater than {@code original.length}, the result is padded
2474     * with the value {@code '\\u0000'}.
2475     *
2476     * @param original the original array
2477     * @param newLength the length of the new array
2478     * @return the new array
2479     * @throws NegativeArraySizeException if {@code newLength < 0}
2480     * @throws NullPointerException if {@code original == null}
2481     * @since 1.6
2482     */
2483    public static char[] copyOf(char[] original, int newLength) {
2484        if (newLength < 0) {
2485            throw new NegativeArraySizeException(Integer.toString(newLength));
2486        }
2487        return copyOfRange(original, 0, newLength);
2488    }
2489
2490    /**
2491     * Copies {@code newLength} elements from {@code original} into a new array.
2492     * If {@code newLength} is greater than {@code original.length}, the result is padded
2493     * with the value {@code 0.0d}.
2494     *
2495     * @param original the original array
2496     * @param newLength the length of the new array
2497     * @return the new array
2498     * @throws NegativeArraySizeException if {@code newLength < 0}
2499     * @throws NullPointerException if {@code original == null}
2500     * @since 1.6
2501     */
2502    public static double[] copyOf(double[] original, int newLength) {
2503        if (newLength < 0) {
2504            throw new NegativeArraySizeException(Integer.toString(newLength));
2505        }
2506        return copyOfRange(original, 0, newLength);
2507    }
2508
2509    /**
2510     * Copies {@code newLength} elements from {@code original} into a new array.
2511     * If {@code newLength} is greater than {@code original.length}, the result is padded
2512     * with the value {@code 0.0f}.
2513     *
2514     * @param original the original array
2515     * @param newLength the length of the new array
2516     * @return the new array
2517     * @throws NegativeArraySizeException if {@code newLength < 0}
2518     * @throws NullPointerException if {@code original == null}
2519     * @since 1.6
2520     */
2521    public static float[] copyOf(float[] original, int newLength) {
2522        if (newLength < 0) {
2523            throw new NegativeArraySizeException(Integer.toString(newLength));
2524        }
2525        return copyOfRange(original, 0, newLength);
2526    }
2527
2528    /**
2529     * Copies {@code newLength} elements from {@code original} into a new array.
2530     * If {@code newLength} is greater than {@code original.length}, the result is padded
2531     * with the value {@code 0}.
2532     *
2533     * @param original the original array
2534     * @param newLength the length of the new array
2535     * @return the new array
2536     * @throws NegativeArraySizeException if {@code newLength < 0}
2537     * @throws NullPointerException if {@code original == null}
2538     * @since 1.6
2539     */
2540    public static int[] copyOf(int[] original, int newLength) {
2541        if (newLength < 0) {
2542            throw new NegativeArraySizeException(Integer.toString(newLength));
2543        }
2544        return copyOfRange(original, 0, newLength);
2545    }
2546
2547    /**
2548     * Copies {@code newLength} elements from {@code original} into a new array.
2549     * If {@code newLength} is greater than {@code original.length}, the result is padded
2550     * with the value {@code 0L}.
2551     *
2552     * @param original the original array
2553     * @param newLength the length of the new array
2554     * @return the new array
2555     * @throws NegativeArraySizeException if {@code newLength < 0}
2556     * @throws NullPointerException if {@code original == null}
2557     * @since 1.6
2558     */
2559    public static long[] copyOf(long[] original, int newLength) {
2560        if (newLength < 0) {
2561            throw new NegativeArraySizeException(Integer.toString(newLength));
2562        }
2563        return copyOfRange(original, 0, newLength);
2564    }
2565
2566    /**
2567     * Copies {@code newLength} elements from {@code original} into a new array.
2568     * If {@code newLength} is greater than {@code original.length}, the result is padded
2569     * with the value {@code (short) 0}.
2570     *
2571     * @param original the original array
2572     * @param newLength the length of the new array
2573     * @return the new array
2574     * @throws NegativeArraySizeException if {@code newLength < 0}
2575     * @throws NullPointerException if {@code original == null}
2576     * @since 1.6
2577     */
2578    public static short[] copyOf(short[] original, int newLength) {
2579        if (newLength < 0) {
2580            throw new NegativeArraySizeException(Integer.toString(newLength));
2581        }
2582        return copyOfRange(original, 0, newLength);
2583    }
2584
2585    /**
2586     * Copies {@code newLength} elements from {@code original} into a new array.
2587     * If {@code newLength} is greater than {@code original.length}, the result is padded
2588     * with the value {@code null}.
2589     *
2590     * @param original the original array
2591     * @param newLength the length of the new array
2592     * @return the new array
2593     * @throws NegativeArraySizeException if {@code newLength < 0}
2594     * @throws NullPointerException if {@code original == null}
2595     * @since 1.6
2596     */
2597    public static <T> T[] copyOf(T[] original, int newLength) {
2598        if (original == null) {
2599            throw new NullPointerException("original == null");
2600        }
2601        if (newLength < 0) {
2602            throw new NegativeArraySizeException(Integer.toString(newLength));
2603        }
2604        return copyOfRange(original, 0, newLength);
2605    }
2606
2607    /**
2608     * Copies {@code newLength} elements from {@code original} into a new array.
2609     * If {@code newLength} is greater than {@code original.length}, the result is padded
2610     * with the value {@code null}.
2611     *
2612     * @param original the original array
2613     * @param newLength the length of the new array
2614     * @param newType the class of the new array
2615     * @return the new array
2616     * @throws NegativeArraySizeException if {@code newLength < 0}
2617     * @throws NullPointerException if {@code original == null}
2618     * @throws ArrayStoreException if a value in {@code original} is incompatible with T
2619     * @since 1.6
2620     */
2621    public static <T, U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
2622        // We use the null pointer check in copyOfRange for exception priority compatibility.
2623        if (newLength < 0) {
2624            throw new NegativeArraySizeException(Integer.toString(newLength));
2625        }
2626        return copyOfRange(original, 0, newLength, newType);
2627    }
2628
2629    /**
2630     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2631     * end (exclusive). The original order of elements is preserved.
2632     * If {@code end} is greater than {@code original.length}, the result is padded
2633     * with the value {@code false}.
2634     *
2635     * @param original the original array
2636     * @param start the start index, inclusive
2637     * @param end the end index, exclusive
2638     * @return the new array
2639     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2640     * @throws IllegalArgumentException if {@code start > end}
2641     * @throws NullPointerException if {@code original == null}
2642     * @since 1.6
2643     */
2644    public static boolean[] copyOfRange(boolean[] original, int start, int end) {
2645        if (start > end) {
2646            throw new IllegalArgumentException();
2647        }
2648        int originalLength = original.length;
2649        if (start < 0 || start > originalLength) {
2650            throw new ArrayIndexOutOfBoundsException();
2651        }
2652        int resultLength = end - start;
2653        int copyLength = Math.min(resultLength, originalLength - start);
2654        boolean[] result = new boolean[resultLength];
2655        System.arraycopy(original, start, result, 0, copyLength);
2656        return result;
2657    }
2658
2659    /**
2660     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2661     * end (exclusive). The original order of elements is preserved.
2662     * If {@code end} is greater than {@code original.length}, the result is padded
2663     * with the value {@code (byte) 0}.
2664     *
2665     * @param original the original array
2666     * @param start the start index, inclusive
2667     * @param end the end index, exclusive
2668     * @return the new array
2669     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2670     * @throws IllegalArgumentException if {@code start > end}
2671     * @throws NullPointerException if {@code original == null}
2672     * @since 1.6
2673     */
2674    public static byte[] copyOfRange(byte[] original, int start, int end) {
2675        if (start > end) {
2676            throw new IllegalArgumentException();
2677        }
2678        int originalLength = original.length;
2679        if (start < 0 || start > originalLength) {
2680            throw new ArrayIndexOutOfBoundsException();
2681        }
2682        int resultLength = end - start;
2683        int copyLength = Math.min(resultLength, originalLength - start);
2684        byte[] result = new byte[resultLength];
2685        System.arraycopy(original, start, result, 0, copyLength);
2686        return result;
2687    }
2688
2689    /**
2690     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2691     * end (exclusive). The original order of elements is preserved.
2692     * If {@code end} is greater than {@code original.length}, the result is padded
2693     * with the value {@code '\\u0000'}.
2694     *
2695     * @param original the original array
2696     * @param start the start index, inclusive
2697     * @param end the end index, exclusive
2698     * @return the new array
2699     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2700     * @throws IllegalArgumentException if {@code start > end}
2701     * @throws NullPointerException if {@code original == null}
2702     * @since 1.6
2703     */
2704    public static char[] copyOfRange(char[] original, int start, int end) {
2705        if (start > end) {
2706            throw new IllegalArgumentException();
2707        }
2708        int originalLength = original.length;
2709        if (start < 0 || start > originalLength) {
2710            throw new ArrayIndexOutOfBoundsException();
2711        }
2712        int resultLength = end - start;
2713        int copyLength = Math.min(resultLength, originalLength - start);
2714        char[] result = new char[resultLength];
2715        System.arraycopy(original, start, result, 0, copyLength);
2716        return result;
2717    }
2718
2719    /**
2720     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2721     * end (exclusive). The original order of elements is preserved.
2722     * If {@code end} is greater than {@code original.length}, the result is padded
2723     * with the value {@code 0.0d}.
2724     *
2725     * @param original the original array
2726     * @param start the start index, inclusive
2727     * @param end the end index, exclusive
2728     * @return the new array
2729     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2730     * @throws IllegalArgumentException if {@code start > end}
2731     * @throws NullPointerException if {@code original == null}
2732     * @since 1.6
2733     */
2734    public static double[] copyOfRange(double[] original, int start, int end) {
2735        if (start > end) {
2736            throw new IllegalArgumentException();
2737        }
2738        int originalLength = original.length;
2739        if (start < 0 || start > originalLength) {
2740            throw new ArrayIndexOutOfBoundsException();
2741        }
2742        int resultLength = end - start;
2743        int copyLength = Math.min(resultLength, originalLength - start);
2744        double[] result = new double[resultLength];
2745        System.arraycopy(original, start, result, 0, copyLength);
2746        return result;
2747    }
2748
2749    /**
2750     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2751     * end (exclusive). The original order of elements is preserved.
2752     * If {@code end} is greater than {@code original.length}, the result is padded
2753     * with the value {@code 0.0f}.
2754     *
2755     * @param original the original array
2756     * @param start the start index, inclusive
2757     * @param end the end index, exclusive
2758     * @return the new array
2759     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2760     * @throws IllegalArgumentException if {@code start > end}
2761     * @throws NullPointerException if {@code original == null}
2762     * @since 1.6
2763     */
2764    public static float[] copyOfRange(float[] original, int start, int end) {
2765        if (start > end) {
2766            throw new IllegalArgumentException();
2767        }
2768        int originalLength = original.length;
2769        if (start < 0 || start > originalLength) {
2770            throw new ArrayIndexOutOfBoundsException();
2771        }
2772        int resultLength = end - start;
2773        int copyLength = Math.min(resultLength, originalLength - start);
2774        float[] result = new float[resultLength];
2775        System.arraycopy(original, start, result, 0, copyLength);
2776        return result;
2777    }
2778
2779    /**
2780     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2781     * end (exclusive). The original order of elements is preserved.
2782     * If {@code end} is greater than {@code original.length}, the result is padded
2783     * with the value {@code 0}.
2784     *
2785     * @param original the original array
2786     * @param start the start index, inclusive
2787     * @param end the end index, exclusive
2788     * @return the new array
2789     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2790     * @throws IllegalArgumentException if {@code start > end}
2791     * @throws NullPointerException if {@code original == null}
2792     * @since 1.6
2793     */
2794    public static int[] copyOfRange(int[] original, int start, int end) {
2795        if (start > end) {
2796            throw new IllegalArgumentException();
2797        }
2798        int originalLength = original.length;
2799        if (start < 0 || start > originalLength) {
2800            throw new ArrayIndexOutOfBoundsException();
2801        }
2802        int resultLength = end - start;
2803        int copyLength = Math.min(resultLength, originalLength - start);
2804        int[] result = new int[resultLength];
2805        System.arraycopy(original, start, result, 0, copyLength);
2806        return result;
2807    }
2808
2809    /**
2810     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2811     * end (exclusive). The original order of elements is preserved.
2812     * If {@code end} is greater than {@code original.length}, the result is padded
2813     * with the value {@code 0L}.
2814     *
2815     * @param original the original array
2816     * @param start the start index, inclusive
2817     * @param end the end index, exclusive
2818     * @return the new array
2819     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2820     * @throws IllegalArgumentException if {@code start > end}
2821     * @throws NullPointerException if {@code original == null}
2822     * @since 1.6
2823     */
2824    public static long[] copyOfRange(long[] original, int start, int end) {
2825        if (start > end) {
2826            throw new IllegalArgumentException();
2827        }
2828        int originalLength = original.length;
2829        if (start < 0 || start > originalLength) {
2830            throw new ArrayIndexOutOfBoundsException();
2831        }
2832        int resultLength = end - start;
2833        int copyLength = Math.min(resultLength, originalLength - start);
2834        long[] result = new long[resultLength];
2835        System.arraycopy(original, start, result, 0, copyLength);
2836        return result;
2837    }
2838
2839    /**
2840     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2841     * end (exclusive). The original order of elements is preserved.
2842     * If {@code end} is greater than {@code original.length}, the result is padded
2843     * with the value {@code (short) 0}.
2844     *
2845     * @param original the original array
2846     * @param start the start index, inclusive
2847     * @param end the end index, exclusive
2848     * @return the new array
2849     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2850     * @throws IllegalArgumentException if {@code start > end}
2851     * @throws NullPointerException if {@code original == null}
2852     * @since 1.6
2853     */
2854    public static short[] copyOfRange(short[] original, int start, int end) {
2855        if (start > end) {
2856            throw new IllegalArgumentException();
2857        }
2858        int originalLength = original.length;
2859        if (start < 0 || start > originalLength) {
2860            throw new ArrayIndexOutOfBoundsException();
2861        }
2862        int resultLength = end - start;
2863        int copyLength = Math.min(resultLength, originalLength - start);
2864        short[] result = new short[resultLength];
2865        System.arraycopy(original, start, result, 0, copyLength);
2866        return result;
2867    }
2868
2869    /**
2870     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2871     * end (exclusive). The original order of elements is preserved.
2872     * If {@code end} is greater than {@code original.length}, the result is padded
2873     * with the value {@code null}.
2874     *
2875     * @param original the original array
2876     * @param start the start index, inclusive
2877     * @param end the end index, exclusive
2878     * @return the new array
2879     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2880     * @throws IllegalArgumentException if {@code start > end}
2881     * @throws NullPointerException if {@code original == null}
2882     * @since 1.6
2883     */
2884    @SuppressWarnings("unchecked")
2885    public static <T> T[] copyOfRange(T[] original, int start, int end) {
2886        int originalLength = original.length; // For exception priority compatibility.
2887        if (start > end) {
2888            throw new IllegalArgumentException();
2889        }
2890        if (start < 0 || start > originalLength) {
2891            throw new ArrayIndexOutOfBoundsException();
2892        }
2893        int resultLength = end - start;
2894        int copyLength = Math.min(resultLength, originalLength - start);
2895        T[] result = (T[]) Array.newInstance(original.getClass().getComponentType(), resultLength);
2896        System.arraycopy(original, start, result, 0, copyLength);
2897        return result;
2898    }
2899
2900    /**
2901     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2902     * end (exclusive). The original order of elements is preserved.
2903     * If {@code end} is greater than {@code original.length}, the result is padded
2904     * with the value {@code null}.
2905     *
2906     * @param original the original array
2907     * @param start the start index, inclusive
2908     * @param end the end index, exclusive
2909     * @return the new array
2910     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2911     * @throws IllegalArgumentException if {@code start > end}
2912     * @throws NullPointerException if {@code original == null}
2913     * @throws ArrayStoreException if a value in {@code original} is incompatible with T
2914     * @since 1.6
2915     */
2916    @SuppressWarnings("unchecked")
2917    public static <T, U> T[] copyOfRange(U[] original, int start, int end, Class<? extends T[]> newType) {
2918        if (start > end) {
2919            throw new IllegalArgumentException();
2920        }
2921        int originalLength = original.length;
2922        if (start < 0 || start > originalLength) {
2923            throw new ArrayIndexOutOfBoundsException();
2924        }
2925        int resultLength = end - start;
2926        int copyLength = Math.min(resultLength, originalLength - start);
2927        T[] result = (T[]) Array.newInstance(newType.getComponentType(), resultLength);
2928        System.arraycopy(original, start, result, 0, copyLength);
2929        return result;
2930    }
2931}
2932