浅谈Java中Collections.sort对List排序的两种方法
作者:wxx614817 发布时间:2021-11-18 11:20:22
目录
一、Collections.sort的简单使用
二、问题提出
三、Comparable实现排序
四、Comparator实现排序
五、Comparable 与Comparator区别
一、Collections.sort的简单使用
说到List的排序,第一反应当然是使用Collections.sort,方便简单。下面实现一下~~
private void sortStrings() {
List<String> list = new ArrayList<String>();
list.add("ccc");
list.add("aaa");
list.add("bbb");
//排序
Collections.sort(list);
//输出
Log.d(TAG, "-----------对字符串排序-----------");
for(String item : list) {
Log.d(TAG, item.toString());
}
}
=02-03 10:32:25.821: D/wxx(4732): -----------对字符串排序-----------
02-03 10:32:25.821: D/wxx(4732): aaa
02-03 10:32:25.821: D/wxx(4732): bbb
02-03 10:32:25.821: D/wxx(4732): ccc
可见,实现了对List<String>的排序,非常简单。
二、问题提出
但在我们的项目中列表List的元素类型经常是自定义的,下面自定义了一个实体类Person:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
然后,想对Person的列表List<Person>进行排序,首先想到的也是通过Collections.sort进行排序:
private void sortPerson() {
Person p1 = new Person("ccc", 20);
Person p2 = new Person("aaa", 18);
Person p3 = new Person("bbb", 16);
List<Person> list = new ArrayList<Person>();
list.add(p1);
list.add(p2);
list.add(p3);
//排序
Collections.sort(list);
}
发现,代码直接报错了:
Bound mismatch: The generic method sort(List<T>) of type Collections is not applicable for the arguments (List<Person>). The inferred type Person is not a valid substitute for the bounded
parameter <T extends Comparable<? super T>>
从上面可知,Person不是一个有效的参数类型,而应该extends Comparable。为什么?
原来,要排序嘛当然要有排序的规则,比如按身高从高到低,按年龄从小到大,等等,也就是要有比较。而String这个对象已经帮我们实现了Comparable接口,所以String类型自己就是可以比较的。而我们的Person如果想要排序,也必须能够按某种规则进行比较,也就是要实现一个比较器。我们可以通过实现Comparable或Comparator接口实现比较器 。
三、Comparable实现排序
Comparable实现比较器,是定义在Person类的内部的,所以实体类Person需要implements Comparable<Person>,然后重写compareTo方法,在此方法里实现比较规则,规则就是先比较名字,如果名字不一样则返回比较结果,如果名字一样,再比较年龄,返回比较结果:
public class Person implements Comparable<Person> {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public int compareTo(Person another) {
int i = name.compareTo(another.name); //比较名字字符串
if (i == 0) { //如果名字一样,则继续比较年龄
return age - another.age;
} else { //首先比较名字,名字不一样,则返回比较结果
return i;
}
}
}
后面就是对List<Person>进行排序并输出:
private void sortByComparable() {
Person p1 = new Person("bbb", 20);
Person p2 = new Person("aaa", 18);
Person p3 = new Person("bbb", 16);
List<Person> list = new ArrayList<Person>();
list.add(p1);
list.add(p2);
list.add(p3);
//排序
Collections.sort(list);
//输出
Log.d(TAG, "-----------使用Comparable实现的排序-----------");
for(Person item : list) {
Log.d(TAG, "name = "+item.name+", age = "+item.age);
}
}
检查输出结果是否正确:
02-03 12:05:31.356: D/wxx(9936): -----------使用Comparable实现的排序-----------
02-03 12:05:31.356: D/wxx(9936): name = aaa, age = 18
02-03 12:05:31.356: D/wxx(9936): name = bbb, age = 16
02-03 12:05:31.356: D/wxx(9936): name = bbb, age = 20
四、Comparator实现排序
Comparator实现比较器,是定义在Person类的外部的,因此实体类Person不需要做任何变化,如下:
public class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
我们的比较器My Comparator的实现,主要是覆盖compare方法,在这个方法内实现比较的规则,具体代码:
public class MyComparator implements Comparator<Person> {
public int compare(Person one, Person two) {
int i = one.name.compareTo(two.name); //比较名字字符串
if (i == 0) { //如果名字一样,则继续比较年龄
return one.age - two.age;
} else { //首先比较名字,名字不一样,则返回比较结果
return i;
}
}
}
上面的排序规则是:先比较name值进行排序,如果name值一样 ,再比较age值排序。
最后,当然是用我们的比较器对List<Person>进行排序:
private void sortByComparator() {
Person p1 = new Person("bbb", 20);
Person p2 = new Person("aaa", 18);
Person p3 = new Person("bbb", 16);
List<Person> list = new ArrayList<Person>();
list.add(p1);
list.add(p2);
list.add(p3);
//排序
Collections.sort(list, new MyComparator());
//输出
Log.d(TAG, "-----------使用Comparator实现的排序-----------");
for(Person item : list) {
Log.d(TAG, "name = "+item.name+", age = "+item.age);
}
}
查看排序后的输出结果是否正确:
02-03 11:51:34.996: D/wxx(1355): -----------使用Comparator实现的排序-----------
02-03 11:51:34.996: D/wxx(1355): name = aaa, age = 18
02-03 11:51:35.001: D/wxx(1355): name = bbb, age = 16
02-03 11:51:35.001: D/wxx(1355): name = bbb, age = 20
五、Comparable 与Comparator区别
上面已经分别实现了Comparable 与Comparator对List进行排序,他们有相似的地方,也有不同的地方:
1)Comparable 与Comparator都是java的接口,用来对自定义的实体对象进行比较;
2)Comparable 是定义在实体类内部的,所以实体类对象本身就有比较大小的可能。但如果想换一种比较规则,如先按年龄后按名字排序,那么就必须修改实体类Person本身;
3)Comparator是在实体类外部实现比较器的,所以对List排序时必须同时传入数据和比较器,如Collections.sort(list, new MyComparator());如果想换一种比较规则,则仅需要修改比较器MyComparator,而实体类Person则不需要改变;所以建议使用这种方法;
4)Comparable实现代码相对简单,Comparator实现代码相对复杂一点,但还是建议使用Comparator方法。
来源:https://blog.csdn.net/wxx614817/article/details/50628197


