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 (element instanceof Object[]) {
1323            return deepHashCode((Object[]) element);
1324        } else if (cl == int.class) {
1325            return hashCode((int[]) element);
1326        } else if (cl == char.class) {
1327            return hashCode((char[]) element);
1328        } else if (cl == boolean.class) {
1329            return hashCode((boolean[]) element);
1330        } else if (cl == byte.class) {
1331            return hashCode((byte[]) element);
1332        } else if (cl == long.class) {
1333            return hashCode((long[]) element);
1334        } else if (cl == float.class) {
1335            return hashCode((float[]) element);
1336        } else if (cl == double.class) {
1337            return hashCode((double[]) element);
1338        } else {
1339            return hashCode((short[]) element);
1340        }
1341    }
1342
1343    /**
1344     * Compares the two arrays.
1345     *
1346     * @param array1
1347     *            the first {@code byte} array.
1348     * @param array2
1349     *            the second {@code byte} array.
1350     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1351     *         same length and the elements at each index in the two arrays are
1352     *         equal, {@code false} otherwise.
1353     */
1354    public static boolean equals(byte[] array1, byte[] array2) {
1355        if (array1 == array2) {
1356            return true;
1357        }
1358        if (array1 == null || array2 == null || array1.length != array2.length) {
1359            return false;
1360        }
1361        for (int i = 0; i < array1.length; i++) {
1362            if (array1[i] != array2[i]) {
1363                return false;
1364            }
1365        }
1366        return true;
1367    }
1368
1369    /**
1370     * Compares the two arrays.
1371     *
1372     * @param array1
1373     *            the first {@code short} array.
1374     * @param array2
1375     *            the second {@code short} array.
1376     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1377     *         same length and the elements at each index in the two arrays are
1378     *         equal, {@code false} otherwise.
1379     */
1380    public static boolean equals(short[] array1, short[] array2) {
1381        if (array1 == array2) {
1382            return true;
1383        }
1384        if (array1 == null || array2 == null || array1.length != array2.length) {
1385            return false;
1386        }
1387        for (int i = 0; i < array1.length; i++) {
1388            if (array1[i] != array2[i]) {
1389                return false;
1390            }
1391        }
1392        return true;
1393    }
1394
1395    /**
1396     * Compares the two arrays.
1397     *
1398     * @param array1
1399     *            the first {@code char} array.
1400     * @param array2
1401     *            the second {@code char} array.
1402     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1403     *         same length and the elements at each index in the two arrays are
1404     *         equal, {@code false} otherwise.
1405     */
1406    public static boolean equals(char[] array1, char[] array2) {
1407        if (array1 == array2) {
1408            return true;
1409        }
1410        if (array1 == null || array2 == null || array1.length != array2.length) {
1411            return false;
1412        }
1413        for (int i = 0; i < array1.length; i++) {
1414            if (array1[i] != array2[i]) {
1415                return false;
1416            }
1417        }
1418        return true;
1419    }
1420
1421    /**
1422     * Compares the two arrays.
1423     *
1424     * @param array1
1425     *            the first {@code int} array.
1426     * @param array2
1427     *            the second {@code int} array.
1428     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1429     *         same length and the elements at each index in the two arrays are
1430     *         equal, {@code false} otherwise.
1431     */
1432    public static boolean equals(int[] array1, int[] array2) {
1433        if (array1 == array2) {
1434            return true;
1435        }
1436        if (array1 == null || array2 == null || array1.length != array2.length) {
1437            return false;
1438        }
1439        for (int i = 0; i < array1.length; i++) {
1440            if (array1[i] != array2[i]) {
1441                return false;
1442            }
1443        }
1444        return true;
1445    }
1446
1447    /**
1448     * Compares the two arrays.
1449     *
1450     * @param array1
1451     *            the first {@code long} array.
1452     * @param array2
1453     *            the second {@code long} array.
1454     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1455     *         same length and the elements at each index in the two arrays are
1456     *         equal, {@code false} otherwise.
1457     */
1458    public static boolean equals(long[] array1, long[] array2) {
1459        if (array1 == array2) {
1460            return true;
1461        }
1462        if (array1 == null || array2 == null || array1.length != array2.length) {
1463            return false;
1464        }
1465        for (int i = 0; i < array1.length; i++) {
1466            if (array1[i] != array2[i]) {
1467                return false;
1468            }
1469        }
1470        return true;
1471    }
1472
1473    /**
1474     * Compares the two arrays. The values are compared in the same manner as
1475     * {@code Float.equals()}.
1476     *
1477     * @param array1
1478     *            the first {@code float} array.
1479     * @param array2
1480     *            the second {@code float} array.
1481     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1482     *         same length and the elements at each index in the two arrays are
1483     *         equal, {@code false} otherwise.
1484     * @see Float#equals(Object)
1485     */
1486    public static boolean equals(float[] array1, float[] array2) {
1487        if (array1 == array2) {
1488            return true;
1489        }
1490        if (array1 == null || array2 == null || array1.length != array2.length) {
1491            return false;
1492        }
1493        for (int i = 0; i < array1.length; i++) {
1494            if (Float.floatToIntBits(array1[i]) != Float
1495                    .floatToIntBits(array2[i])) {
1496                return false;
1497            }
1498        }
1499        return true;
1500    }
1501
1502    /**
1503     * Compares the two arrays. The values are compared in the same manner as
1504     * {@code Double.equals()}.
1505     *
1506     * @param array1
1507     *            the first {@code double} array.
1508     * @param array2
1509     *            the second {@code double} array.
1510     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1511     *         same length and the elements at each index in the two arrays are
1512     *         equal, {@code false} otherwise.
1513     * @see Double#equals(Object)
1514     */
1515    public static boolean equals(double[] array1, double[] array2) {
1516        if (array1 == array2) {
1517            return true;
1518        }
1519        if (array1 == null || array2 == null || array1.length != array2.length) {
1520            return false;
1521        }
1522        for (int i = 0; i < array1.length; i++) {
1523            if (Double.doubleToLongBits(array1[i]) != Double
1524                    .doubleToLongBits(array2[i])) {
1525                return false;
1526            }
1527        }
1528        return true;
1529    }
1530
1531    /**
1532     * Compares the two arrays.
1533     *
1534     * @param array1
1535     *            the first {@code boolean} array.
1536     * @param array2
1537     *            the second {@code boolean} array.
1538     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1539     *         same length and the elements at each index in the two arrays are
1540     *         equal, {@code false} otherwise.
1541     */
1542    public static boolean equals(boolean[] array1, boolean[] array2) {
1543        if (array1 == array2) {
1544            return true;
1545        }
1546        if (array1 == null || array2 == null || array1.length != array2.length) {
1547            return false;
1548        }
1549        for (int i = 0; i < array1.length; i++) {
1550            if (array1[i] != array2[i]) {
1551                return false;
1552            }
1553        }
1554        return true;
1555    }
1556
1557    /**
1558     * Compares the two arrays.
1559     *
1560     * @param array1
1561     *            the first {@code Object} array.
1562     * @param array2
1563     *            the second {@code Object} array.
1564     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1565     *         same length and the elements at each index in the two arrays are
1566     *         equal according to {@code equals()}, {@code false} otherwise.
1567     */
1568    public static boolean equals(Object[] array1, Object[] array2) {
1569        if (array1 == array2) {
1570            return true;
1571        }
1572        if (array1 == null || array2 == null || array1.length != array2.length) {
1573            return false;
1574        }
1575        for (int i = 0; i < array1.length; i++) {
1576            Object e1 = array1[i], e2 = array2[i];
1577            if (!(e1 == null ? e2 == null : e1.equals(e2))) {
1578                return false;
1579            }
1580        }
1581        return true;
1582    }
1583
1584    /**
1585     * Returns {@code true} if the two given arrays are deeply equal to one another.
1586     * Unlike the method {@code equals(Object[] array1, Object[] array2)}, this method
1587     * is appropriate for use for nested arrays of arbitrary depth.
1588     * <p>
1589     * Two array references are considered deeply equal if they are both {@code null},
1590     * or if they refer to arrays that have the same length and the elements at
1591     * each index in the two arrays are equal.
1592     * <p>
1593     * Two {@code null} elements {@code element1} and {@code element2} are possibly deeply equal if any
1594     * of the following conditions satisfied:
1595     * <p>
1596     * {@code element1} and {@code element2} are both arrays of object reference types, and
1597     * {@code Arrays.deepEquals(element1, element2)} would return {@code true}.
1598     * <p>
1599     * {@code element1} and {@code element2} are arrays of the same primitive type, and the
1600     * appropriate overloading of {@code Arrays.equals(element1, element2)} would return
1601     * {@code true}.
1602     * <p>
1603     * {@code element1 == element2}
1604     * <p>
1605     * {@code element1.equals(element2)} would return {@code true}.
1606     * <p>
1607     * Note that this definition permits {@code null} elements at any depth.
1608     * <p>
1609     * If either of the given arrays contain themselves as elements, the
1610     * behavior of this method is uncertain.
1611     *
1612     * @param array1
1613     *            the first {@code Object} array.
1614     * @param array2
1615     *            the second {@code Object} array.
1616     * @return {@code true} if both arrays are {@code null} or if the arrays have the
1617     *         same length and the elements at each index in the two arrays are
1618     *         equal according to {@code equals()}, {@code false} otherwise.
1619     */
1620    public static boolean deepEquals(Object[] array1, Object[] array2) {
1621        if (array1 == array2) {
1622            return true;
1623        }
1624        if (array1 == null || array2 == null || array1.length != array2.length) {
1625            return false;
1626        }
1627        for (int i = 0; i < array1.length; i++) {
1628            Object e1 = array1[i], e2 = array2[i];
1629
1630            if (!deepEqualsElements(e1, e2)) {
1631                return false;
1632            }
1633        }
1634        return true;
1635    }
1636
1637    private static boolean deepEqualsElements(Object e1, Object e2) {
1638        Class<?> cl1, cl2;
1639
1640        if (e1 == e2) {
1641            return true;
1642        }
1643
1644        if (e1 == null || e2 == null) {
1645            return false;
1646        }
1647
1648        cl1 = e1.getClass().getComponentType();
1649        cl2 = e2.getClass().getComponentType();
1650
1651        if (cl1 != cl2) {
1652            return false;
1653        }
1654
1655        if (cl1 == null) {
1656            return e1.equals(e2);
1657        }
1658
1659        /*
1660         * compare as arrays
1661         */
1662        if (e1 instanceof Object[]) {
1663            return deepEquals((Object[]) e1, (Object[]) e2);
1664        } else if (cl1 == int.class) {
1665            return equals((int[]) e1, (int[]) e2);
1666        } else if (cl1 == char.class) {
1667            return equals((char[]) e1, (char[]) e2);
1668        } else if (cl1 == boolean.class) {
1669            return equals((boolean[]) e1, (boolean[]) e2);
1670        } else if (cl1 == byte.class) {
1671            return equals((byte[]) e1, (byte[]) e2);
1672        } else if (cl1 == long.class) {
1673            return equals((long[]) e1, (long[]) e2);
1674        } else if (cl1 == float.class) {
1675            return equals((float[]) e1, (float[]) e2);
1676        } else if (cl1 == double.class) {
1677            return equals((double[]) e1, (double[]) e2);
1678        } else {
1679            return equals((short[]) e1, (short[]) e2);
1680        }
1681    }
1682
1683    /**
1684     * Sorts the specified array in ascending numerical order.
1685     *
1686     * @param array
1687     *            the {@code byte} array to be sorted.
1688     */
1689    public static void sort(byte[] array) {
1690        DualPivotQuicksort.sort(array);
1691    }
1692
1693    /**
1694     * Sorts the specified range in the array in ascending numerical order.
1695     *
1696     * @param array
1697     *            the {@code byte} array to be sorted.
1698     * @param start
1699     *            the start index to sort.
1700     * @param end
1701     *            the last + 1 index to sort.
1702     * @throws IllegalArgumentException
1703     *                if {@code start > end}.
1704     * @throws ArrayIndexOutOfBoundsException
1705     *                if {@code start < 0} or {@code end > array.length}.
1706     */
1707    public static void sort(byte[] array, int start, int end) {
1708        DualPivotQuicksort.sort(array, start, end);
1709    }
1710
1711    /**
1712     * Checks that the range described by {@code offset} and {@code count} doesn't exceed
1713     * {@code arrayLength}.
1714     *
1715     * @hide
1716     */
1717    public static void checkOffsetAndCount(int arrayLength, int offset, int count) {
1718        if ((offset | count) < 0 || offset > arrayLength || arrayLength - offset < count) {
1719            throw new ArrayIndexOutOfBoundsException(arrayLength, offset,
1720                    count);
1721        }
1722    }
1723
1724    /**
1725     * Checks that the range described by {@code start} and {@code end} doesn't exceed
1726     * {@code len}.
1727     *
1728     * @hide
1729     */
1730    public static void checkStartAndEnd(int len, int start, int end) {
1731        if (start < 0 || end > len) {
1732            throw new ArrayIndexOutOfBoundsException("start < 0 || end > len."
1733                    + " start=" + start + ", end=" + end + ", len=" + len);
1734        }
1735        if (start > end) {
1736            throw new IllegalArgumentException("start > end: " + start + " > " + end);
1737        }
1738    }
1739
1740    /**
1741     * Sorts the specified array in ascending numerical order.
1742     *
1743     * @param array
1744     *            the {@code char} array to be sorted.
1745     */
1746    public static void sort(char[] array) {
1747        DualPivotQuicksort.sort(array);
1748    }
1749
1750    /**
1751     * Sorts the specified range in the array in ascending numerical order.
1752     *
1753     * @param array
1754     *            the {@code char} array to be sorted.
1755     * @param start
1756     *            the start index to sort.
1757     * @param end
1758     *            the last + 1 index to sort.
1759     * @throws IllegalArgumentException
1760     *                if {@code start > end}.
1761     * @throws ArrayIndexOutOfBoundsException
1762     *                if {@code start < 0} or {@code end > array.length}.
1763     */
1764    public static void sort(char[] array, int start, int end) {
1765        DualPivotQuicksort.sort(array, start, end);
1766    }
1767
1768    /**
1769     * Sorts the specified array in ascending numerical order.
1770     *
1771     * @param array
1772     *            the {@code double} array to be sorted.
1773     * @see #sort(double[], int, int)
1774     */
1775    public static void sort(double[] array) {
1776        DualPivotQuicksort.sort(array);
1777    }
1778
1779    /**
1780     * Sorts the specified range in the array in ascending numerical order. The
1781     * values are sorted according to the order imposed by {@code Double.compareTo()}.
1782     *
1783     * @param array
1784     *            the {@code double} array to be sorted.
1785     * @param start
1786     *            the start index to sort.
1787     * @param end
1788     *            the last + 1 index to sort.
1789     * @throws IllegalArgumentException
1790     *                if {@code start > end}.
1791     * @throws ArrayIndexOutOfBoundsException
1792     *                if {@code start < 0} or {@code end > array.length}.
1793     * @see Double#compareTo(Double)
1794     */
1795    public static void sort(double[] array, int start, int end) {
1796        DualPivotQuicksort.sort(array, start, end);
1797    }
1798
1799    /**
1800     * Sorts the specified array in ascending numerical order.
1801     *
1802     * @param array
1803     *            the {@code float} array to be sorted.
1804     * @see #sort(float[], int, int)
1805     */
1806    public static void sort(float[] array) {
1807        DualPivotQuicksort.sort(array);
1808    }
1809
1810    /**
1811     * Sorts the specified range in the array in ascending numerical order. The
1812     * values are sorted according to the order imposed by {@code Float.compareTo()}.
1813     *
1814     * @param array
1815     *            the {@code float} array to be sorted.
1816     * @param start
1817     *            the start index to sort.
1818     * @param end
1819     *            the last + 1 index to sort.
1820     * @throws IllegalArgumentException
1821     *                if {@code start > end}.
1822     * @throws ArrayIndexOutOfBoundsException
1823     *                if {@code start < 0} or {@code end > array.length}.
1824     * @see Float#compareTo(Float)
1825     */
1826    public static void sort(float[] array, int start, int end) {
1827        DualPivotQuicksort.sort(array, start, end);
1828    }
1829
1830    /**
1831     * Sorts the specified array in ascending numerical order.
1832     *
1833     * @param array
1834     *            the {@code int} array to be sorted.
1835     */
1836    public static void sort(int[] array) {
1837        DualPivotQuicksort.sort(array);
1838    }
1839
1840    /**
1841     * Sorts the specified range in the array in ascending numerical order.
1842     *
1843     * @param array
1844     *            the {@code int} array to be sorted.
1845     * @param start
1846     *            the start index to sort.
1847     * @param end
1848     *            the last + 1 index to sort.
1849     * @throws IllegalArgumentException
1850     *                if {@code start > end}.
1851     * @throws ArrayIndexOutOfBoundsException
1852     *                if {@code start < 0} or {@code end > array.length}.
1853     */
1854    public static void sort(int[] array, int start, int end) {
1855        DualPivotQuicksort.sort(array, start, end);
1856    }
1857
1858    /**
1859     * Sorts the specified array in ascending numerical order.
1860     *
1861     * @param array
1862     *            the {@code long} array to be sorted.
1863     */
1864    public static void sort(long[] array) {
1865        DualPivotQuicksort.sort(array);
1866    }
1867
1868    /**
1869     * Sorts the specified range in the array in ascending numerical order.
1870     *
1871     * @param array
1872     *            the {@code long} array to be sorted.
1873     * @param start
1874     *            the start index to sort.
1875     * @param end
1876     *            the last + 1 index to sort.
1877     * @throws IllegalArgumentException
1878     *                if {@code start > end}.
1879     * @throws ArrayIndexOutOfBoundsException
1880     *                if {@code start < 0} or {@code end > array.length}.
1881     */
1882    public static void sort(long[] array, int start, int end) {
1883        DualPivotQuicksort.sort(array, start, end);
1884    }
1885
1886    /**
1887     * Sorts the specified array in ascending numerical order.
1888     *
1889     * @param array
1890     *            the {@code short} array to be sorted.
1891     */
1892    public static void sort(short[] array) {
1893        DualPivotQuicksort.sort(array);
1894    }
1895
1896    /**
1897     * Sorts the specified range in the array in ascending numerical order.
1898     *
1899     * @param array
1900     *            the {@code short} array to be sorted.
1901     * @param start
1902     *            the start index to sort.
1903     * @param end
1904     *            the last + 1 index to sort.
1905     * @throws IllegalArgumentException
1906     *                if {@code start > end}.
1907     * @throws ArrayIndexOutOfBoundsException
1908     *                if {@code start < 0} or {@code end > array.length}.
1909     */
1910    public static void sort(short[] array, int start, int end) {
1911        DualPivotQuicksort.sort(array, start, end);
1912    }
1913
1914// BEGIN android-note
1915
1916    /*
1917     * <p>If this platform has an optimizing VM, check whether ComparableTimSort
1918     * offers any performance benefit over TimSort in conjunction with a
1919     * comparator that returns:
1920     *    {@code ((Comparable)first).compareTo(Second)}.
1921     * If not, you are better off deleting ComparableTimSort to eliminate the
1922     * code duplication.  In other words, the commented out code below
1923     * is the preferable implementation for sorting arrays of Comparables if it
1924     * offers sufficient performance.
1925     */
1926
1927//    /**
1928//     * A comparator that implements the natural order of a group of
1929//     * mutually comparable elements.  Using this comparator saves us
1930//     * from duplicating most of the code in this file (one version for
1931//     * Comparables, one for explicit comparators).
1932//     */
1933//    private static final Comparator<Object> NATURAL_ORDER = new Comparator<Object>() {
1934//        @SuppressWarnings("unchecked")
1935//        public int compare(Object first, Object second) {
1936//            return ((Comparable<Object>)first).compareTo(second);
1937//        }
1938//    };
1939//
1940//    public static void sort(Object[] a) {
1941//        sort(a, 0, a.length, NATURAL_ORDER);
1942//    }
1943//
1944//    public static void sort(Object[] a, int fromIndex, int toIndex) {
1945//        sort(a, fromIndex, toIndex, NATURAL_ORDER);
1946//    }
1947
1948// END android-note
1949
1950    /**
1951     * Sorts the specified array in ascending natural order.
1952     *
1953     * @throws ClassCastException if any element does not implement {@code Comparable},
1954     *     or if {@code compareTo} throws for any pair of elements.
1955     */
1956    public static void sort(Object[] array) {
1957        ComparableTimSort.sort(array);
1958    }
1959
1960    /**
1961     * Sorts the specified range in the array in ascending natural order.
1962     *
1963     * @param start
1964     *            the start index to sort.
1965     * @param end
1966     *            the last + 1 index to sort.
1967     * @throws ClassCastException if any element does not implement {@code Comparable},
1968     *     or if {@code compareTo} throws for any pair of elements.
1969     * @throws IllegalArgumentException
1970     *                if {@code start > end}.
1971     * @throws ArrayIndexOutOfBoundsException
1972     *                if {@code start < 0} or {@code end > array.length}.
1973     */
1974    public static void sort(Object[] array, int start, int end) {
1975        ComparableTimSort.sort(array, start, end);
1976    }
1977
1978    /**
1979     * Sorts the specified range in the array using the specified {@code Comparator}.
1980     * All elements must be comparable to each other without a
1981     * {@code ClassCastException} being thrown.
1982     *
1983     * @param start
1984     *            the start index to sort.
1985     * @param end
1986     *            the last + 1 index to sort.
1987     * @param comparator
1988     *            the {@code Comparator}.
1989     * @throws ClassCastException
1990     *                if elements in the array cannot be compared to each other
1991     *                using the given {@code Comparator}.
1992     * @throws IllegalArgumentException
1993     *                if {@code start > end}.
1994     * @throws ArrayIndexOutOfBoundsException
1995     *                if {@code start < 0} or {@code end > array.length}.
1996     */
1997    public static <T> void sort(T[] array, int start, int end, Comparator<? super T> comparator) {
1998        TimSort.sort(array, start, end, comparator);
1999    }
2000
2001    /**
2002     * Sorts the specified array using the specified {@code Comparator}. All elements
2003     * must be comparable to each other without a {@code ClassCastException} being thrown.
2004     *
2005     * @throws ClassCastException
2006     *                if elements in the array cannot be compared to each other
2007     *                using the {@code Comparator}.
2008     */
2009    public static <T> void sort(T[] array, Comparator<? super T> comparator) {
2010        TimSort.sort(array, comparator);
2011    }
2012
2013    /**
2014     * Creates a {@code String} representation of the {@code boolean[]} passed.
2015     * The result is surrounded by brackets ({@code "[]"}), each
2016     * element is converted to a {@code String} via the
2017     * {@link String#valueOf(boolean)} and separated by {@code ", "}.
2018     * If the array is {@code null}, then {@code "null"} is returned.
2019     *
2020     * @param array
2021     *            the {@code boolean} array to convert.
2022     * @return the {@code String} representation of {@code array}.
2023     * @since 1.5
2024     */
2025    public static String toString(boolean[] array) {
2026        if (array == null) {
2027            return "null";
2028        }
2029        if (array.length == 0) {
2030            return "[]";
2031        }
2032        StringBuilder sb = new StringBuilder(array.length * 7);
2033        sb.append('[');
2034        sb.append(array[0]);
2035        for (int i = 1; i < array.length; i++) {
2036            sb.append(", ");
2037            sb.append(array[i]);
2038        }
2039        sb.append(']');
2040        return sb.toString();
2041    }
2042
2043    /**
2044     * Creates a {@code String} representation of the {@code byte[]} passed. The
2045     * result is surrounded by brackets ({@code "[]"}), each element
2046     * is converted to a {@code String} via the {@link String#valueOf(int)} and
2047     * separated by {@code ", "}. If the array is {@code null}, then
2048     * {@code "null"} is returned.
2049     *
2050     * @param array
2051     *            the {@code byte} array to convert.
2052     * @return the {@code String} representation of {@code array}.
2053     * @since 1.5
2054     */
2055    public static String toString(byte[] array) {
2056        if (array == null) {
2057            return "null";
2058        }
2059        if (array.length == 0) {
2060            return "[]";
2061        }
2062        StringBuilder sb = new StringBuilder(array.length * 6);
2063        sb.append('[');
2064        sb.append(array[0]);
2065        for (int i = 1; i < array.length; i++) {
2066            sb.append(", ");
2067            sb.append(array[i]);
2068        }
2069        sb.append(']');
2070        return sb.toString();
2071    }
2072
2073    /**
2074     * Creates a {@code String} representation of the {@code char[]} passed. The
2075     * result is surrounded by brackets ({@code "[]"}), each element
2076     * is converted to a {@code String} via the {@link String#valueOf(char)} and
2077     * separated by {@code ", "}. If the array is {@code null}, then
2078     * {@code "null"} is returned.
2079     *
2080     * @param array
2081     *            the {@code char} array to convert.
2082     * @return the {@code String} representation of {@code array}.
2083     * @since 1.5
2084     */
2085    public static String toString(char[] array) {
2086        if (array == null) {
2087            return "null";
2088        }
2089        if (array.length == 0) {
2090            return "[]";
2091        }
2092        StringBuilder sb = new StringBuilder(array.length * 3);
2093        sb.append('[');
2094        sb.append(array[0]);
2095        for (int i = 1; i < array.length; i++) {
2096            sb.append(", ");
2097            sb.append(array[i]);
2098        }
2099        sb.append(']');
2100        return sb.toString();
2101    }
2102
2103    /**
2104     * Creates a {@code String} representation of the {@code double[]} passed.
2105     * The result is surrounded by brackets ({@code "[]"}), each
2106     * element is converted to a {@code String} via the
2107     * {@link String#valueOf(double)} and separated by {@code ", "}.
2108     * If the array is {@code null}, then {@code "null"} is returned.
2109     *
2110     * @param array
2111     *            the {@code double} array to convert.
2112     * @return the {@code String} representation of {@code array}.
2113     * @since 1.5
2114     */
2115    public static String toString(double[] array) {
2116        if (array == null) {
2117            return "null";
2118        }
2119        if (array.length == 0) {
2120            return "[]";
2121        }
2122        StringBuilder sb = new StringBuilder(array.length * 7);
2123        sb.append('[');
2124        sb.append(array[0]);
2125        for (int i = 1; i < array.length; i++) {
2126            sb.append(", ");
2127            sb.append(array[i]);
2128        }
2129        sb.append(']');
2130        return sb.toString();
2131    }
2132
2133    /**
2134     * Creates a {@code String} representation of the {@code float[]} passed.
2135     * The result is surrounded by brackets ({@code "[]"}), each
2136     * element is converted to a {@code String} via the
2137     * {@link String#valueOf(float)} and separated by {@code ", "}.
2138     * If the array is {@code null}, then {@code "null"} is returned.
2139     *
2140     * @param array
2141     *            the {@code float} array to convert.
2142     * @return the {@code String} representation of {@code array}.
2143     * @since 1.5
2144     */
2145    public static String toString(float[] array) {
2146        if (array == null) {
2147            return "null";
2148        }
2149        if (array.length == 0) {
2150            return "[]";
2151        }
2152        StringBuilder sb = new StringBuilder(array.length * 7);
2153        sb.append('[');
2154        sb.append(array[0]);
2155        for (int i = 1; i < array.length; i++) {
2156            sb.append(", ");
2157            sb.append(array[i]);
2158        }
2159        sb.append(']');
2160        return sb.toString();
2161    }
2162
2163    /**
2164     * Creates a {@code String} representation of the {@code int[]} passed. The
2165     * result is surrounded by brackets ({@code "[]"}), each element
2166     * is converted to a {@code String} via the {@link String#valueOf(int)} and
2167     * separated by {@code ", "}. If the array is {@code null}, then
2168     * {@code "null"} is returned.
2169     *
2170     * @param array
2171     *            the {@code int} array to convert.
2172     * @return the {@code String} representation of {@code array}.
2173     * @since 1.5
2174     */
2175    public static String toString(int[] array) {
2176        if (array == null) {
2177            return "null";
2178        }
2179        if (array.length == 0) {
2180            return "[]";
2181        }
2182        StringBuilder sb = new StringBuilder(array.length * 6);
2183        sb.append('[');
2184        sb.append(array[0]);
2185        for (int i = 1; i < array.length; i++) {
2186            sb.append(", ");
2187            sb.append(array[i]);
2188        }
2189        sb.append(']');
2190        return sb.toString();
2191    }
2192
2193    /**
2194     * Creates a {@code String} representation of the {@code long[]} passed. The
2195     * result is surrounded by brackets ({@code "[]"}), each element
2196     * is converted to a {@code String} via the {@link String#valueOf(long)} and
2197     * separated by {@code ", "}. If the array is {@code null}, then
2198     * {@code "null"} is returned.
2199     *
2200     * @param array
2201     *            the {@code long} array to convert.
2202     * @return the {@code String} representation of {@code array}.
2203     * @since 1.5
2204     */
2205    public static String toString(long[] array) {
2206        if (array == null) {
2207            return "null";
2208        }
2209        if (array.length == 0) {
2210            return "[]";
2211        }
2212        StringBuilder sb = new StringBuilder(array.length * 6);
2213        sb.append('[');
2214        sb.append(array[0]);
2215        for (int i = 1; i < array.length; i++) {
2216            sb.append(", ");
2217            sb.append(array[i]);
2218        }
2219        sb.append(']');
2220        return sb.toString();
2221    }
2222
2223    /**
2224     * Creates a {@code String} representation of the {@code short[]} passed.
2225     * The result is surrounded by brackets ({@code "[]"}), each
2226     * element is converted to a {@code String} via the
2227     * {@link String#valueOf(int)} and separated by {@code ", "}. If
2228     * the array is {@code null}, then {@code "null"} is returned.
2229     *
2230     * @param array
2231     *            the {@code short} array to convert.
2232     * @return the {@code String} representation of {@code array}.
2233     * @since 1.5
2234     */
2235    public static String toString(short[] array) {
2236        if (array == null) {
2237            return "null";
2238        }
2239        if (array.length == 0) {
2240            return "[]";
2241        }
2242        StringBuilder sb = new StringBuilder(array.length * 6);
2243        sb.append('[');
2244        sb.append(array[0]);
2245        for (int i = 1; i < array.length; i++) {
2246            sb.append(", ");
2247            sb.append(array[i]);
2248        }
2249        sb.append(']');
2250        return sb.toString();
2251    }
2252
2253    /**
2254     * Creates a {@code String} representation of the {@code Object[]} passed.
2255     * The result is surrounded by brackets ({@code "[]"}), each
2256     * element is converted to a {@code String} via the
2257     * {@link String#valueOf(Object)} and separated by {@code ", "}.
2258     * If the array is {@code null}, then {@code "null"} is returned.
2259     *
2260     * @param array
2261     *            the {@code Object} array to convert.
2262     * @return the {@code String} representation of {@code array}.
2263     * @since 1.5
2264     */
2265    public static String toString(Object[] array) {
2266        if (array == null) {
2267            return "null";
2268        }
2269        if (array.length == 0) {
2270            return "[]";
2271        }
2272        StringBuilder sb = new StringBuilder(array.length * 7);
2273        sb.append('[');
2274        sb.append(array[0]);
2275        for (int i = 1; i < array.length; i++) {
2276            sb.append(", ");
2277            sb.append(array[i]);
2278        }
2279        sb.append(']');
2280        return sb.toString();
2281    }
2282
2283    /**
2284     * Creates a <i>"deep"</i> {@code String} representation of the
2285     * {@code Object[]} passed, such that if the array contains other arrays,
2286     * the {@code String} representation of those arrays is generated as well.
2287     * <p>
2288     * If any of the elements are primitive arrays, the generation is delegated
2289     * to the other {@code toString} methods in this class. If any element
2290     * contains a reference to the original array, then it will be represented
2291     * as {@code "[...]"}. If an element is an {@code Object[]}, then its
2292     * representation is generated by a recursive call to this method. All other
2293     * elements are converted via the {@link String#valueOf(Object)} method.
2294     *
2295     * @param array
2296     *            the {@code Object} array to convert.
2297     * @return the {@code String} representation of {@code array}.
2298     * @since 1.5
2299     */
2300    public static String deepToString(Object[] array) {
2301        // Special case null to prevent NPE
2302        if (array == null) {
2303            return "null";
2304        }
2305        // delegate this to the recursive method
2306        StringBuilder buf = new StringBuilder(array.length * 9);
2307        deepToStringImpl(array, new Object[] { array }, buf);
2308        return buf.toString();
2309    }
2310
2311    /**
2312     * Implementation method used by {@link #deepToString(Object[])}.
2313     *
2314     * @param array
2315     *            the {@code Object[]} to dive into.
2316     * @param origArrays
2317     *            the original {@code Object[]}; used to test for self
2318     *            references.
2319     * @param sb
2320     *            the {@code StringBuilder} instance to append to or
2321     *            {@code null} one hasn't been created yet.
2322     * @return the result.
2323     * @see #deepToString(Object[])
2324     */
2325    private static void deepToStringImpl(Object[] array, Object[] origArrays,
2326            StringBuilder sb) {
2327        if (array == null) {
2328            sb.append("null");
2329            return;
2330        }
2331
2332        sb.append('[');
2333
2334        for (int i = 0; i < array.length; i++) {
2335            if (i != 0) {
2336                sb.append(", ");
2337            }
2338            // establish current element
2339            Object elem = array[i];
2340            if (elem == null) {
2341                // element is null
2342                sb.append("null");
2343            } else {
2344                // get the Class of the current element
2345                Class<?> elemClass = elem.getClass();
2346                if (elemClass.isArray()) {
2347                    // element is an array type
2348
2349                    // get the declared Class of the array (element)
2350                    Class<?> elemElemClass = elemClass.getComponentType();
2351                    if (elemElemClass.isPrimitive()) {
2352                        // element is a primitive array
2353                        if (boolean.class.equals(elemElemClass)) {
2354                            sb.append(toString((boolean[]) elem));
2355                        } else if (byte.class.equals(elemElemClass)) {
2356                            sb.append(toString((byte[]) elem));
2357                        } else if (char.class.equals(elemElemClass)) {
2358                            sb.append(toString((char[]) elem));
2359                        } else if (double.class.equals(elemElemClass)) {
2360                            sb.append(toString((double[]) elem));
2361                        } else if (float.class.equals(elemElemClass)) {
2362                            sb.append(toString((float[]) elem));
2363                        } else if (int.class.equals(elemElemClass)) {
2364                            sb.append(toString((int[]) elem));
2365                        } else if (long.class.equals(elemElemClass)) {
2366                            sb.append(toString((long[]) elem));
2367                        } else if (short.class.equals(elemElemClass)) {
2368                            sb.append(toString((short[]) elem));
2369                        } else {
2370                            // no other possible primitives, so we assert that
2371                            throw new AssertionError();
2372                        }
2373                    } else {
2374                        // element is an Object[], so we assert that
2375                        // assert elem instanceof Object[];
2376                        if (deepToStringImplContains(origArrays, elem)) {
2377                            sb.append("[...]");
2378                        } else {
2379                            Object[] newArray = (Object[]) elem;
2380                            Object[] newOrigArrays = new Object[origArrays.length + 1];
2381                            System.arraycopy(origArrays, 0, newOrigArrays, 0,
2382                                    origArrays.length);
2383                            newOrigArrays[origArrays.length] = newArray;
2384                            // make the recursive call to this method
2385                            deepToStringImpl(newArray, newOrigArrays, sb);
2386                        }
2387                    }
2388                } else { // element is NOT an array, just an Object
2389                    sb.append(array[i]);
2390                }
2391            }
2392        }
2393        sb.append(']');
2394    }
2395
2396    /**
2397     * Utility method used to assist the implementation of
2398     * {@link #deepToString(Object[])}.
2399     *
2400     * @param origArrays
2401     *            An array of Object[] references.
2402     * @param array
2403     *            An Object[] reference to look for in {@code origArrays}.
2404     * @return A value of {@code true} if {@code array} is an
2405     *         element in {@code origArrays}.
2406     */
2407    private static boolean deepToStringImplContains(Object[] origArrays,
2408            Object array) {
2409        if (origArrays == null || origArrays.length == 0) {
2410            return false;
2411        }
2412        for (Object element : origArrays) {
2413            if (element == array) {
2414                return true;
2415            }
2416        }
2417        return false;
2418    }
2419
2420    /**
2421     * Copies {@code newLength} elements from {@code original} into a new array.
2422     * If {@code newLength} is greater than {@code original.length}, the result is padded
2423     * with the value {@code false}.
2424     *
2425     * @param original the original array
2426     * @param newLength the length of the new array
2427     * @return the new array
2428     * @throws NegativeArraySizeException if {@code newLength < 0}
2429     * @throws NullPointerException if {@code original == null}
2430     * @since 1.6
2431     */
2432    public static boolean[] copyOf(boolean[] original, int newLength) {
2433        if (newLength < 0) {
2434            throw new NegativeArraySizeException(Integer.toString(newLength));
2435        }
2436        return copyOfRange(original, 0, newLength);
2437    }
2438
2439    /**
2440     * Copies {@code newLength} elements from {@code original} into a new array.
2441     * If {@code newLength} is greater than {@code original.length}, the result is padded
2442     * with the value {@code (byte) 0}.
2443     *
2444     * @param original the original array
2445     * @param newLength the length of the new array
2446     * @return the new array
2447     * @throws NegativeArraySizeException if {@code newLength < 0}
2448     * @throws NullPointerException if {@code original == null}
2449     * @since 1.6
2450     */
2451    public static byte[] copyOf(byte[] original, int newLength) {
2452        if (newLength < 0) {
2453            throw new NegativeArraySizeException(Integer.toString(newLength));
2454        }
2455        return copyOfRange(original, 0, newLength);
2456    }
2457
2458    /**
2459     * Copies {@code newLength} elements from {@code original} into a new array.
2460     * If {@code newLength} is greater than {@code original.length}, the result is padded
2461     * with the value {@code '\\u0000'}.
2462     *
2463     * @param original the original array
2464     * @param newLength the length of the new array
2465     * @return the new array
2466     * @throws NegativeArraySizeException if {@code newLength < 0}
2467     * @throws NullPointerException if {@code original == null}
2468     * @since 1.6
2469     */
2470    public static char[] copyOf(char[] original, int newLength) {
2471        if (newLength < 0) {
2472            throw new NegativeArraySizeException(Integer.toString(newLength));
2473        }
2474        return copyOfRange(original, 0, newLength);
2475    }
2476
2477    /**
2478     * Copies {@code newLength} elements from {@code original} into a new array.
2479     * If {@code newLength} is greater than {@code original.length}, the result is padded
2480     * with the value {@code 0.0d}.
2481     *
2482     * @param original the original array
2483     * @param newLength the length of the new array
2484     * @return the new array
2485     * @throws NegativeArraySizeException if {@code newLength < 0}
2486     * @throws NullPointerException if {@code original == null}
2487     * @since 1.6
2488     */
2489    public static double[] copyOf(double[] original, int newLength) {
2490        if (newLength < 0) {
2491            throw new NegativeArraySizeException(Integer.toString(newLength));
2492        }
2493        return copyOfRange(original, 0, newLength);
2494    }
2495
2496    /**
2497     * Copies {@code newLength} elements from {@code original} into a new array.
2498     * If {@code newLength} is greater than {@code original.length}, the result is padded
2499     * with the value {@code 0.0f}.
2500     *
2501     * @param original the original array
2502     * @param newLength the length of the new array
2503     * @return the new array
2504     * @throws NegativeArraySizeException if {@code newLength < 0}
2505     * @throws NullPointerException if {@code original == null}
2506     * @since 1.6
2507     */
2508    public static float[] copyOf(float[] original, int newLength) {
2509        if (newLength < 0) {
2510            throw new NegativeArraySizeException(Integer.toString(newLength));
2511        }
2512        return copyOfRange(original, 0, newLength);
2513    }
2514
2515    /**
2516     * Copies {@code newLength} elements from {@code original} into a new array.
2517     * If {@code newLength} is greater than {@code original.length}, the result is padded
2518     * with the value {@code 0}.
2519     *
2520     * @param original the original array
2521     * @param newLength the length of the new array
2522     * @return the new array
2523     * @throws NegativeArraySizeException if {@code newLength < 0}
2524     * @throws NullPointerException if {@code original == null}
2525     * @since 1.6
2526     */
2527    public static int[] copyOf(int[] original, int newLength) {
2528        if (newLength < 0) {
2529            throw new NegativeArraySizeException(Integer.toString(newLength));
2530        }
2531        return copyOfRange(original, 0, newLength);
2532    }
2533
2534    /**
2535     * Copies {@code newLength} elements from {@code original} into a new array.
2536     * If {@code newLength} is greater than {@code original.length}, the result is padded
2537     * with the value {@code 0L}.
2538     *
2539     * @param original the original array
2540     * @param newLength the length of the new array
2541     * @return the new array
2542     * @throws NegativeArraySizeException if {@code newLength < 0}
2543     * @throws NullPointerException if {@code original == null}
2544     * @since 1.6
2545     */
2546    public static long[] copyOf(long[] original, int newLength) {
2547        if (newLength < 0) {
2548            throw new NegativeArraySizeException(Integer.toString(newLength));
2549        }
2550        return copyOfRange(original, 0, newLength);
2551    }
2552
2553    /**
2554     * Copies {@code newLength} elements from {@code original} into a new array.
2555     * If {@code newLength} is greater than {@code original.length}, the result is padded
2556     * with the value {@code (short) 0}.
2557     *
2558     * @param original the original array
2559     * @param newLength the length of the new array
2560     * @return the new array
2561     * @throws NegativeArraySizeException if {@code newLength < 0}
2562     * @throws NullPointerException if {@code original == null}
2563     * @since 1.6
2564     */
2565    public static short[] copyOf(short[] original, int newLength) {
2566        if (newLength < 0) {
2567            throw new NegativeArraySizeException(Integer.toString(newLength));
2568        }
2569        return copyOfRange(original, 0, newLength);
2570    }
2571
2572    /**
2573     * Copies {@code newLength} elements from {@code original} into a new array.
2574     * If {@code newLength} is greater than {@code original.length}, the result is padded
2575     * with the value {@code null}.
2576     *
2577     * @param original the original array
2578     * @param newLength the length of the new array
2579     * @return the new array
2580     * @throws NegativeArraySizeException if {@code newLength < 0}
2581     * @throws NullPointerException if {@code original == null}
2582     * @since 1.6
2583     */
2584    public static <T> T[] copyOf(T[] original, int newLength) {
2585        if (original == null) {
2586            throw new NullPointerException("original == null");
2587        }
2588        if (newLength < 0) {
2589            throw new NegativeArraySizeException(Integer.toString(newLength));
2590        }
2591        return copyOfRange(original, 0, newLength);
2592    }
2593
2594    /**
2595     * Copies {@code newLength} elements from {@code original} into a new array.
2596     * If {@code newLength} is greater than {@code original.length}, the result is padded
2597     * with the value {@code null}.
2598     *
2599     * @param original the original array
2600     * @param newLength the length of the new array
2601     * @param newType the class of the new array
2602     * @return the new array
2603     * @throws NegativeArraySizeException if {@code newLength < 0}
2604     * @throws NullPointerException if {@code original == null}
2605     * @throws ArrayStoreException if a value in {@code original} is incompatible with T
2606     * @since 1.6
2607     */
2608    public static <T, U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
2609        // We use the null pointer check in copyOfRange for exception priority compatibility.
2610        if (newLength < 0) {
2611            throw new NegativeArraySizeException(Integer.toString(newLength));
2612        }
2613        return copyOfRange(original, 0, newLength, newType);
2614    }
2615
2616    /**
2617     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2618     * end (exclusive). The original order of elements is preserved.
2619     * If {@code end} is greater than {@code original.length}, the result is padded
2620     * with the value {@code false}.
2621     *
2622     * @param original the original array
2623     * @param start the start index, inclusive
2624     * @param end the end index, exclusive
2625     * @return the new array
2626     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2627     * @throws IllegalArgumentException if {@code start > end}
2628     * @throws NullPointerException if {@code original == null}
2629     * @since 1.6
2630     */
2631    public static boolean[] copyOfRange(boolean[] original, int start, int end) {
2632        if (start > end) {
2633            throw new IllegalArgumentException();
2634        }
2635        int originalLength = original.length;
2636        if (start < 0 || start > originalLength) {
2637            throw new ArrayIndexOutOfBoundsException();
2638        }
2639        int resultLength = end - start;
2640        int copyLength = Math.min(resultLength, originalLength - start);
2641        boolean[] result = new boolean[resultLength];
2642        System.arraycopy(original, start, result, 0, copyLength);
2643        return result;
2644    }
2645
2646    /**
2647     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2648     * end (exclusive). The original order of elements is preserved.
2649     * If {@code end} is greater than {@code original.length}, the result is padded
2650     * with the value {@code (byte) 0}.
2651     *
2652     * @param original the original array
2653     * @param start the start index, inclusive
2654     * @param end the end index, exclusive
2655     * @return the new array
2656     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2657     * @throws IllegalArgumentException if {@code start > end}
2658     * @throws NullPointerException if {@code original == null}
2659     * @since 1.6
2660     */
2661    public static byte[] copyOfRange(byte[] original, int start, int end) {
2662        if (start > end) {
2663            throw new IllegalArgumentException();
2664        }
2665        int originalLength = original.length;
2666        if (start < 0 || start > originalLength) {
2667            throw new ArrayIndexOutOfBoundsException();
2668        }
2669        int resultLength = end - start;
2670        int copyLength = Math.min(resultLength, originalLength - start);
2671        byte[] result = new byte[resultLength];
2672        System.arraycopy(original, start, result, 0, copyLength);
2673        return result;
2674    }
2675
2676    /**
2677     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2678     * end (exclusive). The original order of elements is preserved.
2679     * If {@code end} is greater than {@code original.length}, the result is padded
2680     * with the value {@code '\\u0000'}.
2681     *
2682     * @param original the original array
2683     * @param start the start index, inclusive
2684     * @param end the end index, exclusive
2685     * @return the new array
2686     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2687     * @throws IllegalArgumentException if {@code start > end}
2688     * @throws NullPointerException if {@code original == null}
2689     * @since 1.6
2690     */
2691    public static char[] copyOfRange(char[] original, int start, int end) {
2692        if (start > end) {
2693            throw new IllegalArgumentException();
2694        }
2695        int originalLength = original.length;
2696        if (start < 0 || start > originalLength) {
2697            throw new ArrayIndexOutOfBoundsException();
2698        }
2699        int resultLength = end - start;
2700        int copyLength = Math.min(resultLength, originalLength - start);
2701        char[] result = new char[resultLength];
2702        System.arraycopy(original, start, result, 0, copyLength);
2703        return result;
2704    }
2705
2706    /**
2707     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2708     * end (exclusive). The original order of elements is preserved.
2709     * If {@code end} is greater than {@code original.length}, the result is padded
2710     * with the value {@code 0.0d}.
2711     *
2712     * @param original the original array
2713     * @param start the start index, inclusive
2714     * @param end the end index, exclusive
2715     * @return the new array
2716     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2717     * @throws IllegalArgumentException if {@code start > end}
2718     * @throws NullPointerException if {@code original == null}
2719     * @since 1.6
2720     */
2721    public static double[] copyOfRange(double[] original, int start, int end) {
2722        if (start > end) {
2723            throw new IllegalArgumentException();
2724        }
2725        int originalLength = original.length;
2726        if (start < 0 || start > originalLength) {
2727            throw new ArrayIndexOutOfBoundsException();
2728        }
2729        int resultLength = end - start;
2730        int copyLength = Math.min(resultLength, originalLength - start);
2731        double[] result = new double[resultLength];
2732        System.arraycopy(original, start, result, 0, copyLength);
2733        return result;
2734    }
2735
2736    /**
2737     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2738     * end (exclusive). The original order of elements is preserved.
2739     * If {@code end} is greater than {@code original.length}, the result is padded
2740     * with the value {@code 0.0f}.
2741     *
2742     * @param original the original array
2743     * @param start the start index, inclusive
2744     * @param end the end index, exclusive
2745     * @return the new array
2746     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2747     * @throws IllegalArgumentException if {@code start > end}
2748     * @throws NullPointerException if {@code original == null}
2749     * @since 1.6
2750     */
2751    public static float[] copyOfRange(float[] original, int start, int end) {
2752        if (start > end) {
2753            throw new IllegalArgumentException();
2754        }
2755        int originalLength = original.length;
2756        if (start < 0 || start > originalLength) {
2757            throw new ArrayIndexOutOfBoundsException();
2758        }
2759        int resultLength = end - start;
2760        int copyLength = Math.min(resultLength, originalLength - start);
2761        float[] result = new float[resultLength];
2762        System.arraycopy(original, start, result, 0, copyLength);
2763        return result;
2764    }
2765
2766    /**
2767     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2768     * end (exclusive). The original order of elements is preserved.
2769     * If {@code end} is greater than {@code original.length}, the result is padded
2770     * with the value {@code 0}.
2771     *
2772     * @param original the original array
2773     * @param start the start index, inclusive
2774     * @param end the end index, exclusive
2775     * @return the new array
2776     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2777     * @throws IllegalArgumentException if {@code start > end}
2778     * @throws NullPointerException if {@code original == null}
2779     * @since 1.6
2780     */
2781    public static int[] copyOfRange(int[] original, int start, int end) {
2782        if (start > end) {
2783            throw new IllegalArgumentException();
2784        }
2785        int originalLength = original.length;
2786        if (start < 0 || start > originalLength) {
2787            throw new ArrayIndexOutOfBoundsException();
2788        }
2789        int resultLength = end - start;
2790        int copyLength = Math.min(resultLength, originalLength - start);
2791        int[] result = new int[resultLength];
2792        System.arraycopy(original, start, result, 0, copyLength);
2793        return result;
2794    }
2795
2796    /**
2797     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2798     * end (exclusive). The original order of elements is preserved.
2799     * If {@code end} is greater than {@code original.length}, the result is padded
2800     * with the value {@code 0L}.
2801     *
2802     * @param original the original array
2803     * @param start the start index, inclusive
2804     * @param end the end index, exclusive
2805     * @return the new array
2806     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2807     * @throws IllegalArgumentException if {@code start > end}
2808     * @throws NullPointerException if {@code original == null}
2809     * @since 1.6
2810     */
2811    public static long[] copyOfRange(long[] original, int start, int end) {
2812        if (start > end) {
2813            throw new IllegalArgumentException();
2814        }
2815        int originalLength = original.length;
2816        if (start < 0 || start > originalLength) {
2817            throw new ArrayIndexOutOfBoundsException();
2818        }
2819        int resultLength = end - start;
2820        int copyLength = Math.min(resultLength, originalLength - start);
2821        long[] result = new long[resultLength];
2822        System.arraycopy(original, start, result, 0, copyLength);
2823        return result;
2824    }
2825
2826    /**
2827     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2828     * end (exclusive). The original order of elements is preserved.
2829     * If {@code end} is greater than {@code original.length}, the result is padded
2830     * with the value {@code (short) 0}.
2831     *
2832     * @param original the original array
2833     * @param start the start index, inclusive
2834     * @param end the end index, exclusive
2835     * @return the new array
2836     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2837     * @throws IllegalArgumentException if {@code start > end}
2838     * @throws NullPointerException if {@code original == null}
2839     * @since 1.6
2840     */
2841    public static short[] copyOfRange(short[] original, int start, int end) {
2842        if (start > end) {
2843            throw new IllegalArgumentException();
2844        }
2845        int originalLength = original.length;
2846        if (start < 0 || start > originalLength) {
2847            throw new ArrayIndexOutOfBoundsException();
2848        }
2849        int resultLength = end - start;
2850        int copyLength = Math.min(resultLength, originalLength - start);
2851        short[] result = new short[resultLength];
2852        System.arraycopy(original, start, result, 0, copyLength);
2853        return result;
2854    }
2855
2856    /**
2857     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2858     * end (exclusive). The original order of elements is preserved.
2859     * If {@code end} is greater than {@code original.length}, the result is padded
2860     * with the value {@code null}.
2861     *
2862     * @param original the original array
2863     * @param start the start index, inclusive
2864     * @param end the end index, exclusive
2865     * @return the new array
2866     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2867     * @throws IllegalArgumentException if {@code start > end}
2868     * @throws NullPointerException if {@code original == null}
2869     * @since 1.6
2870     */
2871    @SuppressWarnings("unchecked")
2872    public static <T> T[] copyOfRange(T[] original, int start, int end) {
2873        int originalLength = original.length; // For exception priority compatibility.
2874        if (start > end) {
2875            throw new IllegalArgumentException();
2876        }
2877        if (start < 0 || start > originalLength) {
2878            throw new ArrayIndexOutOfBoundsException();
2879        }
2880        int resultLength = end - start;
2881        int copyLength = Math.min(resultLength, originalLength - start);
2882        T[] result = (T[]) Array.newInstance(original.getClass().getComponentType(), resultLength);
2883        System.arraycopy(original, start, result, 0, copyLength);
2884        return result;
2885    }
2886
2887    /**
2888     * Copies elements from {@code original} into a new array, from indexes start (inclusive) to
2889     * end (exclusive). The original order of elements is preserved.
2890     * If {@code end} is greater than {@code original.length}, the result is padded
2891     * with the value {@code null}.
2892     *
2893     * @param original the original array
2894     * @param start the start index, inclusive
2895     * @param end the end index, exclusive
2896     * @return the new array
2897     * @throws ArrayIndexOutOfBoundsException if {@code start < 0 || start > original.length}
2898     * @throws IllegalArgumentException if {@code start > end}
2899     * @throws NullPointerException if {@code original == null}
2900     * @throws ArrayStoreException if a value in {@code original} is incompatible with T
2901     * @since 1.6
2902     */
2903    @SuppressWarnings("unchecked")
2904    public static <T, U> T[] copyOfRange(U[] original, int start, int end, Class<? extends T[]> newType) {
2905        if (start > end) {
2906            throw new IllegalArgumentException();
2907        }
2908        int originalLength = original.length;
2909        if (start < 0 || start > originalLength) {
2910            throw new ArrayIndexOutOfBoundsException();
2911        }
2912        int resultLength = end - start;
2913        int copyLength = Math.min(resultLength, originalLength - start);
2914        T[] result = (T[]) Array.newInstance(newType.getComponentType(), resultLength);
2915        System.arraycopy(original, start, result, 0, copyLength);
2916        return result;
2917    }
2918}
2919