java.util.Arrays 類是 JDK 提供的一個工具類,用來處理數組的各類方法,並且每一個方法基本上都是靜態方法,能直接經過類名Arrays調用。java
public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }
做用是返回由指定數組支持的固定大小列表。算法
注意:這個方法返回的 ArrayList 不是咱們經常使用的集合類 java.util.ArrayList。這裏的 ArrayList 是 Arrays 的一個內部類 java.util.Arrays.ArrayList。這個內部類有以下屬性和方法:
數組
private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable { private static final long serialVersionUID = -2764017481108945198L; private final E[] a; ArrayList(E[] array) { if (array==null) throw new NullPointerException(); a = array; } public int size() { return a.length; } public Object[] toArray() { return a.clone(); } public <T> T[] toArray(T[] a) { int size = size(); if (a.length < size) return Arrays.copyOf(this.a, size, (Class<? extends T[]>) a.getClass()); System.arraycopy(this.a, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } public E get(int index) { return a[index]; } public E set(int index, E element) { E oldValue = a[index]; a[index] = element; return oldValue; } public int indexOf(Object o) { if (o==null) { for (int i=0; i<a.length; i++) if (a[i]==null) return i; } else { for (int i=0; i<a.length; i++) if (o.equals(a[i])) return i; } return -1; } public boolean contains(Object o) { return indexOf(o) != -1; } }
①、返回的 ArrayList 數組是一個定長列表,咱們只能對其進行查看或者修改,可是不能進行添加或者刪除操做微信
經過源碼咱們發現該類是沒有add()或者remove() 這樣的方法的,若是對其進行增長或者刪除操做,都會調用其父類 AbstractList 對應的方法,而追溯父類的方法最終會拋出 UnsupportedOperationException 異常。以下:app
String[] str = {"a","b","c"}; List<String> listStr = Arrays.asList(str); listStr.set(1, "e");//能夠進行修改 System.out.println(listStr.toString());//[a, e, c] listStr.add("a");//添加元素會報錯 java.lang.UnsupportedOperationException
②、引用類型的數組和基本類型的數組區別dom
String[] str = {"a","b","c"}; List listStr = Arrays.asList(str); System.out.println(listStr.size());//3 int[] i = {1,2,3}; List listI = Arrays.asList(i); System.out.println(listI.size());//1
上面的結果第一個listStr.size()==3,而第二個 listI.size()==1。這是爲何呢?ide
咱們看源碼,在 Arrays.asList 中,方法聲明爲 <T> List<T> asList(T... a)。該方法接收一個可變參數,而且這個可變參數類型是做爲泛型的參數。咱們知道基本數據類型是不能做爲泛型的參數的,可是數組是引用類型,因此數組是能夠泛型化的,因而 int[] 做爲了整個參數類型,而不是 int 做爲參數類型。工具
因此將上面的方法泛型化補全應該是:ui
String[] str = {"a","b","c"}; List<String> listStr = Arrays.asList(str); System.out.println(listStr.size());//3 int[] i = {1,2,3}; List<int[]> listI = Arrays.asList(i);//注意這裏List參數爲 int[] ,而不是 int System.out.println(listI.size());//1 Integer[] in = {1,2,3}; List<Integer> listIn = Arrays.asList(in);//這裏參數爲int的包裝類Integer,因此集合長度爲3 System.out.println(listIn.size());//3
③、返回的列表ArrayList裏面的元素都是引用,不是獨立出來的對象this
String[] str = {"a","b","c"}; List<String> listStr = Arrays.asList(str); //執行更新操做前 System.out.println(Arrays.toString(str));//[a, b, c] listStr.set(0, "d");//將第一個元素a改成d //執行更新操做後 System.out.println(Arrays.toString(str));//[d, b, c]
這裏的Arrays.toString()方法就是打印數組的內容,後面會介紹。咱們看修改集合的內容,原數組的內容也變化了,因此這裏傳入的是引用類型。
④、已知數組數據,如何快速獲取一個可進行增刪改查的列表List?
String[] str = {"a","b","c"}; List<String> listStr = new ArrayList<>(Arrays.asList(str)); listStr.add("d"); System.out.println(listStr.size());//4
這裏的ArrayList 集合類後面咱們會詳細講解,你們目前只須要知道有這種用法便可。
⑤、Arrays.asList() 方法使用場景
Arrays工具類提供了一個方法asList, 使用該方法能夠將一個變長參數或者數組轉換成List 。可是,生成的List的長度是固定的;可以進行修改操做(好比,修改某個位置的元素);不能執行影響長度的操做(如add、remove等操做),不然會拋出UnsupportedOperationException異常。
因此 Arrays.asList 比較適合那些已經有數組數據或者一些元素,而須要快速構建一個List,只用於讀取操做,而不進行添加或刪除操做的場景。
該方法是用於數組排序,在 Arrays 類中有該方法的一系列重載方法,能對7種基本數據類型,包括 byte,char,double,float,int,long,short 等都能進行排序,還有 Object 類型(實現了Comparable接口),以及比較器 Comparator 。
①、基本類型的數組
這裏咱們以 int[ ] 爲例看看:
int[] num = {1,3,8,5,2,4,6,7}; Arrays.sort(num); System.out.println(Arrays.toString(num));//[1, 2, 3, 4, 5, 6, 7, 8]
經過調用 sort(int[] a) 方法,將原數組按照升序的順序排列。下面咱們經過源碼看看是如何實現排序的:
public static void sort(int[] a) { DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0); }
在 Arrays.sort 方法內部調用 DualPivotQuicksort.sort 方法,這個方法的源碼很長,分別對於數組的長度進行了各類算法的劃分,包括快速排序,插入排序,冒泡排序都有使用。詳細源碼能夠參考這篇博客。
②、對象類型數組
該類型的數組進行排序能夠實現 Comparable 接口,重寫 compareTo 方法進行排序。
String[] str = {"a","f","c","d"}; Arrays.sort(str); System.out.println(Arrays.toString(str));//[a, c, d, f]
String 類型實現了 Comparable 接口,內部的 compareTo 方法是按照字典碼進行比較的。
③、沒有實現Comparable接口的,能夠經過Comparator實現排序
Person[] p = new Person[]{new Person("zhangsan",22),new Person("wangwu",11),new Person("lisi",33)}; Arrays.sort(p,new Comparator<Person>() { @Override public int compare(Person o1, Person o2) { if(o1 == null || o2 == null){ return 0; } return o1.getPage()-o2.getPage(); } }); System.out.println(Arrays.toString(p));
用二分法查找數組中的某個元素。該方法和 sort 方法同樣,適用於各類基本數據類型以及對象。
注意:二分法是對以及有序的數組進行查找(好比先用Arrays.sort()進行排序,而後調用此方法進行查找)。找到元素返回下標,沒有則返回 -1
實例:
int[] num = {1,3,8,5,2,4,6,7}; Arrays.sort(num); System.out.println(Arrays.toString(num));//[1, 2, 3, 4, 5, 6, 7, 8] System.out.println(Arrays.binarySearch(num, 2));//返回元素的下標 1
具體源碼實現:
public static int binarySearch(int[] a, int key) { return binarySearch0(a, 0, a.length, key); } private static int binarySearch0(int[] a, int fromIndex, int toIndex,int key) { int low = fromIndex; int high = toIndex - 1; while (low <= high) { int mid = (low + high) >>> 1;//取中間值下標 int midVal = a[mid];//取中間值 if (midVal < key) low = mid + 1; else if (midVal > key) high = mid - 1; else return mid; } return -(low + 1); }
拷貝數組元素。底層採用 System.arraycopy() 實現,這是一個native方法。
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
src:源數組
srcPos:源數組要複製的起始位置
dest:目的數組
destPos:目的數組放置的起始位置
length:複製的長度
注意:src 和 dest都必須是同類型或者能夠進行轉換類型的數組。
int[] num1 = {1,2,3}; int[] num2 = new int[3]; System.arraycopy(num1, 0, num2, 0, num1.length); System.out.println(Arrays.toString(num2));//[1, 2, 3]
/** * @param original 源數組 * @param newLength //返回新數組的長度 * @return */ public static int[] copyOf(int[] original, int newLength) { int[] copy = new int[newLength]; System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; }
①、equals
equals 用來比較兩個數組中對應位置的每一個元素是否相等。
八種基本數據類型以及對象都能進行比較。
咱們先看看 int類型的數組比較源碼實現:
public static boolean equals(int[] a, int[] a2) { if (a==a2)//數組引用相等,則裏面的元素必定相等 return true; if (a==null || a2==null)//兩個數組其中一個爲null,都返回false return false; int length = a.length; if (a2.length != length)//兩個數組長度不等,返回false return false; for (int i=0; i<length; i++)//經過for循環依次比較數組中每一個元素是否相等 if (a[i] != a2[i]) return false; return true; }
在看對象數組的比較:
public static boolean equals(Object[] a, Object[] a2) { if (a==a2) return true; if (a==null || a2==null) return false; int length = a.length; if (a2.length != length) return false; for (int i=0; i<length; i++) { Object o1 = a[i]; Object o2 = a2[i]; if (!(o1==null ? o2==null : o1.equals(o2))) return false; } return true; }
基本上也是經過 equals 來判斷。
②、deepEquals
也是用來比較兩個數組的元素是否相等,不過 deepEquals 可以進行比較多維數組,並且是任意層次的嵌套數組。
String[][] name1 = {{ "G","a","o" },{ "H","u","a","n"},{ "j","i","e"}}; String[][] name2 = {{ "G","a","o" },{ "H","u","a","n"},{ "j","i","e"}}; System.out.println(Arrays.equals(name1,name2));// false System.out.println(Arrays.deepEquals(name1,name2));// true
該系列方法用於給數組賦值,並能指定某個範圍賦值。
//給a數組全部元素賦值 val public static void fill(int[] a, int val) { for (int i = 0, len = a.length; i < len; i++) a[i] = val; } //給從 fromIndex 開始的下標,toIndex-1結尾的下標都賦值 val,左閉右開 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; }
toString 用來打印一維數組的元素,而 deepToString 用來打印多層次嵌套的數組元素。
public static String toString(int[] a) { if (a == null) return "null"; int iMax = a.length - 1; if (iMax == -1) return "[]"; StringBuilder b = new StringBuilder(); b.append('['); for (int i = 0; ; i++) { b.append(a[i]); if (i == iMax) return b.append(']').toString(); b.append(", "); } }
本系列教程持續更新,能夠微信搜索「 IT可樂 」第一時間閱讀。回覆《電子書》有我爲你們特別篩選的書籍資料