猜你喜欢
- 本文实例为大家分享了PopupWindow+RecyclerView实现上下滑动框功能的具体代码,供大家参考,具体内容如下1.新建一个适配器
- 原生Toast样式自定义Toast样式创建样式所谓自定义一个Toast就是建立一个布局文件,然后使用一个view容器承载,然后显示出来。To
- 因为案例比较简单,所以简单用AndroidApplication -> Game -> Stage 搭建框架 一、主入口,无特殊
- Spring中提供了很多PostProcessor供开发者进行拓展,例如:BeanPostProcessor、BeanFactoryPost
- 一、什么是相对布局相对布局是另外一种控件摆放的方式相对布局是通过指定当前控件与兄弟控件或者父控件之间的相对位置,从而达到相对的位置二、为什么
- 本文实例讲述了C#实现读取DataSet数据并显示在ListView控件中的方法。分享给大家供大家参考。具体如下:/*lvStudentLi
- 简单的说下实现来电秀的大概原理流程:首先通过监听来电状态,通过拦截来电然后在窗口弹出一层系统级别的弹窗,这层弹窗即是来电秀。先来两张效果图:
- 一个项目可能会有不同的环境,例如dev/stating/prod等,不同的环境的配置文件是不同的,如何根据环境快速的切换到对应的配置文件很重
- 前言本文介绍的是Android如何实现数字跳动效果的TextView,主要运用了DancingNumberView,DancingNumbe
- 前言Android模拟用户点击。在自动化测试中可使用的工具。可以利用adb命令,也可以使用Android SDK中的monkeyrunner
- 前言可能对于很多新人来讲,看到这个题目,想到的能接收输入法输入的内容大概只有EditText和TextView这两个控件了,其实不然,只要是
- 微信开放平台 : https://open.weixin.qq.com/一、准备工作 : 1. Android Studio环境下:在bui
- 反射方式获取JPA Entity属性和值在记录日志或者调试的时候,往往需要输出数据库查询或者写入的值,或者在接 * 互的时候,可能需要将实体转
- 场景描述在项目开发的过程中,需要修改调试的时候偶每次都需要重启项目浪费时间,下面是我整理的两种常用的两种方式方式一修改启动配置方式(主要针对
- 前言大家都知道,不少仪器工作站可xls文件和2007+的xl以将数据导出为Excel文件,包括97-2003版本的sx文件。采集Excel文
- 需求:假设我们的APP有3个页面AActivity,BActivity,CActivity,我们的APP需要一直运行在前台(特殊设备),要求
- 1、synchronized的作用为了避免临界区的竞态条件发生,有多种手段可以达到目的。阻塞式的解决方案:synchronized,Lock
- 中文乱码问题真的是一个很棘手的问题,特别是从前台传到后台之后,都不知道问题出在哪里了。现在分享解决javaWEB中前后台中文乱码问题的3种方
- 本文实例讲述了C#多线程学习之操纵一个线程的方法。分享给大家供大家参考。具体实现方法如下:下面我们就动手来创建一个线程,使用Thread类创
- properties和yml的区别这几天刚好看到Spring Boot当中有两种配置文件的方式,但是这两种配置方式有什么区别呢?proper