深入理解java中Arrays.sort()的用法
作者:github_38838414 发布时间:2021-05-26 22:25:58
Java的Arrays类中有一个sort()方法,该方法是Arrays类的静态方法,在需要对数组进行排序时,非常的好用。
但是sort()的参数有好几种,基本上是大同小异,下面是以int型数组为例的Arrays.sort()的典型用法
import java.util.Arrays;
import java.util.Comparator;
/**
* Arrays.sort()排序
*/
public class SortTest
{
public static void main(String []args)
{
int[] ints=new int[]{2,324,4,57,1};
System.out.println("增序排序后顺序");
Arrays.sort(ints);
for (int i=0;i<ints.length;i++)
{
System.out.print(ints[i]+" ");
}
System.out.println("\n减序排序后顺序");
//要实现减序排序,得通过包装类型数组,基本类型数组是不行滴
Integer[] integers=new Integer[]{2,324,4,4,6,1};
Arrays.sort(integers, new Comparator<Integer>()
{
/*
* 此处与c++的比较函数构成不一致
* c++返回bool型,而Java返回的为int型
* 当返回值>0时
* 进行交换,即排序(源码实现为两枢轴快速排序)
*/
public int compare(Integer o1, Integer o2)
{
return o2-o1;
}
public boolean equals(Object obj)
{
return false;
}
});
for (Integer integer:integers)
{
System.out.print(integer+" ");
}
System.out.println("\n对部分排序后顺序");
int[] ints2=new int[]{212,43,2,324,4,4,57,1};
//对数组的[2,6)位进行排序
Arrays.sort(ints2,2,6);
for (int i=0;i<ints2.length;i++)
{
System.out.print(ints2[i]+" ");
}
}
}
排序结果如下
增序排序后顺序
1 2 4 57 324
减序排序后顺序
324 6 4 4 2 1
对部分排序后顺序
212 43 2 4 4 324 57 1
打开Arrays.sort()源码,还是以int型为例,其他类型也是大同小异
public static void sort(int[] a) {
DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}
public static void sort(int[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
DualPivotQuicksort.sort(a, fromIndex, toIndex - 1, null, 0, 0);
}
从源码中发现,两种参数类型的sort方法都调用了 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;
}
/*
* 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;
// Check if the array is nearly sorted
for (int k = left; k < right; run[count] = k) {
if (a[k] < a[k + 1]) { // ascending
while (++k <= right && a[k - 1] <= a[k]);
} else if (a[k] > a[k + 1]) { // descending
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 { // equal
for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
if (--m == 0) {
sort(a, left, right, true);
return;
}
}
}
/*
* The array is not highly structured,
* use Quicksort instead of merge sort.
*/
if (++count == MAX_RUN_COUNT) {
sort(a, left, right, true);
return;
}
}
// Check special cases
// 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;
}
// Determine alternation base for merge
byte odd = 0;
for (int n = 1; (n <<= 1) < count; odd ^= 1);
// Use or create temporary array b for merging
int[] b; // temp array; alternates with a
int ao, bo; // array offsets from 'left'
int blen = right - left; // space needed for b
if (work == null || workLen < blen || workBase + blen > work.length) {
work = new int[blen];
workBase = 0;
}
if (odd == 0) {
System.arraycopy(a, left, work, workBase, blen);
b = a;
bo = 0;
a = work;
ao = workBase - left;
} else {
b = work;
ao = 0;
bo = workBase - left;
}
// Merging
for (int last; count > 1; count = last) {
for (int k = (last = 0) + 2; k <= count; k += 2) {
int hi = run[k], mi = run[k - 1];
for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
if (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
b[i + bo] = a[p++ + ao];
} else {
b[i + bo] = a[q++ + ao];
}
}
run[++last] = hi;
}
if ((count & 1) != 0) {
for (int i = right, lo = run[count - 1]; --i >= lo;
b[i + bo] = a[i + ao]
);
run[++last] = right;
}
int[] t = a; a = b; b = t;
int o = ao; ao = bo; bo = o;
}
}
结合文档以及源代码,我们发现,jdk中的Arrays.sort()的实现是通过所谓的双轴快排的算法
/**
* This class implements the Dual-Pivot Quicksort algorithm by
* Vladimir Yaroslavskiy, Jon Bentley, and Josh Bloch. The algorithm
* offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations.
*
* All exposed methods are package-private, designed to be invoked
* from public methods (in class Arrays) after performing any
* necessary array bounds checks and expanding parameters into the
* required forms.
*
* @author Vladimir Yaroslavskiy
* @author Jon Bentley
* @author Josh Bloch
*
* @version 2011.02.11 m765.827.12i:5\7pm
* @since 1.7
*/
Java1.8的快排是一种双轴快排,顾名思义:双轴快排是基于两个轴来进行比较,跟普通的选择一个点来作为轴点的快排是有很大的区别的,双轴排序利用了区间相邻的特性,对原本的快排进行了效率上的提高,很大程度上是利用了数学的一些特性。。。。。嗯。。。反正很高深的样子
算法步骤
1.对于很小的数组(长度小于27),会使用插入排序。
2.选择两个点P1,P2作为轴心,比如我们可以使用第一个元素和最后一个元素。
3.P1必须比P2要小,否则将这两个元素交换,现在将整个数组分为四部分:
(1)第一部分:比P1小的元素。
(2)第二部分:比P1大但是比P2小的元素。
(3)第三部分:比P2大的元素。
(4)第四部分:尚未比较的部分。
在开始比较前,除了轴点,其余元素几乎都在第四部分,直到比较完之后第四部分没有元素。
4.从第四部分选出一个元素a[K],与两个轴心比较,然后放到第一二三部分中的一个。
5.移动L,K,G指向。
6.重复 4 5 步,直到第四部分没有元素。
7.将P1与第一部分的最后一个元素交换。将P2与第三部分的第一个元素交换。
8.递归的将第一二三部分排序。
疑问:为啥不用泛型
来源:https://blog.csdn.net/github_38838414/article/details/80642329


