Arrays是操做數組對象的工具類,Collections是操做集合對象的工具類。Objects是操做引用數據類型對象的工具類java
Arrays的經常使用方法:python
普通排序:
Arrays.sort(int[] a)
Arrays.sort(int[] a, int fromIndex, int toIndex)
其餘非boolean基礎數據類型的數組對象以及實現Comparable接口的類的數組對象均有此方法。算法
並行排序:JDK1.8新增。
Arrays.parallelSort(int[] a)
Arrays.parallelSort(int[] a, int fromIndex, int toIndex)
其餘非boolean基礎數據類型的數組對象以及實現Comparable接口的類的數組對象均有此方法。編程
並行計算:JDK1.8新增,支持函數式編程,根據傳入的方法進行一次計算。
Arrays.parallelPrefix(int[] array, IntBinaryOperator op)
Arrays.parallelPrefix(int[] array, int fromIndex, int toIndex, IntBinaryOperator op)
其餘非boolean基礎數據類型的數組對象以及實現Comparable接口的類的數組對象均有此方法。數組
二分法查找:前提是該數組已經進行了排序
Arrays.binarySearch(int[] a, int key)
Arrays.binarySearch(int[] a, int fromIndex, int toIndex, int key)
其餘非boolean基礎數據類型的數組對象以及實現Comparable接口的類的數組對象均有此方法。安全
判斷兩個數組是否相等:
Arrays.equals(int[] a, int[] a2)
其餘基礎數據類型的數組對象以及Object數組對象均有此方法,Object調用的是equels()方法。框架
對數組進行填充:
Arrays.fill(int[] a, int val)
Arrays.fill(int[] a, int fromIndex, int toIndex, int val)
其餘基礎數據類型的數組對象以及Object數組對象均有此方法。函數式編程
複製數組:
Arrays.copyOf(int[] original, int newLength),返回賦值後的數組,數組長度爲newLength。
Arrays.copyOfRange(int[] original, int from, int to)
其餘基礎數據類型的數組對象以及Object數組對象均有此方法。Object數組爲淺複製,即複製的是引用。svn
toString: 將元素用","隔開,包裹在"[ ]"內。
Arrays.toString(int[] a)
其餘基礎數據類型的數組對象以及Object數組對象均有此方法。Object數組爲引用地址。
Arrays.deepToString(Object[] a)方法內部調用了a.toString()。函數
更改元素值:JDK1.8新增,支持函數式編程
setAll(int[] array, IntUnaryOperator generator)
setAll(long[] array, IntToLongFunction generator)
setAll(double[] array, IntToDoubleFunction generator)
setAll(T[] array, IntFunction<? extends T> generator)
該類方法支持這四種類型。每種類型均有對應的並行設置方法parallelSetAll()
數組轉集合:
Arrays.asList(T... a) 返回List<T>
若是是Object數組對象,該方法生成的集合對象持有的是數組對象對應元素的引用。
生成並行遍歷的Spliterator,JDK1.8新增
Arrays.spliterator(int[] array)
Arrays.spliterator(int[] array, int startInclusive, int endExclusive)
int、long、double和實現了Spliterator接口的類具備該類型方法。
生成Stream類,JDK1.8新增
Arrays.stream(int[] a)
Arrays.stream(int[] array, int startInclusive, int endExclusive)
int、long、double和實現了Stream接口的類具備該類型方法。
JDK1.8新增的方法基本都是與函數式變成或多核並行操做相關。
接下來看看Arrays經常使用方法的源碼。
1,Arrays.asList()的源碼實現分析:
public static <T> List<T> asList(T... a) { return new ArrayList<>(a); // 爲何JDK的設計者不直接使用ava.util.ArrayList呢? }
這個ArrayList是數組的內部實現類,不是常常是用的java.util.ArrayList。這個內部類ArrayList是一個固定大小的list,不支持list.add()和list.remove(),這裏必定要注意。
2,Arrays.sort()的源碼實現分析:
public static void sort(int[] a) { DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0); }
這裏用到了DualPivotQuicksort.sort()。DualPivotQuicksort是java.util包下的final類,專門用來對基礎數據類型的數據進行排序的。DualPivotQuicksort.sort()源碼分析:
static void sort(int[] a, int left, int right, int[] work, int workBase, int workLen) { // 對於數組長度小的狀況採用快速排序 if (right - left < QUICKSORT_THRESHOLD) { // QUICKSORT_THRESHOLD = 286 sort(a, left, right, true); return; } // 歸併+快排 (引入了TimSort的run的概念) ...省略算法源碼 }
快排算法sort()的源碼分析:
private static void sort(int[] a, int left, int right, boolean leftmost) { int length = right - left + 1; // 對於數組長度很小的狀況採用插入排序 if (length < INSERTION_SORT_THRESHOLD) { // INSERTION_SORT_THRESHOLD) = 47 // 插入排序 insertion sort ...省略算法源碼 } // 雙軸快排 dual-pivot quicksort ...省略算法源碼(遞歸插入排序) }
具體的算法實現源碼不作深究,之後有機會的話寫一些關於算法拾遺。這裏主要是一些閥值要注意。
3,Arrays.sort(Object[] a)的源碼實現分析:
public static void sort(Object[] a) { if (LegacyMergeSort.userRequested) // 若是用戶強制要求使用傳統的排序方法。 // -Djava.util.Arrays.useLegacyMergeSort=true // 或者System.setProperty("java.util.Arrays.useLegacyMergeSort", "true"); legacyMergeSort(a); // 使用傳統方法排序 else ComparableTimSort.sort(a, 0, a.length, null, 0, 0); // 使用TimSort算法排序 }
傳統的排序算法legacyMergeSort()源碼:
private static void legacyMergeSort(Object[] a, int fromIndex, int toIndex) { Object[] aux = copyOfRange(a, fromIndex, toIndex); mergeSort(aux, a, fromIndex, toIndex, -fromIndex); } private static void mergeSort(Object[] src, Object[] dest, int low, int high, int off) { int length = high - low; // 若是數組長度很小,採用插入排序 Insertion sort if (length < INSERTIONSORT_THRESHOLD) { // INSERTIONSORT_THRESHOLD = 7 for (int i=low; i<high; i++) for (int j=i; j>low && ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--) swap(dest, j, j-1); return; } // 將數組分爲兩個子數組,分別使用遞歸排序Recursively sort,再進行合併排序 ...省略算法源碼 }
JDK1.8開始支持TimSort算法,源於Python中的TimSort(結合了merge sort 和 insertion sort)。
ComparableTimSort.sort()源碼:
static void sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen) { assert a != null && lo >= 0 && lo <= hi && hi <= a.length; int nRemaining = hi - lo; if (nRemaining < 2) return; // 數組長度爲0或1時無需排序 // 若是數組長度小,採用無合併形式的"mini-TimSort"排序 if (nRemaining < MIN_MERGE) { // MIN_MERGE = 32 int initRunLen = countRunAndMakeAscending(a, lo, hi); binarySort(a, lo, hi, lo + initRunLen); // 二分插入排序 return; } // 1,遍歷一遍數組,找到已經天然排序好順序的序列;3,這個序列入棧(臨時數組,排序後的數組就放在這裏); // 2,若是這個序列的長度 < minRun 則經過binarySort獲得長度爲minRun的序列。這個minRun的計算跟數組自己長度有關; // 4,一樣的方法尋找下一個分段併入另一個棧; // 5,合併排序兩個棧中的序列; // 6,重複4和5; ...省略算法源碼 }
4,Arrays.parallelSort()的源碼實現分析:
public static void parallelSort(byte[] a) { int n = a.length, p, g; if (n <= MIN_ARRAY_SORT_GRAN || (p = ForkJoinPool.getCommonPoolParallelism()) == 1) DualPivotQuicksort.sort(a, 0, n - 1); else new ArraysParallelSortHelpers.FJByte.Sorter (null, a, new byte[n], 0, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ? MIN_ARRAY_SORT_GRAN : g).invoke(); }
Arrays.parallelSort()採用的是cilk排序算法。
cilk排序算法基本思想:
若是當前數組的長度a.length < MIN_ARRAY_SORT_GRAN = 8192,或者當前機器不支持並行排序,則採起普通的sort()。
ForkJoinPool.getCommonPoolParallelism()獲取當前ForkJoin線程池的並行度,跟機器的處理器核數有關,能夠經過-Djava.util.concurrent.ForkJoinPool.common.parallelism=8或者System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism","8")來指定,若是=1則表示不支持並行執行。
parallelSort()的基本實現思想:
==================================華麗的分割線==================================
Collections的經常使用方法:
排序:
Collections.sort(List<T> list) T或其父類須要實現Comparable接口 Collections.sort(List<T> list, Comparator<? super T> c) Collections.sort()的源碼:
public static <T> void sort(List<T> list, Comparator<? super T> c) { list.sort(c); }
List.sort()的源碼:
default void sort(Comparator<? super E> c) { Object[] a = this.toArray(); Arrays.sort(a, (Comparator) c); // 調用Arrays.sort()來進行排序 ListIterator<E> i = this.listIterator(); for (Object e : a) { i.next(); i.set((E) e); } }
Collections.sort()最終調用的是Arrays.sort()進行排序。
查到索引
Collections.binarySearch(List<? extends Comparable<? super T>> list, T key) Collections.binarySearch(List<? extends T> list, T key, Comparator<? super T> c)
順序反轉
Collections.reverse(List<?> list)
亂序
Collections.shuffle(List<?> list)
指定元素互換
Collections.swap(List<?> list, int i, int j)
填充
Collections.fill(List<? super T> list, T obj)
複製
Collections.copy(List<? super T> dest, List<? extends T> src)
求極值
Collections.min(Collection<? extends T> coll)
Collections.min(Collection<? extends T> coll, Comparator<? super T> comp)
Collections.max(Collection<? extends T> coll)
Collections.max(Collection<? extends T> coll, Comparator<? super T> comp)
轉動元素
Collections.rotate(List<?> list, int distance)
distance能夠接受負數 將list元素總體向後移動distance的距離,原來最後的distance個元素放到最前面(有點相似與一個圓圈轉動)
替換元素
Collections.replaceAll(List<T> list, T oldVal, T newVal)
子集合索引
Collections.indexOfSubList(List<?> source, List<?> target)
Collections.lastIndexOfSubList(List<?> source, List<?> target)
若是不是子集合,返回-1
轉換爲不可變集合
Collections.unmodifiableCollection(Collection<? extends T> c)
將集合轉換爲不可變集合read-only。裝飾者模式,使用final修飾iterator,增刪元素的方法throw new UnsupportedOperationException()
Collections.unmodifiableSet(Set<? extends T> s)
Collections.unmodifiableList(List<? extends T> list)
Collections.unmodifiableMap(Map<? extends K, ? extends V> m)
轉換爲同步集合
Collections.synchronizedCollection(Collection<T> c)
Collections.synchronizedCollection(Collection<T> c, Object mutex) 指定mutex對象做爲同步鎖,將集合轉換爲線程安全的同步集合。裝飾着模式,方法內使用了 synchronized (mutex) { ... }保證線程安全
Collections.synchronizedSet(Set<T> s)
Collections.Collections.synchronizedSet(Set<T> s, Object mutex)
Collections.synchronizedList(List<T> list)
Collections.synchronizedList(List<T> list, Object mutex)
Collections.synchronizedMap(Map<K, V>)
元素受限制集合
Collections.checkedCollection(Collection<E> c, Class<E> type)
因爲JDK1.5引入了泛型,採用該方法,保證運行期集合中增長的元素只能是指定的類型。一樣是裝飾着模式。
Collections.checkedQueue(Queue<E> queue, Class<E> type)
Collections.checkedSet(Set<E>, Class<E>)
Collections.checkedList(List<E>, Class<E>)
Collections.checkedMap(Map<K, V>, Class<K>, Class<V>)
生成空的不可變集合
Collections.emptyIterator()
Collections.emptyListIterator()
Collections.emptyEnumeration()
Collections.emptySet()
Collections.emptyList()
Collections.emptyMap()
只有1個元素的不可變集合
Collections.singleton(T)
Collections.singletonList(T)
Collections.singletonMap(K, V)
擁有n個相同元素的不可變集合
Collections.nCopies(int, T)
反序比較器
Collections.reverseOrder(Comparator<T>) 返回一個Comparator<T>,返回值與參數值是相反順序的比較器
轉換爲枚舉類型的API
Collections.enumeration(Collection<T>) 返回Enumeration<T>
將Enumeration<T>轉換爲集合
Collections.list(Enumeration<T>) 返回ArrayList<T>
元素在集合中的個數
Collections.frequency(Collection<?>, Object) 返回int
兩個元素是否有交集
Collections.disjoint(Collection<?>, Collection<?>) 返回boolean
增長元素
addAll(Collection<? super T> c, T... elements)
因爲List接口擁有listItegertor()方法,與List相關的大部分操做內部會判斷閥值,超過閥值則採用listIterator遍歷,小於閥值則採用for循環索引遍歷。不一樣的方法閥值不一樣。
==================================華麗的分割線==================================
Objects類最主要就一個方法 Objects.equals(Object a, Object b)
public static boolean equals(Object a, Object b) { return a == b || (a != null && a.equals(b)); }
其他的一些好比Obejcts.isNull(Object obj)、Objects.nonNull(Ojbect obj)主要是用來在Stream流式API操做的時候使用。