zoukankan      html  css  js  c++  java
  • Java Comparable 和 Comparator

    关于Comparable和Comparator

    这篇文章参考Java Sorting: Comparator vs Comparable TutorialJava排序: Comparator vs Comparable 入门做了一些个人总结。

    Comaprable

    一个实现了comparable接口的对象的实例可以被用于和相同对象的不同实例做对比。它本身必须实现java.lang.Comparable的接口,这样它就拥有了对比的能力。即实现了Comparable的对象具有对比的能力。

    Comparator

    一个Comparetor对象能够对比不同的对象,它比较的不是自身的对象——Comparator本身,而是对比其他类的对象。一个Comparator对象必须实现java.util.Comparator接口。

    如何使用

    在Java中有两个接口来支持这两个概念(Comparable和Comparator),这两个接口都有连个需要被实现的方法。分别是:
    * java.lang.Comparable: int comparaTo(Object o1)
    该方法将该对象(this)和o1进行对比,返回一个int型的值,意义如下(大小都是逻辑上的大小):
    1. positive – 该对象比o1大
    2. zero – 该对象和o1对象一样大
    3. negative – 该对象比o1对象小

    • java.util.Comparator: int compare(Object o1, Object o2)
      该方法将o1和o2进行比较,返回一个int型的值,意义如下(大小都是逻辑上的大小):

      1. positive – o1 的值比 o2大
      2. zero – o1 的值和 o2 一样大
      3. negative – o1 的值比 o2小
    • java.util.Collections.sort(List)java.util.Arrays.sort(Object [])这两个方法用把指定的list按照升序排列,这时list中的元素必须实现java.lang.Comparable接口.

    • java.util.Collections.sort(List,Comparator)java.util.Arrays.sort(Object[], Comparator)这两个方法在能够提供Comparator时对list进行排序。

    举个栗子

    考虑一个web页面需要显示职工的列表。通常情况下职工列表是按照职工的ID来排序。同样也可以根据姓名或者年龄来排序。
    我们默认的条件是员工的排序是按照职工的ID来进行排序的,下面的代码省略了各种import,不可直接粘贴代码运行

    class Employee implements Comparable<Employee> { // 职工的类
        private int id;
        private String name;
        private int age;
    
        public int compareTo(Employee e) {
            return this.getId() - e.getId();
        }
    
        public Employee(int id, String name, int age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }
    
        public int getId(){return this.id;}
        public String getName(){return this.name;}
        public int getAge(){return this.age;}
    }

    下面我们将使用一个工具类来构造一个Employees List

    class Util {
        public static List<Employee> getEmployee() {
            List<Employee> col = new ArrayList<Employee>();
            col.add(new Employee(5, "Frank", 28));
            col.add(new Employee(1, "Jorge", 19));
            col.add(new Employee(6, "Bill", 34));
            col.add(new Employee(3, "Michel", 10));
            col.add(new Employee(7, "Simpson", 8));
            col.add(new Employee(4, "Clerk", 16));
            col.add(new Employee(8, "Lee", 40));
            col.add(new Employee(2, "Mark", 30));
    
            return col;
        }
    }

    接下来是Main方法

    public class Main {
    
        public static void main(String[] args) {
            List<Employee> coll =Util.getEmployee();
            Collections.sort(coll);
            for(Employee e: coll){
                System.out.println(e.getId() + " " + e.getName() + " " + e.getAge());
            }
        }
    }
    

    输出结果将如下所示
    1 Jorge 19
    2 Mark 30
    3 Michel 10
    4 Clerk 16
    5 Frank 28
    6 Bill 34
    7 Simpson 8
    8 Lee 40

    根据其他字段排序

    如果我们要根据employee的其他字段进行排序,上面的例子我们就要修改Employee的compareTo的实现,这样必然会破坏我们按照id进行排序的机制。其实最好的方法就是将排序策略与模型分离开来,这是Comparator就派上用场了。
    下面的代码通过构建一个内部类将coll根据Employee的name升序排列。其实只需稍微修改Main方法。

    public class Main {
    
        public static void main(String[] args) {
            List<Employee> coll =Util.getEmployee();
    
            Comparator<Employee> cmp = new Comparator<Employee>() {
                @Override
                public int compare(Employee o1, Employee o2) {
                    return o1.getName().compareTo(o2.getName());
                }
            };
    
            Collections.sort(coll, cmp);
            for(Employee e: coll){
                System.out.println(e.getId() + " " + e.getName() + " " + e.getAge());
            }
        }
    }

    输出结果如下:
    6 Bill 34
    4 Clerk 16
    5 Frank 28
    1 Jorge 19
    8 Lee 40
    2 Mark 30
    3 Michel 10
    7 Simpson 8

    同样的可以按照这种方法对id进行重排序

    其实本人是比较喜欢Comparator因为它把排序机制和数据结构分离开来了,这样代码比较容易维护。

  • 相关阅读:
    [洛谷P1484] 种树
    Codeforces Round #505 Div. 1 + Div. 2
    [NOIp2015] 斗地主
    ☆ [NOIp2016] 天天爱跑步 「树上差分」
    [NOI2010] 超级钢琴
    [POI2000] 病毒
    [SCOI2010] 股票交易
    [NOI2002] 贪吃的九头龙
    [ZJOI2008] 骑士
    LeetCode 笔记系列 18 Maximal Rectangle [学以致用]
  • 原文地址:https://www.cnblogs.com/pluviophile/p/7460325.html
Copyright © 2011-2022 走看看