Arrays
本系列的Java源码版本是官网最新版java 11
该类是一个工具类,从名字可以看出是对数组操作的工具类。java中还有很多这样的工具类,类名后面加s表示该类型的工具类,比如 Collections
等等。该类方法比较多,我会分几个主题来讲解。
排序
Arrays
中的排序是通过 DualPivotQuicksort
这个类实现的,首先我们看看 sort
这个方法的具体实现
static void sort(int[] a, int left, int right,
int[] work, int workBase, int workLen) {
// Use Quicksort on small arrays
if (right - left < QUICKSORT_THRESHOLD) {
sort(a, left, right, true);
return;
}
...
}
QUICKSORT_THRESHOLD
这个变量是快速排序的阈值(286),当数组长度小于这个数的时候使用快速排序。为啥是这个值后续我们再探讨。
private static void sort(int[] a, int left, int right, boolean leftmost) {
int length = right - left + 1;
// Use insertion sort on tiny arrays
if (length < INSERTION_SORT_THRESHOLD) {
...
return;
}
}
INSERTION_SORT_THRESHOLD
这个变量也是一个阈值(47),当数组长度小于这个数的时候使用插入排序。看看java是如何实现插入排序的
/*
* 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;
}
首先代码有个地方非常迷惑 j-- == left
,这个分成2部:
- j == left
- j = j - 1
我通过 javap -l -c QuicksortMain
查看了编译的字节码如下:
...
53: iload 4 // 将j放入栈中
55: iinc 4, -1 // 将本地变量j-1,但是不改变已经入栈的值
58: iload_1 // 将left放入栈中
59: if_icmpne 24 // 判断栈里面的j和left,如果不相等跳转到 int ai = a[i + 1]
...
LocalVariableTable:
Slot Name
1 left
4 j
java中实现了2种插入排序,这种是传统的插入排序也称之为无哨兵模式,插入排序的代码思路如下:
i和j左边的都是排好序的,每次从数组选择一个元素ai(i+1)依次同左边的每一个元素aj进行比较,如果ai<aj则将aj腾挪到右边相邻的位置上,否则将ai赋值给aj
下一节继续研究
未完待续