Collections.sort(List list)与Collections.sort(List list,Comparator c)用法

1. 基本类型比较

 package compare;
 ​
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 ​
 /**
  * 基础类型比较
  */
 public class CollectionsTest1 {
     public static void main(String[] args) {
         List<String> strList = new ArrayList<>();
         strList.add("15");
         strList.add("12");
         strList.add("18");
         // 字符串排序
         Collections.sort(strList);
         System.out.println("*******字符串排序********");
         strList.forEach(System.out::println);
         System.out.println("*************集合元素“逆向输出(反转)”而非“逆向排序”***********");
         Collections.reverse(strList);
         strList.forEach(System.out::println);
 ​
         List<Integer> intList = new ArrayList<>();
         intList.add(15);
         intList.add(12);
         intList.add(18);
         // 整型排序
         Collections.sort(intList);// 升序排列
         System.out.println("*************整数类型排序***********");
         intList.forEach(System.out::println);
         System.out.println("*************集合元素“逆向输出(反转)”而非“逆向排序”***********");
         Collections.reverse(intList);
         intList.forEach(System.out::println);
 ​
         /**
          * 为什么基础类型的集合,可以直接调用sort排序,而不需要重新 实现 Comparable 接口类?
          * 查看底层源码可知:
          *    Sorts the specified list into ascending order, according to the natural ordering of its elements.
          *    All elements in the list must implement the Comparable interface. Furthermore, all elements in the
          *    list must be mutually comparable (that is, e1.compareTo(e2) must not throw a ClassCastException for
          *    any elements e1 and e2 in the list).
          * 调用该sort()方法的前提条件时,该集合list的类型T必须实现Comparable才行,
          * 但是基础类型默认都实现了Comparable接口,所以可以直接使用sort方法:
          *    1.public final class Integer extends Number implements Comparable<Integer>
          *    2.public final class Double extends Number implements Comparable<Double>
          *    3.public final class Long extends Number implements Comparable<Long>
          *    ......
          * 而String也实现了Comparable接口:
          *    public final class String implements java.io.Serializable, Comparable<String>, CharSequence
          * 所以都可以直接调用sort方法。
          *
          * 而对于对象而言,其不是基础类型,需要使用Collections.sort()方法时对象需要实现Comparable接口,然后重写compareTo()方法,在方法体中自定义比较规则。
          *
          * 参考链接:
          *    https://www.cnblogs.com/darkings/p/16414530.html
          *    https://blog.csdn.net/u012062455/article/details/78087314
          *
          * 补充:
          *    reverse的意思是反转,而不是降序,只是将原来集合的元素顺序反转一下输出,反转并不意味着降序了,要真正的实现降序,可以先对集合进行升序,然后进行反转,就可以实现降序了。
          */
     }
 }

输出结果:

 *******字符串排序********
 12
 15
 18
 *************集合元素“逆向输出(反转)”而非“逆向排序”***********
 18
 15
 12
 *************整数类型排序***********
 12
 15
 18
 *************集合元素“逆向输出(反转)”而非“逆向排序”***********
 18
 15
 12

2. 对象类型比较

2.1 list.stream().sorted()

参考链接:JAVA集合多字段排序方法 - 未月廿三 - 博客园

 List<类> list; 代表某集合
  
 //返回 对象集合以类属性一升序排序
 list.stream().sorted(Comparator.comparing(类::属性一));
 ​
 //返回 对象集合以类属性一降序排序 注意两种写法
 list.stream().sorted(Comparator.comparing(类::属性一).reversed());//先以属性一升序,对升序结果进行属性一降序
 list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()));//以属性一降序
 ​
 //返回 对象集合以类属性一升序 属性二升序
 list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二));
 ​
 //返回 对象集合以类属性一降序 属性二升序 注意两种写法
 list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二));//先以属性一升序,对升序结果进行属性一降序,再进行属性二升序
 list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二));//先以属性一降序,再进行属性二升序
 ​
 //返回 对象集合以类属性一降序 属性二降序 注意两种写法
 list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一升序,对升序结果进行属性一降序,再进行属性二降序
 list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一降序,再进行属性二降序
 ​
 //返回 对象集合以类属性一升序 属性二降序 注意两种写法
 list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二).reversed());//先以属性一升序,对升序结果进行属性一降序,再进行属性二升序,对前面结果进行属性一降序属性二降序(优先按照属性一降序,属性一相等时再按照属性二降序)
 list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一升序,再进行属性二降序

通过以上例子我们可以发现:

  1. Comparator.comparing(类::属性一).reversed();

  2. Comparator.comparing(类::属性一,Comparator.reverseOrder());

两种排序是完全不一样的,一定要区分开来:

1、是得到排序结果后再排序,

