Arrays.sort(数组名);
Arrays.sort(数组名 ,int fromIndex, int toIndex);
这两个方法在排序中用到的频率最高,默认是升序排序,当我们需要默认排序时,就需要花点功夫了。
Arrays.cort()自定义排序
通过自定义一个类实现Comparator接口的compare()方法,再作为比较器传参,就可以现在自定义排序了。
public class test1 {
public static void main(String args[]) throws IOException {
//注意,要想改变默认的排列顺序,不能使用基本类型(int,double, char),而要使用它们对应的类
Integer[] arr = {
9, 8, 7, 2, 3, 4, 1, 0, 6, 5};
//定义一个自定义类MyComparator的对象
Comparator cmp = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return (Integer)o1 > (Integer)o2 ? -1 :1;
}
};
Arrays.sort(arr,cmp);
System.out.println(Arrays.toString(arr));
}
}
Arrays.cort()逆序排序
Integer[] a = {
9, 8, 7, 2, 3, 4, 1, 0, 6, 5};
Arrays.sort(a,Collections.reverseOrder()); //Collections.reverseOrder()在方法调用返回一个比较器,它强行上实现Comparable接口的对象的集合的自然顺序相反。
System.out.println(Arrays.toString(a));
二、Collections.cort()
List<Integer> intList = Arrays.asList(33, 24, 18, 6, 9, 99);
Collections.sort(intList);
Collections.sort()自定义排序
Collections.sort(personList, new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.getAge() > p2.getAge() ? 1 : -1;//升序
}
});
三、面试重点:源码分析
一、Arrays.sort()
基本类型:采用调优的快速排序;
对象类型:采用改进的归并排序。
1、基本类型
数组长度小于47的时候是用直接插入算法,大于47并且小于286是采用双轴快速排序,大于286如果连续性好「也就是元素大多有序,有一个flag专门用来记录数组元素的升降次数,代表这个数组的连续性」采用的是归并排序,否则还是依旧采用双轴快速排序。
小于286(小于47/大于47并且小于286)
private static void sort(int[] a, int left, int right, boolean leftmost) {
int length = right - left + 1;
// 长度小于47,使用直接插入排序
if (length < INSERTION_SORT_THRESHOLD) {
if (leftmost) {
/*
* Traditional (without sentinel) insertion sort,
* optimized for server VM, is used in case of
* the leftmost part.
*/
for (int i = left, j = i; i < right; j = ++i) {
int ai = a[i + 1];
while (ai < a[j]) {
a[j + 1] = a[j];
if (j-- == left) {
break;
}
}
a[j + 1] = ai;
}
}
//长度大于47小于286
else {
//双轴快速排序
}
大于等于286
static void sort(int[] a, int left, int right,
int[] work, int workBase, int workLen) {
// 小于286排序
if (right - left < QUICKSORT_THRESHOLD) {
sort(a, left, right, true);
return;
}
/*
* Index run[i] is the start of i-th run
* (ascending or descending sequence).
*/
int[] run = new int[MAX_RUN_COUNT + 1];
int count = 0; run[0] = left;
//检查数组是否接近排好序
for (int k = left; k < right; run[count] = k) {
if (a[k] < a[k + 1]) {
// 上升
while (++k <= right && a[k - 1] <= a[k]);
} else if (a[k] > a[k + 1]) {
// 下降
while (++k <= right && a[k - 1] >= a[k]);
for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
int t = a[lo]; a[lo] = a[hi]; a[hi] = t;
}
} else {
// 相等
for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
if (--m == 0) {
sort(a, left, right, true);
return;
}
}
}
/*
*连续性不好,
*依然使用快速排序.
*/
if (++count == MAX_RUN_COUNT) {
sort(a, left, right, true);
return;
}
}
//检查特殊情况
// Implementation note: variable "right" is increased by 1.
if (run[count] == right++) {
// The last run contains one element
run[++count] = right;
} else if (count == 1) {
// The array is already sorted
return;
}
/*
*连续性好,
*使用归并排序.
*/
.............
}
}
2、对象类型
TimSort.sort()
public static void sort(Object[] a) {
if (LegacyMergeSort.userRequested)//如果设置了归并排序为true
legacyMergeSort(a);
else//否则使用TimeSort(结合了归并排序和插入排序)
ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
}
当待排序元素小于32个时,采用二分插入排序,是插入排序的一种改进。
当待排序元素大于等于32个时,进行归并排序。
二、Collectiom.sort()
@SuppressWarnings({
"unchecked", "rawtypes"})
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
使用的是Arrays.sort()中的TimSort.sort()
总结:Arrays.sort()分为基本数据类型和对象类型。Collections.sort()是先转换为数组,再调用Arrays.sort(),也就是对象类型。