| Arrays.java是Java中用來操作數(shù)組的類。使用這個工具類可以減少平常很多的工作量。了解其實(shí)現(xiàn),可以避免一些錯誤的用法。 它提供的操作包括: 排序 sort查找 binarySearch()比較 equals填充 fill轉(zhuǎn)列表 asList()哈希 Hash()轉(zhuǎn)字符串 toString()
 這個類的代碼量很多,Java1.7中有4000多行。因?yàn)槊恳环N基本類型都做了兼容,所以整個類真正邏輯不多。下面簡單介紹一下它各個功能的實(shí)現(xiàn): 排序這里的排序?qū)崿F(xiàn)有兩種 一種是為基本類型數(shù)組設(shè)計的,它的對外接口有兩種,如下: //whole arraypublic static void sort(primitive[] a);
 
 //sub array
 public static void sort(primitive[] a, int fromIndex, int toIndex);
 它們的具體實(shí)現(xiàn)方式是一樣的都是調(diào)用了DualPivotQuicksort.sort(...)方法。這個方法的中文含義是 雙軸快速排序。它在性能上優(yōu)于傳統(tǒng)的單軸快速排序。 算法的邏輯可以參考如果想要閱讀源碼可以參考我的另一篇博客
 它是不穩(wěn)定的 另一種是為Object對象設(shè)計的,它要求傳進(jìn)來的數(shù)組對象必須實(shí)現(xiàn)Comparable接口。它提供的接口如下:
 // whole array, default asecpublic static void sort(Object[] a);
 
 // subArray, default asec
 public static void sort(Object[] a, int fromIndex, int toIndex);
 還有帶泛型參數(shù)的接口,它需要指定一個比較器。 // whole array with comparatorpublic static <T> void sort(T[] a, Comparator<? super T> c);
 
 // sub array with comparator
 public static <T> void sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c);
 他的實(shí)現(xiàn)方式如下: // java/utils/Arrays.javastatic final class LegacyMergeSort {
 private static final boolean userRequested =
 java.security.AccessController.doPrivileged(
 new sun.security.action.GetBooleanAction(
 "java.util.Arrays.useLegacyMergeSort")).booleanValue();
 }
 
 //sort 方法的實(shí)現(xiàn)
 public static void sort(Object[] a) {
 if (LegacyMergeSort.userRequested)
 legacyMergeSort(a);
 else
 //與TimSort的邏輯是相同的
 ComparableTimSort.sort(a);
 }
 
 //legacyMergeSort
 private static void legacyMergeSort(Object[] a) {
 Object[] aux = a.clone();
 mergeSort(aux, a, 0, a.length, 0);
 }
 
 //歸并排序
 private static void mergeSort(Object[] src,
 Object[] dest,
 int low,
 int high,
 int off) {
 // 小數(shù)組直接進(jìn)行普通插入排序
 if (length < INSERTIONSORT_THRESHOLD) {
 ///...
 return;
 }
 
 //下面是歸并排序的實(shí)現(xiàn),
 ///...
 }
 從上面的邏輯可以看出來,它的實(shí)現(xiàn)方式分為兩種,一種是通過Arrays.java中的歸并排序?qū)崿F(xiàn)的,另一種采用了TimSort算法。其中Arrays.java中的歸并排序的邏輯相對簡單,是一種插入排序與傳統(tǒng)歸并排序的結(jié)合。當(dāng)待排序的數(shù)組小于INSERTIONSROT_THERSHOLD的時候直接進(jìn)行插入排序,不再遞歸。TimSort算法也是一種插入排序與歸并排序結(jié)合的算法,不過它的細(xì)節(jié)優(yōu)化要比Arrays.java中的算法做的多。詳細(xì)介紹可以參考或者我的。 兩種算法的切換依靠運(yùn)行時系統(tǒng)變量的設(shè)置。具體參考上的一篇回答。我們默認(rèn)情況下是不打開這個開關(guān)的,也就是說沒有特殊要求的情況下,我們默認(rèn)使用TimSort算法來實(shí)現(xiàn)排序。從注釋上來看,在未來某個版本,Arrays.java中的merge方法將會被刪除掉。 這個排序方法是穩(wěn)定的。 查找Arrays.java中只提供了二分查找。二分查找的前提就是數(shù)組是經(jīng)過升序排序的,所以使用之前務(wù)必確保數(shù)組是有序的。 調(diào)用的接口比較簡單: public static int binarySearch(primative[] a, primative key);public static int binarySearch(primative[] a, int fromIndex, int toIndex, primative key);
 public static int binarySearch(Object[] a, Object key);
 public static int binarySearch(Object[] a, int fromIndex, int toIndex, Object key);
 public static <T> int binarySearch(T[] a, T key, Comparator< ? super T> c);
 public static <T> int binarySearch(T[] a, int fromIndex, int toIndex, T key,Comparator<? super T> c);
 
