在应用Collections工具类的sort方法时,一般有两种使用方式:

//将集合中元素按照默认规则排序。
public static <T> void sort(List<T> list)
//将集合中元素按照指定规则排序。
public static <T> void sort(List<T> list,Comparator<? super T> )

第一种方法:

直接把待排序集合作为参数传入Collections.sort(),默认规则是升序排列,比如:

ArrayList<Integer> list=new ArrayList<>();
Collections.addAll(list,3,7,2,4,1);//list=[3,7,2,4,1]
Collections.sort(list);//排序结果是list=[1,2,3,4,7]

当然,ArrayList也可以存储对象类型的数据,那么如何将对象类型的数据按我们想要的规则进行排序呢?这时候就需要让我们的自定义的类实现Comparabler接口,并且重写Comparabler接口中的compareTo方法:

//测试类,用于测试排序效果
public class DemoSort {public static void main(String[] args) {ArrayList<Person> list = new ArrayList<>();list.add(new Person("张三",18));list.add(new Person("李四",20));list.add(new Person("王五",15));System.out.println(list);//[Person{name='张三', age=18}, Person{name='李四', age=20}, Person{name='王五', age=15}]Collections.sort(list);System.out.println(list);}
}
//自定义的Person类,最下面重写了Comparabler接口中的compareTo方法
public class Person implements Comparable<Person>{private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}//重写排序的规则@Overridepublic int compareTo(Person o) {//自定义比较的规则,比较两个人的年龄(this,参数Person)return this.getAge() - o.getAge();//年龄升序排序//return o.getAge() - this.getAge();//年龄降序排序}
}

上面的例子中定义了一个Person类,有名字和年龄两个成员变量,当有多个Person对象时,我们想让年龄大的排在list后面(也就是按年龄升序排列),就需要在Person类中重写compareTo方法。

传入参数就是Preson类型的对象o,在代码中,当前的人用this指代(当前对象),要比较的后一个人就是传进来的参数,用o指代;

这里面的compareTo方法只是sort排序中的很少一部分代码,它的作用只是提供一个i的返回值,这个返回值如果是正数,在sort其它部分的代码中会转换为1;如果是负数,会转换为-1;如果参与比较的两个数相等,会返回0;

  • 返回值为负数(后面会转换为-1):在sort其他的代码段中,将不会对参与比较的两个对象对调次序;
  • 返回值为正数(后面会转换为1):在sort其他的代码段中,将会对参与比较的两个对象对调次序

所以,在前面的代码中,compareTo返回的如果是this.getAge() - o.getAge();,也就是表示当前人的年龄(当前对象)减去后一个人的年龄(传入对象0):

  • 如果返回正数,就要将当前人和后一个人调换次序,而返回正数说明当前这个人的年龄更大。这样效果就是年龄大的人会排在后面,实现的是升序的逻辑;
  • 如果返回负数,就不调换次序,而返回负数说明后面这个人的年龄更大。这样效果就是年龄大的人会排在后面,实现的还是升序的逻辑;

运行测试代码,运行结果是按年龄升序排类:

[Person{name='王五', age=15}, Person{name='张三', age=18}, Person{name='李四', age=20}]

这种时候,如果把上面代码中Person类的compareTo方法的返回值改成o.getAge() - this.getAge(),同样适用前面的规则:

  • 如果返回正数,就要将当前人和后一个人调换次序,而返回正数说明后面这个人的年龄更大。这样效果就是年龄大的人会排在后面,实现的是降序的逻辑;
  • 如果返回负数,就不调换次序,而返回负数说明当前这个人的年龄更大。这样效果就是年龄大的人会排在后面,实现的还是降序的逻辑;

测试运行结果是按年龄降序排列:

[Person{name='李四', age=20}, Person{name='张三', age=18}, Person{name='王五', age=15}]

第二种方法

第二种方法作为参数的不仅有集合,还有一个Comparator比较器,它是一个接口,它的一般使用和Comparable接口的使用不一样,可以在本类中直接使用匿名类自定义排序规则。

举例:

这里使用学生类,有姓名和年龄两个变量,类里面重写了toString方法方便测试代码,有普通的get和set方法:

public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

下面在测试类中给学生类进行自定义排序:

public class Demo03Sort {public static void main(String[] args) {//list01为普通Integer类型的集合ArrayList<Integer> list01 = new ArrayList<>();list01.add(1);list01.add(3);list01.add(2);System.out.println(list01);//[1, 3, 2]Collections.sort(list01, new Comparator<Integer>() {//重写比较的规则@Overridepublic int compare(Integer o1, Integer o2) {//return o1-o2;//升序return o2-o1;//降序}});System.out.println(list01);ArrayList<Student> list02 = new ArrayList<>();list02.add(new Student("张三",18));list02.add(new Student("李四",20));list02.add(new Student("王五",17));list02.add(new Student("赵七",18));System.out.println(list02);//按照年龄升序排序Collections.sort(list02, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return o1.getAge()-o2.getAge();//升序规则}});System.out.println(list02);}
}

输出结果为:

[1, 3, 2]
[3, 2, 1]
[Student{name='张三', age=18}, Student{name='李四', age=20}, Student{name='王五', age=17}, Student{name='赵七', age=18}]
[Student{name='王五', age=17}, Student{name='张三', age=18}, Student{name='赵七', age=18}, Student{name='李四', age=20}]

可以看出当重写的compare返回值是o1-o2时,是按升序排列,当return的是o2-o1时,排序按降序。

这里compare的规则和前面第一种方法里的compareTo方法类似,也是当返回值是正数是,会被转成1,表示需要调换o1和o2的次序。当返回o1-o2时,如果返回正数,就需要调换o1和o2的次序,同时返回正数表示o1>o2,也就是要把更大的o1换到后面去,所以是升序的规则;返回负数时,不调换次序,同时负数表示o1<o2,也就是让本来更大的o2保持在后面。

当返回o2-o1的时候,道理是一样的,是降序的规则。

当然,Comparator还有另外一种使用方法:

list.sort(new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return o1.getAge() - o2.getAge();}
});

