首页 > 编程语言 >JAVA Comparator 自定义排序 源码分析

JAVA Comparator 自定义排序 源码分析

时间:2024-05-13 14:31:28浏览次数:23  
标签:src JAVA 自定义 int mid high dest 源码 low

对于一个数组来说
如果我们想要从大到小排序一般会这么写

Integer[] nums = {1,2,3};
Arrays.sort(nums, new Comparator<Integer>() {
            @Override
            public int compare(Integer a, Integer b) {
                return b - a;
            }
        });
//lambda 表达式
Arrays.sort(nums, (a, b) -> b - a);

为什么这么写可以? 我们以 Arrays.sort 源码为例看看到底是怎么排序的。

private static void mergeSort(Object[] src,
                                  Object[] dest,
                                  int low, int high, int off,
                                  Comparator c) {// c 就是我们实现的Comparator
        int length = high - low;

        // Insertion sort on smallest arrays
        if (length < INSERTIONSORT_THRESHOLD) {
            for (int i=low; i<high; i++)
                for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
                    swap(dest, j, j-1);
            return;
        }

        // Recursively sort halves of dest into src
        int destLow  = low;
        int destHigh = high;
        low  += off;
        high += off;
        int mid = (low + high) >>> 1;
        mergeSort(dest, src, low, mid, -off, c);
        mergeSort(dest, src, mid, high, -off, c);

        // If list is already sorted, just copy from src to dest.  This is an
        // optimization that results in faster sorts for nearly ordered lists.
        if (c.compare(src[mid-1], src[mid]) <= 0) {
           System.arraycopy(src, low, dest, destLow, length);
           return;
        }

        // Merge sorted halves (now in src) into dest
        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
    }

可以看到底层用的是归并排序,我们直接看最下面几行代码。

// Merge sorted halves (now in src) into dest
for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
    if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
        dest[i] = src[p++];
    else
        dest[i] = src[q++];
}

判断两数大小调用了我们实现的 Comparator c.compare

Arrays.sort(nums, (a, b) -> b - a);

那么分为两种情况

1.src[p] >= src[q]
那么 c.compare(src[p], src[q]) 我们返回的是 src[q] - src[p] 返回的是一个小于等于0的数 也就意味着 下标 p++ 也就是说谁大谁的下标后移了
也就实现了从大到小排序

2.src[p] < src[q]
同上分析

对于其他的数据结构排序也是同样的规则

标签:src,JAVA,自定义,int,mid,high,dest,源码,low
From: https://www.cnblogs.com/ganyq/p/18189096

相关文章

  • Java Chassis 3:接口维度负载均衡
    本文分享自华为云社区《JavaChassis3技术解密:接口维度负载均衡》,作者:liubao68。在JavaChassis3技术解密:负载均衡选择器中解密了JavaChassis3负载均衡在解决性能方面提供的算法。这次解密的技术来源于实际客户案例:在客户的微服务系统中,存在很多种不同逻辑的接口,以及特殊......
  • [LeetCode] 1584.连接所有点的最小费用 Kruskal And Prim 算法 Java 并查集
    Problem:1584.连接所有点的最小费用目录Kruskal算法复杂度CodePrim算法复杂度CodeKruskal算法复杂度时间复杂度:添加时间复杂度,示例:$O(mlog(m))$空间复杂度:添加空间复杂度,示例:$O(n)$CodeclassSolution{publicintminCostConnectPoints(int[][]po......
  • 基于Java的redis客户端的基本使用
    1.简介Java中redis客户端有jedis、lettuce、Redission等2.jedis的基本使用引入依赖<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.2.3</version></dependency>从jedis连接池获取je......
  • JavaSE之java基础语法
    关键字和保留字关键字定义和特点定义:被java语言赋予了特殊含义,用作专门用途的字符串。特点:关键字中所有字母都为小写。关键字不能用作变量名,方法名,类名,包名和参数。用于定义数字类型的关键字classinterfaceenumbyteshortintlongfloatdoublecharbooleanvoi......
  • 软工计算1—Java篇1 20240513
    Java中的函数重载函数重载(FunctionOverloading)是面向对象编程中的一个概念,它允许在同一个类中定义多个同名函数,但这些函数的参数列表必须不同。参数列表的不同可以体现在参数的类型、数量或顺序上。函数重载使得程序设计更加灵活,可以针对不同的参数类型或数量提供不同的函数实现......
  • Go语言异常处理:自定义错误【errors.New+panic】
    程序本身抛出的异常信息不是太友好,我们可以自定义错误或者异常的信息,需要使用errors包中的New函数来包装一下异常或错误信息;在使用内置函数panic(err),把异常信息后面的程序执行终止掉,因为再执行后面的程序也没有意义了。 packagemainimport"fmt"import"errors"funcma......
  • UcOs-III 源码阅读: os_time.c
    对实时时钟源文件os_time.c进行源码阅读与注释://功能:Tick级别延时、时间延时、恢复延时中的任务、获取/设置系统Tick值、实时时钟滴答函数//Tick级别延时API:OSTimeDly(ticks)//时间延时API:OSTimeDlyHMSM(p_hmsm)//恢复延时API:OSTimeDlyResume(task_id)//获取系统T......
  • Tomcat中为什么要使用自定义类加载器
    Tomcat使用自定义类加载器主要是基于以下几个关键原因:1.应用隔离:Tomcat作为一个Web容器,能够同时部署和运行多个Web应用程序。每个应用可能依赖不同的库版本或者包含同名类,为了确保每个应用的类库相互独立,避免类冲突,Tomcat为每个Web应用提供了一个独立的类加载器实例,即`WebAppC......
  • Tomcat中为什么要使用自定义类加载器
    Tomcat使用自定义类加载器主要是基于以下几个关键原因:1.应用隔离:Tomcat作为一个Web容器,能够同时部署和运行多个Web应用程序。每个应用可能依赖不同的库版本或者包含同名类,为了确保每个应用的类库相互独立,避免类冲突,Tomcat为每个Web应用提供了一个独立的类加载器实例,即`WebAppC......
  • Java 高效获取两个List中不同的元素集合
    /***借助Map来获取listA、listB的不同元素集合**@paramlistA集合A*@paramlistB集合B*@returnlist<String>不同元素集合*/publicstaticList<String>getDifferListByMap(List<String>listA,List<String>listB){List<String>differList=new......