equals這個也比較簡單,equals方法與==的不同大家應(yīng)該都很熟悉了,這里直接貼出接口: // 基本類型public static boolean equals(long[] a, long[] a2) {
 //...
 }
 // 對象
 public static boolean equals(Object[] a, Object[] a2) {
 //...
 }
 // 高維數(shù)組的equal比較,通過遞歸實(shí)現(xiàn)
 // 這里沒有對循環(huán)引用進(jìn)行檢查,如果兩個如組同時存在循環(huán)引用的情況下可能出現(xiàn)死循環(huán)的風(fēng)險。
 public static boolean deepEquals(Object[] a1, Object[] a2) {
 //...
 }
 fill 填充批量初始化的時候不要自己寫for循環(huán)了,已經(jīng)有人幫我們寫好了。 // 基本類型批量賦值public static void fill(int[] a, int fromIndex, int toIndex, int val) {
 rangeCheck(a.length, fromIndex, toIndex);
 for (int i = fromIndex; i < toIndex; i++)
 a[i] = val;
 }
 // 對象批量賦值
 public static void fill(Object[] a, int fromIndex, int toIndex, Object val) {
 rangeCheck(a.length, fromIndex, toIndex);
 for (int i = fromIndex; i < toIndex; i++)
 a[i] = val;
 }
 
復(fù)制數(shù)組復(fù)制的最終實(shí)現(xiàn)是調(diào)用了JVM中的方法。具體沒有深究,但在數(shù)據(jù)量大的時候應(yīng)該能快些。 // @file Arrays.java// 基本類型的復(fù)制,從0開始到指定長度
 public static byte[] copyOf(byte[] original, int newLength) {
 byte[] copy = new byte[newLength];
 System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength));
 return copy;
 }
 // 基本類型復(fù)制,從指定起點(diǎn)到指定終點(diǎn)
 public static byte[] copyOfRange(byte[] original, int from, int to) {
 int newLength = to - from;
 if (newLength < 0)
 throw new IllegalArgumentException(from + " > " + to);
 byte[] copy = new byte[newLength];
 System.arraycopy(original, from, copy, 0,
 Math.min(original.length - from, newLength));
 return copy;
 }
 //這里是泛型數(shù)組的復(fù)制, 結(jié)合泛型進(jìn)階中的內(nèi)容,這里好理解很多。
 public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
 T[] copy = ((Object)newType == (Object)Object[].class)
 ? (T[]) new Object[newLength]
 : (T[]) Array.newInstance(newType.getComponentType(), newLength);
 System.arraycopy(original, 0, copy, 0,
 Math.min(original.length, newLength));
 return copy;
 }
 
 // @file System.java
 public static native void arraycopy(Object src,  int  srcPos, Object dest, int destPos, int length);
 
 //
 
轉(zhuǎn)換成列表 asList將一組對象轉(zhuǎn)換成列表,這里一定要注意返回的ArrayList并非平常用的java.util.ArrayList ,而是Arrays.java中定義的一個簡單的靜態(tài)內(nèi)部類--ArrayList。它不支持添加和移除元素,不支持?jǐn)U容。 @file java/util/Arrays.java
 @SafeVarargs
 public static <T> List<T> asList(T... a) {
 return new ArrayList<>(a);
 }
 
 //注意,此ArrayList非平常用的ArrayList;這里的實(shí)現(xiàn)比較簡單。
 //不能擴(kuò)容,所以不支持add,remove等操作。
 private static class ArrayList<E> extends AbstractList<E>
 implements RandomAccess, java.io.Serializable {
 /// ...
 }
 
哈希 hash高維數(shù)組的哈希計算,采用遞歸實(shí)現(xiàn)。同樣,如果自己的某個元素直接或者間接持有自己,會出現(xiàn)死循環(huán)。 // 基本類型哈希public static int hashCode(long a[]) {
 // ...
 }
 
 // 對象哈希
 public static int hashCode(Object a[]) {
 //...
 }
 
 // 高維數(shù)組哈希,采用遞歸實(shí)現(xiàn)。如果自己的某個元素直接或者間接持有自己,會出現(xiàn)死訊環(huán),
 // 所以`Object[]`最好直接使用`hashcode(Object)`。
 public static int deepHashCode(Object a[]) {
 //...
 }
 toString有了這個方法,打Log的時候就不需要寫循環(huán)了。這里的高維數(shù)組直接或者間接持有自己的情況不會出現(xiàn)死循環(huán)。因?yàn)檫@里做了特殊處理,用一個Set保存了打印過的數(shù)組。
 文章來源:https://www./blog-eA5LgU30OF.htm// 基本類型public static String toString(int[] a) {
 // ...
 }
 // 對象
 public static String toString(Object[] a) {
 // ...
 }
 // 高維數(shù)組toString(). 這里處理了自我持有的問題。
 public static String deepToString(Object[] a) {
 // ...
 deepToString(a, buf, new HashSet<Object[]>());
 return buf.toString();
 }
 // 真正的實(shí)現(xiàn)方法, 遞歸實(shí)現(xiàn)。
 // 使用了一個Set來存儲已經(jīng)打印過的類,如果再次出現(xiàn)這個對象,直接打印[...]
 private static void deepToString(Object[] a, StringBuilder buf,
 Set<Object[]> dejaVu) {
 //...
 }
 |