一、概述
1、介紹
Arrays 類是 JDK1.2 提供的一個工具類,提供處理數組的各種方法,基本上都是靜態方法,能直接通過類名Arrays調用。
二、類源碼
1、asList()方法
將一個泛型數組轉化為List集合返回。但是,這個List集合既不是ArrayList實例,也不是Vector實例。它是一個固定長度的 List 集合,是 Arrays 的一個內部類 java.util.Arrays.ArrayList。
代碼示例:使用
1 public class Main { 2 public static void main(String[] args) throws Exception { 3 Integer[] d = {3, 1, 2}; 4 final List<Integer> integers = Arrays.asList(d); 5 System.out.println(integers); 6 } 7 } 8 9 // 結果 10 [3, 1, 2]
源碼示例:
1 public static <T> List<T> asList(T... a) { 2 return new ArrayList<>(a); 3 } 4 5 private static class ArrayList<E> extends AbstractList<E> 6 implements RandomAccess, java.io.Serializable 7 { 8 // 源碼省略,讀者可自行用idea查看 9 }
說明:
①、定長列表,只能對其進行查看或者修改,不能進行添加或者刪除操作
1 public class Main { 2 public static void main(String[] args) { 3 String[] str = {"a", "b", "c"}; 4 List<String> list = Arrays.asList(str); 5 // 可以進行修改 6 list.set(1, "e"); 7 System.out.println(list.toString()); // [a, e, c] 8 9 list.add("a"); //添加元素會報錯 java.lang.UnsupportedOperationException 10 } 11 }
查看源碼發現,該類沒有add() 和 remove()方法。如果對其進行增加或者刪除操作,會調用其父類 AbstractList 對應的方法,而追溯父類的方法最終會拋出 UnsupportedOperationException 異常。源碼如下:
1 // 類 AbstractList 2 public boolean add(E e) { 3 add(size(), e); 4 return true; 5 } 6 7 public void add(int index, E element) { 8 throw new UnsupportedOperationException(); 9 }
②、引用類型的數組和基本類型的數組區別
1 public class Main { 2 public static void main(String[] args) { 3 String[] str = {"a", "b", "c"}; 4 final List<String> list = Arrays.asList(str); 5 System.out.println(list.size()); // 3 6 7 int[] i = {1, 2, 3}; 8 final List<int[]> ints = Arrays.asList(i); 9 System.out.println(ints.size()); // 1 10 11 Integer[] in = {1, 2, 3}; 12 final List<Integer> integers = Arrays.asList(in); 13 System.out.println(integers.size()); // 3 14 } 15 }
類類型才是泛型,基本數據類型不能作為泛型的參數。讀者根據上面結果自行體會一下。
③、返回的是原數組的里的引用,不是獨立出來的集合對象
1 public class Main { 2 public static void main(String[] args) { 3 String[] str = {"a", "b", "c"}; 4 List<String> listStr = Arrays.asList(str); 5 System.out.println(Arrays.toString(str)); // [a, b, c] 6 7 listStr.set(0, "d"); 8 9 System.out.println(Arrays.toString(str)); // [d, b, c] 10 } 11 }
這里,修改的是返回的集合的內容,但是原數組的內容也變化了,所以只是返回了原數組的一個視圖。如果希望返回一個全新的集合,可以如下:
1 public class Main { 2 public static void main(String[] args) { 3 String[] str = {"a", "b", "c"}; 4 5 ArrayList<String> strings = new ArrayList<>(Arrays.asList(str)); 6 strings.add("d"); 7 8 System.out.println(Arrays.toString(str)); // [a, b, c] 9 System.out.println(strings); // [a, b, c, d] 10 } 11 }
2、sort()方法
用於數組排序,有一系列重載方法。注意,如果是 Object 類型,需要實現Comparable接口或者傳入一個比較器 Comparator ,使其具有可比性。可以參考這篇。Java比較器。
源碼示例:
1 public static void sort(int[] a) { 2 DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0); 3 }
這個方法的源碼很長,分別對數組的長度進行了各種算法的划分,包括快速排序,插入排序,冒泡排序都有使用。詳細源碼可以參考這篇博客。
3、binarySearch()方法
用於數組查找,是基於二分查找算法實現,有一系列重載方法,適用於各種基本數據類型以及對象數組。
值得注意的是:調用此方法,要求待查找的數組有序。存在,返回元素下標;不存在,返回一個負數(不是 -1)。
源碼示例:
1 public static int binarySearch(int[] a, int key) { 2 return binarySearch0(a, 0, a.length, key); 3 } 4 5 // 典型的二分查找算法 6 private static int binarySearch0(int[] a, int fromIndex, int toIndex, 7 int key) { 8 int low = fromIndex; 9 int high = toIndex - 1; 10 11 while (low <= high) { 12 int mid = (low + high) >>> 1; 13 int midVal = a[mid]; 14 15 if (midVal < key) 16 low = mid + 1; 17 else if (midVal > key) 18 high = mid - 1; 19 else 20 return mid; // key found 21 } 22 23 // 找不到,返回並不是 -1 24 return -(low + 1); // key not found. 25 }
4、copyOf()方法
拷貝數組元素。底層采用 System.arraycopy() 實現,這是一個native方法。
注意:這個方法在ArrayList源碼擴容時,也是用的它。
代碼示例:
1 public class Main { 2 public static void main(String[] args) { 3 int[] old = {1, 3, 2}; 4 5 int[] ints = Arrays.copyOf(old, 5); 6 System.out.println(Arrays.toString(ints)); // [1, 3, 2, 0, 0] 7 8 int[] ints1 = Arrays.copyOf(old, 1); 9 System.out.println(Arrays.toString(ints1)); // [1] 10 } 11 }
源碼示例:
1 // Arrays類 2 public static int[] copyOf(int[] original, int newLength) { 3 int[] copy = new int[newLength]; 4 System.arraycopy(original, 0, copy, 0, 5 // 長度是舊數組長度 與 新長度 取小 6 Math.min(original.length, newLength)); 7 return copy; 8 } 9 10 // System類 11 public static native void arraycopy(Object src, int srcPos, 12 Object dest, int destPos, 13 int length);
src:源數組
srcPos:源數組要復制的起始位置
dest:目的數組
destPos:目的數組放置的起始位置
length:復制的長度
注意:src 和 dest都必須是同類型或者可以進行轉換類型的數組。
5、equals()/deepEquals()方法
①、equals
用於比較兩個數組中對應位置的每一個元素是否相等。
源碼示例:
1 // 基本數據類型數組比較 2 public static boolean equals(int[] a, int[] a2) { 3 // 引用相等,則相同 4 if (a==a2) 5 return true; 6 if (a==null || a2==null) 7 return false; 8 9 int length = a.length; 10 // 長度不同,則不相同 11 if (a2.length != length) 12 return false; 13 14 // 循環依次比較數組中每個元素是否相等 15 for (int i=0; i<length; i++) 16 if (a[i] != a2[i]) 17 return false; 18 19 return true; 20 } 21 22 // 引用類型數組比較 23 public static boolean equals(Object[] a, Object[] a2) { 24 if (a==a2) 25 return true; 26 if (a==null || a2==null) 27 return false; 28 29 int length = a.length; 30 if (a2.length != length) 31 return false; 32 33 for (int i=0; i<length; i++) { 34 Object o1 = a[i]; 35 Object o2 = a2[i]; 36 37 // 對象相同通過 equals 方法判斷 38 if (!(o1==null ? o2==null : o1.equals(o2))) 39 return false; 40 } 41 42 return true; 43 }
②、deepEquals
比較兩個數組的元素是否相等,可以嵌套任意層次的數組。
源碼就是遞歸的使用 deepEquals 判斷每一層的數組是否相同。
代碼示例:
1 public class Main { 2 public static void main(String[] args) { 3 String[][] name1 = {{"G", "a", "o"}, {"H", "u", "a", "n"}, {"j", "i", "e"}}; 4 String[][] name2 = {{"G", "a", "o"}, {"H", "u", "a", "n"}, {"j", "i", "e"}}; 5 6 System.out.println(Arrays.equals(name1, name2));// false 7 System.out.println(Arrays.deepEquals(name1, name2));// true 8 } 9 }
6、fill()方法
該系列方法用於給數組賦值,並能指定某個范圍賦值。
代碼示例:
1 public class Main { 2 public static void main(String[] args) { 3 int[] arr = new int[4]; 4 System.out.println(Arrays.toString(arr)); // [0, 0, 0, 0] 5 6 Arrays.fill(arr, 6); 7 System.out.println(Arrays.toString(arr)); // [6, 6, 6, 6] 8 } 9 }
源碼示例:
1 // 不寫注釋也能看懂的代碼 2 public static void fill(int[] a, int val) { 3 for (int i = 0, len = a.length; i < len; i++) 4 a[i] = val; 5 } 6 7 public static void fill(int[] a, int fromIndex, int toIndex, int val) { 8 rangeCheck(a.length, fromIndex, toIndex); 9 for (int i = fromIndex; i < toIndex; i++) 10 a[i] = val; 11 }
7、toString 和 deepToString方法
toString 用來打印一維數組的元素,而 deepToString 用來打印多層次嵌套的數組元素。
參考文檔:https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html