猜你喜欢
- 简单说明一下:线程池可以看做容纳线程的容器;一个应用程序最多只能有一个线程池;ThreadPool静态类通过QueueUserWorkIte
- 一.关于使用Mybatisplus自带的selectById和insert方法时的一些问题1.selectById的问题(1).表的主键列名
- 本想把练习题做了的结果放上来,不过发现附录是有答案的,就算了吧,自己做了没问题就行了哈。之前提到过,要是有朋友有想法,需要做小工具我可以帮忙
- 今日遇到一个问题:springboot需要获取到一个自定义名称文件夹下的静态资源(图片等),并且文件夹的路径不在classPath下面,而是
- 本文实例讲述了Java二维数组。分享给大家供大家参考,具体如下:一 点睛1 每行的元素个数不同的二维数组Java定义二维数组更加灵活,允许二
- 第1类:嵌套模式package day14;import java.io.FileInputStream;import java.io.Fi
- Pom文件的依赖我们进入POM文件,首先是看到的是Pom文件中的parentparent是Spring Boot的框架版本控制中心<!
- 一、文件上传的原理分析1、文件上传的必要前提a、表单的method必须是postb、表单的enctype属性必须是multipart/for
- Java-Web获取客户端真实IP:发生的场景:服务器端接收客户端请求的时候,一般需要进行签名验证,客户端IP限定等情况,在进行客户端IP限
- 本文实例为大家分享了Android简单自定义音乐波动特效图的具体代码,供大家参考,具体内容如下最终效果:思路:就是绘制一个不断变化高度的矩形
- 一 介绍本节给知识追寻者给大家带来的是springSecurity入门篇,主要是简述下springSecrurity的启动原理和简单的入门搭
- 借用@Caching实现入参是基本类型的:@Caching(evict={@CacheEvict(value = Cache.CONSTAN
- 前言继承是面向对象语法的三大特征之一。继承可以降低代码编写的冗余度,提高编程的效率。通过继承,子类获得了父类的成员变量和方法。一个子类如何继
- 本文实例为大家分享了spring aop注解配置的具体代码,供大家参考,具体内容如下Demo.javapackage cn.itcast.e
- 对于学习过C语言的朋友应该都知道,使用 malloc/calloc 等分配内存的函数时,一定要检查其返回值是否为“空指针”(亦即检查分配内存
- 著名的Java单元测试框架Junit 4已经出来很长时间了,当时我发现JUnit 5已经处于测试版,就准备写文章来介绍JUnit 5.不过因
- 开发中有时候需要自己封装分页排序时,List如何对某一属性排序呢,分享一个小实例,大家共勉,希望能对大家有用,请多多指教。1.Student
- 前言我们在日常的开发中有时候会遇到需要用到相机的需求,而相机也是很常用的东西,例如扫二维码啊拍照上传啊等等。这里我不讲像qq那样自定义很强的
- Spire.Cloud.SDK for .NET提供了接口PdfSecurityApi可用于加密、解密PDF文档。本文将通过C#代码演示具体
- 由于之前一直在使用spring-boot开发,但一直苦恼于不知道如何利用debug调试代码.在网上查找了很多文章之后。学习之余决定把spri