Java中List排序的3种方法!

news2024/11/18 14:44:20

引用:https://blog.csdn.net/sinat_32849897/article/details/122098256

在某些特殊的场景下,我们需要在 Java 程序中对 List 集合进行排序操作。比如从第三方接口中获取所有用户的列表,但列表默认是以用户编号从小到大进行排序的,而我们的系统需要按照用户的年龄从大到小进行排序,这个时候,我们就需要对 List 集合进行自定义排序操作了。

List 排序的常见方法有以下 3 种:

1.使用 Comparable 进行排序;

2.使用 Comparator 进行排序;

3.如果是 JDK 8 以上的环境,也可以使用 Stream 流进行排序。

下面我们分别来看各种排序方法的具体实现。

1.使用 Comparable 排序:

按照本文设计的场景,我们需要创建一个包含了用户列表的 List 集合,并按用户的年龄从大到小进行排序,具体实现代码如下:

public class ListSortExample {
    public static void main(String[] args) {
        // 创建并初始化 List
        List<Person> list = new ArrayList<Person>() {{
            add(new Person(1, 30, "北京"));
            add(new Person(2, 20, "西安"));
            add(new Person(3, 40, "上海"));
        }};
        // 使用 Comparable 自定的规则进行排序
        Collections.sort(list);
        // 打印 list 集合
        list.forEach(p -> {
            System.out.println(p);
        });
    }
}
 
//  以下 set/get/toString 使用的是 lombok 的注解
@Getter
@Setter
@ToString
class Person implements Comparable<Person> {
    private int id;
    private int age;
    private String name;
 
    public Person(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
 
    @Override
    public int compareTo(Person p) {
        return p.getAge() - this.getAge();
    }
}

以上代码的执行结果,如下图所示:
在这里插入图片描述
本方法的核心代码如下:
在这里插入图片描述

2.使用 Comparator 排序

Comparable 是类内部的比较方法,而 Comparator 是排序类外部的比较器。使用 Comparator 比较器,无需修改原 Person 类,只需要扩充一个 Person 类的比较器就行了,Comparator 的实现方法有以下两种:

  • 新建 Comparator 比较器;
  • 使用 Comparator 匿名类比较器。

其中,第二种实现方法要更简洁一些,我们通过下面的具体代码,来观察一下二者的区别。

2.1 新建 Comparator 比较器

public class ListSortExample2 {
    public static void main(String[] args) {
        // 创建并初始化 List
        List<Person> list = new ArrayList<Person>() {{
            add(new Person(1, 30, "北京"));
            add(new Person(2, 20, "西安"));
            add(new Person(3, 40, "上海"));
        }};
        // 使用 Comparator 比较器排序
        Collections.sort(list, new PersonComparator());
        // 打印 list 集合
        list.forEach(p -> {
            System.out.println(p);
        });
    }
}
/**
 * 新建 Person 比较器
 */
class PersonComparator implements Comparator<Person> {
    @Override
    public int compare(Person p1, Person p2) {
        return p2.getAge() - p1.getAge();
    }
}
@Getter
@Setter
@ToString
class Person {
    private int id;
    private int age;
    private String name;
 
