/**
下面在自己代码中使用Collections.sort()方法去比较Student对象,通过在自己写的类里面通过匿名内部类实现Comparator接口,这个接口是让你自己实现比较器的规则
*/
//把待排序的集合list 和 实现后的比较器Comparator一起传入Collections的sort方法
Collections.sort(list, new Comparator<Student>() {这行断点调试
@Override
public int compare(Student o1, Student o2) { //比较器规则
return o1.getAge()-o2.getAge();//升序 如果正数就把o1往后排,如果负数就把o1往前排,
// return o2.getAge()-o1.getAge();//降序
}
});

这里通过实现比较器接口实现排序
(自己重写compare()方法来返回一个整数或者负数,给sort()方法,然后底层其实使用的是二分排序)

进入Collections.java的以下方法:
public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c); //这里断点
}

继续调试,进入ArrayList.java的sort()方法:
@Override
/unchecked/
public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, size, c); //这行断点
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
modCount++;
}

进入Arrays.java的sort()方法:(中其实是把上面数组elementData,0,size,比较器传进来)
即传了集合本身,起始索引,结束索引,比较器
public static <T> void sort(T[] a, int fromIndex, int toIndex,
Comparator<? super T> c) {
if (c == null) { //没有比较器的时候
sort(a, fromIndex, toIndex);
} else {
rangeCheck(a.length, fromIndex, toIndex);
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, fromIndex, toIndex, c);
else
TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0); //通过前面判断跳到这里
//这里也是集合本身,起始索引,结束索引,比较器,还有另外三个参数不知道作用
}
}

然后进入了TimeSort.java的sort()方法:
//a是集合本身,lo是起始索引,hi是结束索引,c是比较器
static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
T[] work, int workBase, int workLen) {
assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;

int nRemaining = hi - lo;
if (nRemaining < 2)
return; // Arrays of size 0 and 1 are always sorted

// If array is small, do a "mini-TimSort" with no merges
if (nRemaining < MIN_MERGE) {
//a是集合本身,lo是起始索引,hi是结束索引,c是比较器
int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
binarySort(a, lo, hi, lo + initRunLen, c);
return;
}

然后进入同一类(TimeSort.java)中的countRunAndMakeAscending()方法:
//a是集合本身,lo是起始索引,hi是结束索引,c是比较器
private static <T> int countRunAndMakeAscending(T[] a, int lo, int hi,
Comparator<? super T> c) {
assert lo < hi;
int runHi = lo + 1; //起始索引+1
if (runHi == hi)
return 1;
//这里表示集合只有一个元素
// Find end of run, and reverse range if descending

//重点的比较在这里

if (c.compare(a[runHi++], a[lo]) < 0) { // Descending
while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)
runHi++;
reverseRange(a, lo, runHi);
} else { // Ascending
while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0)
runHi++;
}

return runHi - lo;
}

调用逻辑:
首先自己使用Collections.sort()比较对象的时候要实现比较器接口,然后把待排序的集合与比较器一起传入sort方法里
Collections.sort(list, new Comparator<Student>() {
@Override //下面重写接口抽象方法
});
public static <T> void sort(List<T> list, Comparator<? super T> c)
可以看到Collections.sort中的list传到了 List<T> list中的list,而匿名内部类对象传给 Comparator<? super T> c中的c.然后这个方法里使用了list.sort(c);然后会进入ArrayList的sort方法
运行到Arrays.sort((E[]) elementData, 0, size, c);这行后,调用Arrays的sort方法,再通过一些判断跳转到 TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0); //通过前面判断跳到这里,进入TimSort.sor()方法,通过判断进入了ountRunAndMakeAscending(a, lo, hi, c); 这个是TimeSort类的方法:然后通过以下代码比较:
if (c.compare(a[runHi++], a[lo]) < 0) { // Descending
//这里compare方法先拿a[1]和a[0]比较
while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)
//如果符合c.compare(a[1],a[0])<0,就循环判断c.compare(a[2],a[1]) c.compare(a[3],a[2])
runHi++;
//如果a[i]<a[i-1]执行交换,把较大的数换到后面
reverseRange(a, lo, runHi);
} else { // Ascending
while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0)
//如果a[i]>a[i-1]不用交换
runHi++;
}

return runHi - lo;
}