2、是直接进行排序,很多人会混淆导致理解出错,2更好理解,建议使用2

  • Img类

 package compare;
 ​
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateField;
 import cn.hutool.core.date.DateUtil;
 import lombok.Data;
 import lombok.ToString;
 ​
 import java.util.Comparator;
 import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
 ​
 @Data
 @ToString
 public class Img {
     private Integer id;
     private Integer sort;
     private Date createTime;
 ​
     public static void main(String[] args) {
         List<Img> list = CollUtil.newArrayList();
         for (int i = 1; i <= 3; i++) {
             Img img = new Img();
             img.setId(i);
             img.setSort(i != 1 ? 2 : 1);
             img.setCreateTime(i == 1 ? DateUtil.offset(new Date(), DateField.MINUTE, 3) : i == 2 ? DateUtil.offset(new Date(), DateField.MINUTE, 1) : DateUtil.offset(new Date(), DateField.MINUTE, 2));
             list.add(img);
         }
         System.out.println("现有集合:");
         list.stream().forEach(item -> System.out.println(item));
 ​
         System.out.println("使用reversed()排序:");
         List<Img> imgList = list.stream().sorted(Comparator.comparing(Img::getSort).thenComparing(Img::getCreateTime).reversed()).collect(Collectors.toList());
         imgList.stream().forEach(item -> System.out.println(item));
 ​
         System.out.println("使用Comparator.reverseOrder()排序:");
         List<Img> imgs = list.stream().sorted(Comparator.comparing(Img::getSort).thenComparing(Img::getCreateTime, Comparator.reverseOrder())).collect(Collectors.toList());
         imgs.stream().forEach(item -> System.out.println(item));
     }
 }

输出结果:

 现有集合:
 Img(id=1, sort=1, createTime=2022-09-22 20:52:42)
 Img(id=2, sort=2, createTime=2022-09-22 20:50:42)
 Img(id=3, sort=2, createTime=2022-09-22 20:51:42)
 使用reversed()排序:
 Img(id=3, sort=2, createTime=2022-09-22 20:51:42)
 Img(id=2, sort=2, createTime=2022-09-22 20:50:42)
 Img(id=1, sort=1, createTime=2022-09-22 20:52:42)
 使用Comparator.reverseOrder()排序:
 Img(id=1, sort=1, createTime=2022-09-22 20:52:42)
 Img(id=3, sort=2, createTime=2022-09-22 20:51:42)
 Img(id=2, sort=2, createTime=2022-09-22 20:50:42)

2.2 Collections.sort()

 @Override
 public int compareTo(Object o) {
     return 0;
 }

方法原理:利用当前对象和传入的目标对象进行比较,通过返回值,决定顺序。

(1)当返回值是 “-1”,代表从大到小排序;

(2)当返回值是 “1”,代表从小到大排序;