    public Person(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
}

以上代码的执行结果,如下图所示:
在这里插入图片描述
本方法的核心实现代码如下:
在这里插入图片描述
2.2 匿名类比较器
比较器 Comparator 可以使用更简洁的匿名类的方式,来实现排序功能,具体实现代码如下:

public class ListSortExample2 {
    public static void main(String[] args) {
        // 创建并初始化 List
        List<Person> list = new ArrayList<Person>() {{
            add(new Person(1, 30, "北京"));
            add(new Person(2, 20, "西安"));
            add(new Person(3, 40, "上海"));
        }};
        // 使用匿名比较器排序
        Collections.sort(list, new Comparator<Person>() {
            @Override
            public int compare(Person p1, Person p2) {
                return p2.getAge() - p1.getAge();
            }
        });
        // 打印 list 集合
        list.forEach(p -> {
            System.out.println(p);
        });
    }
}
@Getter
@Setter
@ToString
class Person {
    private int id;
    private int age;
    private String name;
    public Person(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
}

以上代码的执行结果,如下图所示:
在这里插入图片描述
3.使用 Stream 流排序
在 JDK 8 之后可以使用更加简单的方法 Stream 流来实现排序功能,它的实现只需要一行代码,具体实现如下:

public class ListSortExample3 {
    public static void main(String[] args) {
        // 创建并初始化 List
        List<Person> list = new ArrayList<Person>() {{
            add(new Person(1, 30, "北京"));
            add(new Person(2, 20, "西安"));
            add(new Person(3, 40, "上海"));
        }};
        // 使用 Stream 排序
        list = list.stream().sorted(Comparator.comparing(Person::getAge).reversed())
                .collect(Collectors.toList());
        // 打印 list 集合
        list.forEach(p -> {
            System.out.println(p);
        });
    }
    @Getter
    @Setter
    @ToString
    static class Person {
        private int id;
        private int age;
        private String name;
        public Person(int id, int age, String name) {
            this.id = id;
            this.age = age;
            this.name = name;
        }
    }
}

其中 reversed() 表示倒序的意思,如果不使用此方法则是正序。

以上代码的执行结果,如下图所示:
在这里插入图片描述
扩展:排序字段为 null
使用 Stream 进行排序时,如果排序的字段出现 null 值就会导致异常发生,具体示例如下:

public class ListSortExample4 {
    public static void main(String[] args) {
        // 创建并初始化 List
        List<Person> list = new ArrayList<Person>() {{
            add(new Person(30, "北京"));
            add(new Person(10, "西安"));
            add(new Person(40, "上海"));
            add(new Person(null, "上海")); // 年龄为 null 值
        }};
        // 按照[年龄]正序,但年龄中有一个 null 值
        list = list.stream().sorted(Comparator.comparing(Person::getAge))
                .collect(Collectors.toList());
        // 打印 list 集合
        list.forEach(p -> {
            System.out.println(p);
        });
    }
}
@Getter
@Setter
@ToString
class Person {
    private Integer age;
    private String name;
 
    public Person(Integer age, String name) {
        this.age = age;
        this.name = name;
    }
}

以上代码的执行结果,如下图所示:
在这里插入图片描述
想要解决上述问题,需要给 Comparator.comparing 传递第二个参数:Comparator.nullsXXX,如下代码所示:

public class ListSortExample4 {
    public static void main(String[] args) {
        // 创建并初始化 List
        List<Person> list = new ArrayList<Person>() {{
            add(new Person(30, "北京"));
            add(new Person(10, "西安"));
            add(new Person(40, "上海"));
            add(new Person(null, "上海"));
        }};
        // 按照[年龄]正序,但年龄中有一个 null 值
        list = list.stream().sorted(Comparator.comparing(Person::getAge,
                Comparator.nullsFirst(Integer::compareTo)))
                .collect(Collectors.toList());
        // 打印 list 集合
        list.forEach(p -> {
            System.out.println(p);
        });
    }
}
@Getter
@Setter
@ToString
class Person {
    private Integer age;
    private String name;
 