直接通过list的sort方法调用,重写compare方法的规则和前面提到的是一样的

Comparable和Comparator两个接口的区别

Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次,不能经常修改类的代码实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序,对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。

Comparator强行对某个对象进行整体排序。可以将Comparator 传递给sort方法(如Collections.sort或 Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。

Java中Colletcions.sort方法详解以及Comparable和Comparator两个接口的区别相关推荐

  1. Java中的main()方法详解

    源文作者:leizhimin    源文链接:http://lavasoft.blog.51cto.com/62575/53263 源文作者版权申明: 版权声明:原创作品,允许转载,转载时请务必以超链 ...

  2. java中Collections.sort排序详解

    Comparator是个接口,可重写compare()及equals()这两个方法,用于比价功能:如果是null的话,就是使用元素的默认顺序,如a,b,c,d,e,f,g,就是a,b,c,d,e,f, ...

  3. java perl5compiler,Java中正则表达式使用方法详解(四)

    3.2 HTML处理实例一 下面一个任务是分析HTML页面内FONT标记的所有属性.HTML页面内典型的FONT标记如下所示 程序将按照如下形式,输出每一个FONT标记的属性 在这种情况下,我建议你使 ...

  4. Java中Collections.sort()排序详解

    https://www.cnblogs.com/learnapi/p/9003112.html

  5. java中main是什么_Java中的main()方法详解

    在Java中,main()方法是Java应用程序的入口方法,也就是说,程序在运行的时候,第一个执行的方法就是main()方法,这个方法和其他的方法有很大的不同,比如方法的名字必须是main,方法必须是 ...

  6. java多线程中的join方法详解

    java多线程中的join方法详解 方法Join是干啥用的? 简单回答,同步,如何同步? 怎么实现的? 下面将逐个回答. 自从接触Java多线程,一直对Join理解不了.JDK是这样说的:join p ...

  7. Java中的static关键字详解

    ** Java中的static关键字详解 ** 在一个类中定义一个方法为static,即静态的,那就是说无需本类的对象就可以调用此方法.调用一个静态方法就是 "类名.方法名" ,静 ...

  8. java中的进制输出转换_Java I/O : Java中的进制详解

    作者:李强强 上一篇,泥瓦匠基础地讲了下Java I/O : Bit Operation 位运算.这一讲,泥瓦匠带你走进Java中的进制详解. 一.引子 在Java世界里,99%的工作都是处理这高层. ...

  9. Java中的Runtime类详解

    Java中的Runtime类详解 1.类注释 /**Every Java application has a single instance of class Runtime that allows ...

最新文章

  1. 机器学习——大数据与MapReduce
  2. scrapy 怎么添加cookie_scrapy学习之爬虫练习平台5
  3. smarty安装与配置
  4. 设计一个成绩分类 输入成绩 输出优秀_BenQ 明基 PD2720U 27寸 Thunderbolt3.0 专业设计显示器开箱评测...
  5. nginx连接php-fpm sock文件失败502
  6. 自定义类模板 重载遇到的问题
  7. 织梦多个栏目arclist调用副栏目不显示的解决办法
  8. 工业发展 安全护航 2021年工业互联网安全发展峰会成功召开
  9. LeetCode——350. 两个数组的交集 II
  10. ModalPopupExtender控件主要有两种使用方式:客户端使用方式和服务器端使用方式
  11. java jdbc 批处理_Java JDBC批处理插入数据操作
  12. 三大公有云托管 Kubernetes 服务 (EKS、GKE、AKS) 评估
  13. java 微信开发图片发送,微信开发?Java上传Base64图片
  14. linux 安装tomcat
  15. sql注入检测工具之sqlmap
  16. cad2012打开后闪退_win10系统打开CAd2012出现闪退的恢复方法
  17. Spring Data JPA/Hibernate 运行期动态模型、动态实体建表、动态字段查询的方式
  18. linux扩展模式触摸屏,Ubuntu14.04下使用触摸屏以及笔记本扩展触摸屏设置方法
  19. oracle的date_add,SQL Server 中add函数到 oracle date add的操作
  20. java栈溢出漏洞cve,TP-Link WR841N 栈溢出漏洞(CVE-2020-8423)分析

热门文章

  1. 用Compose来搞个水墨画效果吧
  2. HTML中,图片放大与缩小
  3. 项目和程序的敏捷里程碑标准
  4. w10怎样关闭对计算机更改,w10电脑如何彻底关闭操作中心|w10关闭操作中的方法...
  5. 升降压斩波电路(电力电子技术)
  6. c语言漫函数,漫谈C指针:函数名其实也是指针
  7. linux 看硬盘运行时间长,Linux/CentOS下怎么查看硬盘使用时间
  8. 表格标签 ,待支付、未支付转换,可直接复制使用
  9. 重磅消息:Elastic 公司即将修改 ElasticSearch 的开源许可证,限制云服务商的使用...
  10. 对iphone5的期待背后