List集合排序Comparable与Comparator实现

时光总嘲笑我的痴心妄想 提交于 2019-12-07 16:55:49

List集合排序Comparable与Comparator实现

前言

Comparable和 Comparator有什么区别?相信很多同学在面试过程中会经常遇到这个问题。今天我们就结合实际应用来分析这两个对象的区别。

需求

我们的集合里存放了一批砖石王老五的资料,我们需要对这个集合进行排序,排序的规则就按照年少多金来进行排序。什么是年少多金?也就是说我们先比较年龄,年龄小的排在前面,年龄大的排在后面,年龄相同的,千多的排在前面。

Comparable 实现

使用Comparable 排序的需要实现Comparable 接口中的compareTo方法,在User中我们先

@Data
public class User implements Comparable<User> {

    /**
     * 名字
     */
    private String name;
    /**
     * 年龄
     */
    private int age;
    /**
     * 金钱
     */
    private int money;
    public User(){}
    public User(String name,int age,int money){
        this.name=name;
        this.age=age;
        this.money=money;
    }
    @Override
    public int compareTo(User user) {
    	//先根据用户年龄升序排序
        int tmp=this.getAge()-user.getAge();
        if(tmp==0){
        //如果年纪相等,那么在比较钱多钱少,
            return user.getMoney()-this.getMoney();
        }
        return tmp;
    }
}

  public static void main(String[] args){
        List<User> list=new ArrayList<>();
        list.add(new User("Aom",38,999999));
        list.add(new User("Bom",28,999999));
        list.add(new User("Com",18,999999));
        list.add(new User("Dom",38,888888));
        list.add(new User("Gom",20,666666));
        list.add(new User("Eom",28,888888));
        list.add(new User("Fom",18,888888));
        System.out.println("排序前");
        list.forEach(x->System.out.println(x));
        Collections.sort(list);
        System.out.println("排序后");
        list.forEach(x->System.out.println(x));
    }

执行main方法输出结果如下所示,集合输出的结果是按照年少多金排序的。可见通过Comparable 实现是可实现我们的排序需求的。

排序前
User(name=Aom, age=38, money=999999)
User(name=Bom, age=28, money=999999)
User(name=Com, age=18, money=999999)
User(name=Dom, age=38, money=888888)
User(name=Gom, age=20, money=666666)
User(name=Eom, age=28, money=888888)
User(name=Fom, age=18, money=888888)
排序后
User(name=Com, age=18, money=999999)
User(name=Fom, age=18, money=888888)
User(name=Gom, age=20, money=666666)
User(name=Bom, age=28, money=999999)
User(name=Eom, age=28, money=888888)
User(name=Aom, age=38, money=999999)
User(name=Dom, age=38, money=888888)

Comparator 实现

Comparator 实现方式则不需要对比较的对象进行修改,经排序的逻辑放在外层。

@Data
public class User {

    /**
     * 名字
     */
    private String name;
    /**
     * 年龄
     */
    private int age;
    /**
     * 金钱
     */
    private int money;
    public User(){}
    public User(String name,int age,int money){
        this.name=name;
        this.age=age;
        this.money=money;
    }
}

排序方法实现

  public static void main(String[] args){
        List<User> list=new ArrayList<>();
        list.add(new User("Aom",38,999999));
        list.add(new User("Bom",28,999999));
        list.add(new User("Com",18,999999));
        list.add(new User("Dom",38,888888));
        list.add(new User("Gom",20,666666));
        list.add(new User("Eom",28,888888));
        list.add(new User("Fom",18,888888));
        System.out.println("排序前");
        list.forEach(x->System.out.println(x));
        Collections.sort(list, new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                int tmp=o1.getAge()-o2.getAge();
                if(tmp==0){
                    return o2.getMoney()-o1.getMoney();
                }
                return tmp;
            }
        });
        System.out.println("排序后");
        list.forEach(x->System.out.println(x));
    }

执行main方法运行结果如下,也同样实现了我们的需求。

排序前
User(name=Aom, age=38, money=999999)
User(name=Bom, age=28, money=999999)
User(name=Com, age=18, money=999999)
User(name=Dom, age=38, money=888888)
User(name=Gom, age=20, money=666666)
User(name=Eom, age=28, money=888888)
User(name=Fom, age=18, money=888888)
排序后
User(name=Com, age=18, money=999999)
User(name=Fom, age=18, money=888888)
User(name=Gom, age=20, money=666666)
User(name=Bom, age=28, money=999999)
User(name=Eom, age=28, money=888888)
User(name=Aom, age=38, money=999999)
User(name=Dom, age=38, money=888888)

总结

  1. Comparable 排序需要在实体中信息接口中的compareTo,这种方式耦合性较高,当需求变更时需要改动的地方较多,比如需求突然变成先按照金额排序,在排序年龄时,我们就需要重写实体的代码,但是实体的代码在其它地方有引用的情况,那么这个坑就有点大了。
  2. Comparator排序方式将排序逻辑放在外层,我们可以根据实质情况临时调整排序逻辑而不影响实体的结构。从这一点来说个人建议使用Comparator方式进行集合排序。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!