Java中List排序的3种方法!

5a8964bd45b0cf7b7de61686684125e7.png

作者 | 王磊

来源 | Java中文社群(ID:javacn666)

转载请联系授权(微信ID:GG_Stone)

在某些特殊的场景下,我们需要在 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) {// 创建并初始化 ListList<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;}@Overridepublic int compareTo(Person p) {return p.getAge() - this.getAge();}
}

以上代码的执行结果,如下图所示:c70311beaaf77dfacac90795f3a35cea.png本方法的核心代码如下:ad4f60049a52a544a4e01b4f128f759c.png

2.使用 Comparator 排序

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

  • 新建 Comparator 比较器;

  • 使用 Comparator 匿名类比较器。

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

2.1 新建 Comparator 比较器

public class ListSortExample2 {public static void main(String[] args) {// 创建并初始化 ListList<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> {@Overridepublic 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;}
}

以上代码的执行结果,如下图所示:edbf76dbcac671b5a0b1041a9988485b.png本方法的核心实现代码如下:1574dfc8e90ffb26bac4ff4b57a9f2a8.png

2.2 匿名类比较器

比较器 Comparator 可以使用更简洁的匿名类的方式,来实现排序功能,具体实现代码如下:

public class ListSortExample2 {public static void main(String[] args) {// 创建并初始化 ListList<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>() {@Overridepublic 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;}
}

以上代码的执行结果,如下图所示:d22f955d6c099dcaf649c82b5562937c.png

3.使用 Stream 流排序

在 JDK 8 之后可以使用更加简单的方法 Stream 流来实现排序功能,它的实现只需要一行代码,具体实现如下:

public class ListSortExample3 {public static void main(String[] args) {// 创建并初始化 ListList<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@ToStringstatic 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() 表示倒序的意思,如果不使用此方法则是正序。

以上代码的执行结果,如下图所示:9b84228074244a907b6e7cd1039a4fb3.png

扩展:排序字段为 null

使用 Stream 进行排序时,如果排序的字段出现 null 值就会导致异常发生,具体示例如下:

public class ListSortExample4 {public static void main(String[] args) {// 创建并初始化 ListList<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;}
}

以上代码的执行结果,如下图所示:71a22e906fa413a90d12f943ad908f88.png想要解决上述问题,需要给 Comparator.comparing 传递第二个参数:Comparator.nullsXXX,如下代码所示:

public class ListSortExample4 {public static void main(String[] args) {// 创建并初始化 ListList<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。

以上代码的执行结果,如下图所示:f975cc2b54b72f3c5e9bb96227a3825e.png

总结

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

卒然临之而不惊,无故加之而不怒。享受平凡生活中的喜悦,终身成长者。

博主:80 后程序员。

爱好:读书、写作和慢跑。

34c0bd022800fa756429820a8caa07ea.gif

往期推荐

fa4f8d24628ff6d928ba2f829ebd164a.png

面试官:如何实现 List 集合去重?


1242e4280176f6f50b8bbf5af3040373.png

面试官:HashMap有几种遍历方法?推荐使用哪种?


8ad234a8b12d055b5c193c95e4ff6008.png

面试官:元素排序Comparable和Comparator有什么区别?


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

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

相关文章

setdefault_Java语言环境setDefault()方法及示例

setdefault语言环境类setDefault()方法 (Locale Class setDefault() method) setDefault() method is available in java.util package. setDefault()方法在java.util包中可用。 setDefault() method is used to assign the default locale for this Locale instance of the JV…

Spring 事务失效的 8 种场景!

在日常工作中&#xff0c;如果对Spring的事务管理功能使用不当&#xff0c;则会造成Spring事务不生效的问题。而针对Spring事务不生效的问题&#xff0c;也是在跳槽面试中被问的比较频繁的一个问题。点击上方卡片关注我今天&#xff0c;我们就一起梳理下有哪些场景会导致Spring…

xcode6 AsynchronousTesting 异步任务测试

xcode集成了非常方便的测试框架&#xff0c;XCTest 在xcode6之后&#xff0c;提供了 <XCTest/XCTestCaseAsynchronousTesting.h> 利用此我们可以直接在XCTest里面测试一些异步的任务&#xff0c;比如异步网络请求 如下示例 - (void)testExample {XCTestExpectation *exce…

vscode无法识别constexpr

问题 vscode 无法识别constexpr&#xff08;常指针类型&#xff09; 方法 打开工程路径下的.vscode文件夹&#xff08;一般是自动隐藏的&#xff0c;CtrlH显示隐藏&#xff09;设置c_cpp_properties.json文件如下&#xff1a; {"configurations": [{"name…

三流Java搞技术,二流Java搞框架,一流Java…

如何反驳“99&#xff05; 的 Java 程序员都是 Spring 程序员”这句话&#xff1f;答案是不能。互联网发展至今&#xff0c;站在巨人肩膀上编程像一日三餐一样寻常。Spring Boot 的确凭一己之力拉低了 Java 开发的门槛&#xff0c;可普通开发与高开之间&#xff0c;真就因为一个…

java 方法 示例_Java语言环境getVariant()方法与示例

java 方法 示例区域设置类getVariant()方法 (Locale Class getVariant() method) getVariant() method is available in java.util package. getVariant()方法在java.util包中可用。 getVariant() method is used to get the variant code for this Locale. getVariant()方法用…

2.7-源码编译安装

网上下载源码包 wget http://网址 如果没有wget yum install -y wget建议下载下来的源码包&#xff0c;统一放到/usr/local/scr/下&#xff0c;方便维护管理养成查看INSTALL和README文档的习惯&#xff0c;内有软件安装方法和详细信息。1. ./configure --prefix/usr/l…

【Ubuntu】vscode配置PCL库/vscode无法导入PCL库

问题 PCL库是ROS框架自带的点云处理库&#xff0c;可以通过find_package(PCL REQUIRED)在CMakeLists.txt中导入&#xff0c;但是vscode却无法识别&#xff0c;出现问题如下&#xff1a; 注意&#xff0c;本文解决方案仅限Ubuntu&#xff01; 解决方案 打开工程路径下的.vsc…

面试官:HashSet是如何保证元素不重复的?

作者 | 磊哥来源 | Java面试真题解析&#xff08;ID&#xff1a;aimianshi666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;本文已收录《Java常见面试题》系列&#xff0c;开源地址&#xff1a;https://gitee.com/mydb/interviewHashSet 实现…

java bitset_Java BitSet nextSetBit()方法与示例

java bitsetBitSet类nextSetBit()方法 (BitSet Class nextSetBit() method) nextSetBit() method is available in java.util package. nextSetBit()方法在java.util包中可用。 nextSetBit() method is used to retrieve the index of the first bit that is set to true that …

STM32串口寄存器操作(转)

源&#xff1a;STM32串口寄存器操作 //USART.C/*********************************************************************************************************/ /* USART 收发 */ /* 陈鹏 20110611*/#include "SYSTEM.H" #include "GPIO_INIT.H" #inclu…

【Ubuntu】Ubuntu 20.04无法识别网口/以太网/有线网卡

这里写自定义目录标题0.症状1.查看网卡类型2.下载网卡驱动3.安装网卡驱动0.症状 \qquad表现为插入以太网网口后右上角没有显示网络&#xff0c;即没有下图的音量左侧的标志 打开设置的【网络】选项没有以太网接入&#xff0c;然而以太网口信号灯仍然正常闪烁。这种情况基本可以…

小心Lombok用法中的坑

刚才写完了代码&#xff0c;自测的时候&#xff0c;出现了NPE问题。排查的时候发现是Lombok的坑&#xff0c;以前也遇到过&#xff0c;所以觉得有必要过来记录一下。我先描述一下现象&#xff0c;我的代码里面订单服务A 需要调用缓存服务B&#xff0c;服务B就是一个Bean&#x…

Java BigDecimal negate()方法与示例

BigDecimal类的negate()方法 (BigDecimal Class negate() method) Syntax: 句法&#xff1a; public BigDecimal negate();public BigDecimal negate(MathContext ma_co);negate() method is available in java.math package. negate()方法在java.math包中可用。 negate() met…

【VSCode】VSCode使用conda环境时找不到python包/找不到Module

这里写自定义目录标题0.问题描述1.原因2.解决方法0.问题描述 \qquad首先需要排除是否是VSCode未配置conda环境的问题&#xff0c;当然&#xff0c;相信VSCode的老粉都不会犯这个低级错误&#xff0c;请CtrlP&#xff0c;在搜索框>select interpreter检查一下python环境。 …

PS如何对JPG文件直接抠图

如何JPG文件直接抠图 先转为智能对象&#xff1a; 再栅格化图层 此进即可直接进行抠图&#xff01;

更快的Maven来了,我的天,速度提升了8倍!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;周末被 maven-mvnd 刷屏了&#xff0c;于是我也下载了一个 mvnd 体验了一把。虽然测试的数据都是基于我本地项目&#xff0c…

java bitset_Java BitSet intersects()方法与示例

java bitsetBitSet类intersects()方法 (BitSet Class intersects() method) intersects() method is available in java.util package. intersects()方法在java.util包中可用。 intersects() method is used to check the common number of bits set to true in both the BitSe…

【C++】For循环同时初始化两个及以上个变量

文章目录0.引言1.初始化同类型变量2.初始化两个不同类型的变量0.引言 \qquadC的for循环在初始化时可以通过类型定义符直接初始化两个相同类型的变量&#xff0c;但是对于不同类型的变量是不可以直接初始化的&#xff0c;若想达到类似python的zip()函数的多类型多变量迭代的效果…

Java 中接口和抽象类竟然有 7 点不同?

作者 | 磊哥来源 | Java面试真题解析&#xff08;ID&#xff1a;aimianshi666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;本文已收录《Java常见面试题》系列&#xff1a;https://gitee.com/mydb/interviewJava 是一门面向对象的编程语言&am…