关于Collections.sort()排序方法的源码探索的更多相关文章

  1. Scala 深入浅出实战经典 第41讲:List继承体系实现内幕和方法操作源码揭秘

    Scala 深入浅出实战经典 第41讲:List继承体系实现内幕和方法操作源码揭秘 package com.parllay.scala.dataset /** * Created by richard ...

  2. 三种排序算法python源码——冒泡排序、插入排序、选择排序

    最近在学习python,用python实现几个简单的排序算法,一方面巩固一下数据结构的知识,另一方面加深一下python的简单语法. 冒泡排序算法的思路是对任意两个相邻的数据进行比较,每次将最小和最大 ...

  3. [Java源码解析] -- String类的compareTo(String otherString)方法的源码解析

    String类下的compareTo(String otherString)方法的源码解析 一. 前言 近日研究了一下String类的一些方法, 通过查看源码, 对一些常用的方法也有了更透彻的认识,  ...

  4. Pycharm中查看方法的源码

    方法1.鼠标放在函数上,Ctrl+B,看源码 方法2.将光标移动至要查看的方法处,按住ctrl 键,点击鼠标左键,即可查看该方法的源码.

  5. 如何查看laravel门脸类包含方法的源码

    以Route门脸类为例,我们定义路由时使用的就是Route门脸类,例如我们在web.php中定义的路由 use Illuminate\Support\Facades\Route; Route::get ...

  6. 《JAVA高并发编程详解》-Thread start方法的源码

    Thread start方法的源码:

  7. HttpServlet中service方法的源码解读

    前言     最近在看<Head First Servlet & JSP>这本书, 对servlet有了更加深入的理解.今天就来写一篇博客,谈一谈Servlet中一个重要的方法-- ...

  8. Tars | 第4篇 Subset路由规则业务分析与源码探索

    目录 前言 1. Subset不是负载均衡 1.1 任务需求 1.2 负载均衡源码结构图 1.3 负载均衡四种调用器 1.4 新增两种负载均衡调用器 1.5 Subset应该是"过滤&quo ...

  9. Eureka源码探索(一)-客户端服务端的启动和负载均衡

    1. Eureka源码探索(一)-客户端服务端的启动和负载均衡 1.1. 服务端 1.1.1. 找起始点 目前唯一知道的,就是启动Eureka服务需要添加注解@EnableEurekaServer,但 ...

随机推荐

  1. Android Studio 1.0~3.3加载android源码 笔记

    一. AS3.3上出现问题: 1. File Z:\Project\****\***\AndroidManifest.xml doesnt exist 分析引用: ------------------ ...

  2. SQL对于 小数处理的小结

    DECLARE @digital INT --截断小数位 ,,)),@digital) AS 截断小数位 --上抛小数位 ,,)),@digital) AS 上抛小数位 SELECT CEILING ...

  3. Win8 & WP8.1 轻型数据库

    自Win8 和 WP8.1 以来,MS把SQL CE去掉了.为了方便自己的APP升级,减少代码改动量,所以写了个小型的数据库管理,参考WP8.1之前的DataContext. 用时较短,花了几天的时间 ...

  4. JS面试Q&A(续2): Rest parameter,Arrow function 等

    rest parameter 和 Destructuring assignment. function fun1(...theArgs) { console.log(theArgs.length);} ...

  5. redis哨兵架构的基础知识及部署和管理

    一.前言 1.哨兵的介绍 sentinal,中文名是哨兵 哨兵是redis集群架构中非常重要的一个组件,主要功能如下 ()集群监控,负责监控redis master和slave进程是否正常工作 ()消 ...

  6. CSS ——padding

    css样式中使用padding(内边距)会将盒子撑开? 解决办法:在样式中添加box-sizing:border-box;

  7. java-框架-索引

    spring 整体了解 spring 入门demo Spring整体了解 spring梳理 Spring线程池的5个要素 spring的事务隔离级别以及传播性 事务4个隔离界别及脏读,不可重复读,幻读 ...

  8. An item with the same key has already been added. Key: Pomelo.EntityFrameworkCore.MySql.Infrastructure.Internal.MySqlOptionsExtension

    An item with the same key has already been added. Key: Pomelo.EntityFrameworkCore.MySql.Infrastructu ...

  9. qt qextserialport __imp_SetupDiGetDeviceRegistryPropertyW

    使用 qextserialport 编写串口助手的时候,提示找不到 __imp_SetupDiGetDeviceRegistryPropertyW,经过摸索有以下两种解决方法: 第一种: 把相应的源文 ...

  10. Android Jetpack 组建介绍(二)——Lifecycler

    参考Android Jetpack架构组件之 Lifecycle(源码篇) 源码分析 关于Lifecycle的使用考上一篇文章Android Jetpack框架之 Lifecycles(使用篇),从使 ...