(3)当返回值是 “0”,两对象相等;

  • User

 package compare;
 ​
 import lombok.*;
 import lombok.experimental.Accessors;
 ​
 @Data
 @Getter
 @Setter
 @NoArgsConstructor
 @AllArgsConstructor
 @ToString
 @Accessors(chain = true)
 public class User implements Comparable{
 ​
     private String name;
     private Integer age;
 ​
     @Override
     public int compareTo(Object o) {
         // 1.单条件比较
 //        if(o instanceof User){
 //            User user = (User)o;
 //            return this.name.compareTo(user.getName());// 按照name升序排列
 //
             return this.age.compareTo(user.getAge());// 按照age升序排列
             return this.age - user.getAge();// 按照age升序排列
 //        }
 //
         // 2.多条件比较
         if(o instanceof User){
             User user = (User)o;
             if(this.age>user.getAge()){
                 return 1;
             }else if(this.age<user.getAge()){
                 return -1;
             }else{
                 return this.name.compareTo(user.getName());
             }
         }
         throw new ClassCastException("类型转换异常");
     }
 }
  • 测试

 package compare;
 ​
 import java.util.*;
 ​
 /**
  * 对象类型比较:根据对象的某些属性来排序
  */
 public class CollectionsTest2 {
     public static void main(String[] args) {
         /**
          * 参考链接:
          *    https://blog.csdn.net/qq_43842093/article/details/122934159
          *    https://blog.csdn.net/glenshappy/article/details/125320532
          * java集合的工具类Collections中提供了两种排序的方法,分别是:
          * 1.Collections.sort(List list):自然排序
          *    要求参与排序的对象(包含基本属性、getter/setter方法、有参/无参构造方法、toString方法)实现Comparable接口,并重写其中的compareTo()方法,方法体中定义对象的大小比较原则
          *
          * 2.Collections.sort(List list,Comparator c)
          *    也叫定制排序/自定义排序,需编写匿名内部类,先new一个Comparator接口的比较器对象c,同时实现compare()其方法;
          * 然后将比较器对象c传给Collections.sort()方法的参数列表中,实现排序功能。
          *
          *    第二种方法说明第一种方法不够灵活,实体类实现了comparable接口后,会增加耦合,
          * 如果在项目中不同的位置需要根据不同的属性调用排序方法时,需要反复修改比较规则(按name还是按age),二者只能选择其一,会起冲突,
          * 第二种方法就很好地解决了这个问题,在需要的地方创建个内部类的实例,重写其比较方法即可。
          *
          *
          */
         List<User> userList = new ArrayList<>();
         userList.add(new User("tom",18));
         userList.add(new User("jack",20));
         userList.add(new User("rose",15));
         userList.add(new User("jerry",17));
         userList.add(new User("liming",17));
         userList.add(new User("rose",19));
         System.out.println("------------排序前:-----------");
         userList.forEach(System.out::println);
 ​
         List<User> userList1 = userList;
         List<User> userList2 = userList;
         List<User> userList3= userList;
         List<User> userList4= userList;
         List<User> userList5= userList;
 ​
         // 1.测试Collections.sort(List list)按照自然规则排序:单一规则
         Collections.sort(userList);// 更换name或age比较规则时需要在重写的compareTo()方法中修改方法体,只能定义单一比较规则
         System.out.println("------------Collections.sort(List list)排序后:--------------");
         userList.forEach(System.out::println);
 ​
         System.out.println("------------使用迭代器对实现Comparable接口对象集合进行输出,效果与Collections.sort(List list)一致-------------------");
         Iterator<User> iterator = userList3.iterator();
         while (iterator.hasNext()){
             User next = iterator.next();
             System.out.println(next);
         }
 ​
 ​
         // 2.1 测试Collections.sort(List list,Comparator c)按age自定义排序:单一规则
 //        Collections.sort(userList1, new Comparator<User>() {
 //            @Override
 //            public int compare(User o1, User o2) {
 //                return o1.getAge() - o2.getAge();
 //            }
 //        });
         // 简化
         Collections.sort(userList1, (o1,o2)-> o1.getAge() - o2.getAge());// o1.getAge() - o2.getAge():升序排列,o2.getAge() - o1.getAge():降序排列
         System.out.println("-------------Collections.sort(List list)按age升序排列后:-----------------");
         userList1.forEach(System.out::println);
 ​
         // 2.2 测试Collections.sort(List list,Comparator c)按name自定义排序:单一规则
         Collections.sort(userList2, (e1,e2)->e1.getName().compareTo(e2.getName()));// e1.getName().compareTo(e2.getName()):升序排列,e1.getName().compareTo(e2.getName()):降序排列
         System.out.println("-------------Collections.sort(List list)按name升序排列后:-----------------");
         userList2.forEach(System.out::println);
 ​
         // 2.3 测试Collections.sort(List list,Comparator c)按name自定义排序:多规则
         Collections.sort(userList4,((Comparator<User>)(o1, o2) -> {
             return o1.getAge() - o2.getAge();// 升序
         }).thenComparing((o1, o2) -> {
             return o1.getName().compareTo(o2.getName());// 升序
         }));
         System.out.println("-------------Collections.sort(List list)先按age升序再按name升序排列后:-----------------");
         userList4.forEach(System.out::println);
 ​
         // 2.4  测试Collections.sort(List list,Comparator c)按name自定义排序:多规则
         Collections.sort(userList5, new Comparator<User>() {
             @Override
             public int compare(User o1, User o2) {
                 if(o1.getAge()>o2.getAge()){
                     return 1;
                 }else if(o1.getAge()<o2.getAge()){
                     return -1;
                 }else{
                     return o1.getName().compareTo(o2.getName());
                 }
             }
         });
         System.out.println("-------------Collections.sort(List list)先按age升序再按name升序排列后:-----------------");
         userList5.forEach(System.out::println);
     }
 }

输出结果:

 ------------排序前:-----------
 User(name=tom, age=18)
 User(name=jack, age=20)
 User(name=rose, age=15)
 User(name=jerry, age=17)
 User(name=liming, age=17)
 User(name=rose, age=19)
 ------------Collections.sort(List list)排序后:--------------
 User(name=rose, age=15)
 User(name=jerry, age=17)
 User(name=liming, age=17)
 User(name=tom, age=18)
 User(name=rose, age=19)
 User(name=jack, age=20)
 ------------使用迭代器对实现Comparable接口对象集合进行输出,效果与Collections.sort(List list)一致-------------------
 User(name=rose, age=15)
 User(name=jerry, age=17)
 User(name=liming, age=17)
 User(name=tom, age=18)
 User(name=rose, age=19)
 User(name=jack, age=20)
 -------------Collections.sort(List list)按age升序排列后:-----------------
 User(name=rose, age=15)
 User(name=jerry, age=17)
 User(name=liming, age=17)
 User(name=tom, age=18)
 User(name=rose, age=19)
 User(name=jack, age=20)
 -------------Collections.sort(List list)按name升序排列后:-----------------
 User(name=jack, age=20)
 User(name=jerry, age=17)
 User(name=liming, age=17)
 User(name=rose, age=15)
 User(name=rose, age=19)
 User(name=tom, age=18)
 -------------Collections.sort(List list)先按age升序再按name升序排列后:-----------------
 User(name=rose, age=15)
 User(name=jerry, age=17)
 User(name=liming, age=17)
 User(name=tom, age=18)
 User(name=rose, age=19)
 User(name=jack, age=20)
 -------------Collections.sort(List list)先按age升序再按name升序排列后:-----------------
 User(name=rose, age=15)
 User(name=jerry, age=17)
 User(name=liming, age=17)
 User(name=tom, age=18)
 User(name=rose, age=19)
 User(name=jack, age=20)

参考链接:每天记录学习的知识:Comparable 多条件比较器_清风徐来辽的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值