    public Person(Integer age, String name) {
        this.age = age;
        this.name = name;
    }
}

Comparator.nullsFirst 表示将排序字段中的 null 值放到集合最前面,如果想要将 null 值放到集合最后面可以使用 Comparator.nullsLast。

以上代码的执行结果,如下图所示:
在这里插入图片描述

总结:
本文介绍了 3 种 List 排序的方法,前两种方法常用于 JDK 8 之前的版本,其中比较器 Comparator 有两种实现的写法,而在 JDK 8 之后的版本,就可以使用 Comparator.comparing 实现排序了,如果排序字段中可能出现 null 值,要使用 Comparator.nullsXXX 进行排序处理(否则会报错)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/348613.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

acwing 2 普通背包 2维做法的坑

背包问题应该都挺熟了&#xff0c;但还是放一下题目 无论是一维还是二维的解法&#xff0c;思路都比较一致&#xff0c;就是用一个二维的dpdpdp矩阵&#xff0c;dp[i][j]dp[i][j]dp[i][j] 的定义为前 iii 个元素的最优组合在容量为 jjj 的背包的最大价值。 这个定义非常的巧妙…

前缀和-蓝桥杯

一、前缀和的概念数组a[0]~ a[n-1]&#xff0c;前缀和sum[i]等于a[0] ~ a[i]的和:sum[0] a[0]sum[1] a[0] a[1]sum[2] a[0] a[1] a[2] ......在O(n)时间内求所有前缀和: sum[i] sum[i-l] a[i]a[0]一般不用。二、前缀和与区间问题预计算出前缀和&#xff0c;能快速计算出区…

C语言结构体(初阶)声明、初始化、成员访问、传参

目录结构体类型的声明结构体变量的定义和初始化结构体成员访问结构体传参1.结构体类型的声明//1. struct Book {char name[20];int price; //成员列表 }b3,b4,b5;//全局变量 int main() {struct Book b1;//b1,b2局部变量struct Book b2;return 0; }//2. struct Book {char n…

重磅!ChatGPT席卷全球,Salesforce将推出EinsteinGPT!

2月9日&#xff0c;Salesforce首席执行官Marc Benioff在Twitter上发布了这样一则推文&#xff0c;表示将于3月7日的TrailblazerDX 23上发布Salesforce EinsteinGPT&#xff0c;随后Salesforce的官方Twitter也进行了转发。 虽然还没有正式的新闻稿&#xff0c;但不少业内人士猜测…

C++【模板初阶】

✨个人主页&#xff1a; Yohifo &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f38a;每篇一句&#xff1a; 图片来源 No one saves us but ourselves, no one can and no one may. We ourselves must walk the path. 除了我们自己&#xff0c;没有人能拯救我们&#xf…

FreeRTOS-Tickless低功耗模式 | FreeRTOS十四

目录 说明&#xff1a; 一、低功耗模式简介 1.1、STM32低功耗模式 二、Tickless模式 2.1、Tickless模式如何功耗 2.2、Tickless模式设计思想 2.3、为了降低功耗&#xff0c;又不影响系统运行&#xff0c;怎么能做到呢&#xff1f; 三、Tickless模式修改配置 3.1、配置…

如何提升 ETF 期权隐含波动率和希腊值的计算速度?

期权的隐含波动率可以反应市场对未来的预期&#xff0c;通常使用牛顿法和二分法来计算。这两种方法都需要频繁迭代&#xff0c;且迭代次数不能确定&#xff0c;核心代码无法向量化&#xff0c;因此只能通过循环来逼近求解。这就导致在期权相关计算中&#xff0c;隐含波动率往往…

PO模式在Selenium中简单实践

初识PO模式 PO&#xff08;PageObject&#xff09;是一种设计模式。简单来说就是把一些繁琐的定位方法、元素操作方式等封装到类中&#xff0c;通过类与类之间的调用完成特定操作。 PO被认为是自动化测试项目开发实践的最佳设计模式之一。 在学习PO模式前&#xff0c;可以先…

InstructGPT笔记

一、InstructGPT是在GPT3上微调&#xff0c;ChatGPT是在GPT3.5上微调 二、该论文展示了怎么样对语言模型和人类意图之间进行匹配&#xff0c;方法是在人类的反馈上进行微调。 **三、方法简介&#xff1a;**收集很多问题&#xff0c;使用标注工具将问题的答案写出来&#xff0…

大数据面试题flume篇

1.Flume 的Source&#xff0c;Sink&#xff0c;Channel 的作用&#xff1f;你们Source 是什么类型&#xff1f; 1. 作用 &#xff08;1&#xff09;Source组件是专门用来收集数据的&#xff0c;可以处理各种类型、各种格式的日志数据&#xff0c;包括 avro、thrift、exec、jm…

Nginx介绍及安装(windows版,Linux版)

目录 一、Nginx介绍 1、Nginx优势 2、Nginx作用 3、部署静态资源 4、代理 5、负载均衡 二、Nginx安装步骤&#xff08;windows版&#xff09; 三、Nginx安装步骤&#xff08;Linux版&#xff09; 1、官网下载安装包&#xff0c;下载完之后上传到Linux系统上 2、在Lin…

股票量化策略是如何被执行出来的?

在股票量化方面&#xff0c;很多投资者是不知道怎么样挖掘量化策略&#xff0c;便在量化交易接口方面会通过股票交易接口将数据慢慢挖掘出来&#xff0c;就简单的通过api接口调用数据方面&#xff0c;直接通过交易接口端输出交易持仓数据&#xff0c;并且通过交易系统对数据的筛…

什么是“镜像浏览”?文件夹加密后的镜像浏览有什么用?

电脑中的文件夹经常用来储存各种重要文件&#xff0c;加密保护成为很多人的选择&#xff0c;而夏冰加密软件拥有各种适用于不同场景的文件夹加密软件&#xff0c;备受用户喜爱。在我们打开加密文件夹之后&#xff0c;我们可以在加密控制面板中发现“镜像浏览”的按钮&#xff0…

Sharding-jdbc

一、概念理解垂直切分&#xff1a;包含垂直分库和垂直分表1.1、垂直分库 &#xff1a;专库专用&#xff08;按照业务类型对表分类&#xff09;1.2、垂直分表&#xff1a;基于数据表的列&#xff08;字段&#xff09;为依据切分的&#xff0c;是一种大表拆小表的模式。1.3、垂直…

【Python--torch(激活函数说明+代码讲解)】激活函数(sigmoid/softmax/ELU/ReLU/LeakyReLU/Tanh)

【Python–torch】激活函数(sigmoid/softmax/ELU/ReLU/LeakyReLU/Tanh) 文章目录【Python--torch】激活函数(sigmoid/softmax/ELU/ReLU/LeakyReLU/Tanh)1. 介绍2. 常用激活函数说明2.1 Sigmoid2.1.1 公式2.1.2 图像2.1.3 代码解读2.2 Softmax2.2.1 公式2.2.2 代码解读2.3 ELU2.…

荧光探针Pyrene-PEG2-Propargyl,芘甲酰胺-二聚乙二醇-丙炔

Pyrene-PEG2-Propargyl物理参数&#xff1a; CAS号&#xff1a;N/A | 英文名&#xff1a;Pyrene-PEG2-Propargyl |中文名&#xff1a;芘甲酰胺-二聚乙二醇-丙炔分子式&#xff1a;C24H21NO3分子量&#xff1a;371.44纯度标准&#xff1a;95%外形颜色&#xff1a;淡黄色或白色固…

shell学习4

目录 一、统计文本中的词频 二、压缩javascript 三、打印文件的或行中的第n个单词或列---awk 3.1 利用awk打印文件中每行中的第五个单词。 3.2 利用awk打印当前目录下的文件的权限和文件名 3.3 利用awk打印从M行到N行这个范围内的所有文本 3.4 利用awk 部分提取文件中的内…

opencv复习

文章目录图像衡量结果&#xff08;损失函数&#xff09;预测的好坏前向传播 反向传播图像 实质是矩阵 长 宽 像素通道&#xff08;0-255 0 黑 255 亮&#xff09; 假设这里做一个10分类 行向量✖列向量是一个数 分类 最后的结果是一个各个分类的概率值 这里的b是偏置项&…

学校节能降耗减排方案——能耗监管平台的建设及效果剖析

摘要&#xff1a;作为崭新的校园能耗管理手段&#xff0c;能耗监测平台以传统管理方式无法企及的优势有力地提升了高校能源管理工作的水平&#xff0e;从而受到了相关管理者的青睐。本文梳理总结了高校能耗监测平台的基本组成和优势特点&#xff0c;同时对能耗平台建设和使用中…

nginx设置重定向跳转后ip:[端口]/abc变成ip/abc而报错404

nginx设置重定向跳转后 ip:[端口]/abc 变成 ip/abc 而报错404nginx配置&#xff1a;server {listen 80;server_name _;client_max_body_size 300m;absolute_redirect off;location / {root html;index index.html index.htm;proxy_set_header X-Real-IP $remote_a…