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操做的时候使用。