• OpenJDK源码研究笔记(二)-Comparable和Comparator2个接口的作用和区别(一道经典的Java笔试面试题)


    Comparable和Comparator是JDK中定义的2个比较接口,很相似,但又有所不同。

    这2个接口的作用和区别也是Java中的常见经典面试题。

    下面我们就来详细介绍下这2个接口的定义、作用、区别、模式、应用场景和代码案例。

    定义

    public interface Comparable<T> {
       public int compareTo(T o);
    }
    public interface Comparator<T> {
       int compare(T o1, T o2);
       boolean equals(Object obj);
    }
    
    


    作用

    用来实现集合中元素的比较和排序。

    区别

    Comparable强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。

    实现此接口的对象列表(和数组)可以通过 Collections.sort(和 Arrays.sort)进行自动排序。实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。

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

    可以说一个是自已完成比较,一个是外部程序实现比较的差别而已。

    模式

    用 Comparator 是策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。

    Comparator可以看成一种算法的实现,将算法和数据分离。

    应用场景

    Comparator也可以在下面两种环境下使用:
    1、类的设计师没有考虑到比较问题而没有实现Comparable,可以通过Comparator来实现排序而不必改变对象本身。
    2、可以使用多种排序标准,比如员工按照员工号、年龄、名字 升序或降序排序等。

    代码案例

    //员工
    public class Employee implements Comparable<Employee> {
        // 员工号
        private int no;
        // 员工的年龄
        private int age;
        // 员工的姓名
        private String name;
    
        public Employee() {
            super();
        }
    
        public Employee(int no, int age, String name) {
            super();
            this.no = no;
            this.age = age;
            this.name = name;
        }
    
        public int getNo() {
            return no;
        }
    
        public void setNo(int no) {
            this.no = no;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        // 自然排序按照员工号的顺序
        public int compareTo(Employee obj) {
            Employee employee = (Employee) obj;
            return this.no - employee.no;
        }
    
        @Override
        public String toString() {
            return "Employee [no=" + no + ", age=" + age + ", name=" + name + "]";
        }
    
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + no;
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Employee other = (Employee) obj;
            if (no != other.no)
                return false;
            return true;
        }
    
    }
    
    


     

    /**
     *
     * 按照员工的年龄进行比较的比较器。
     */
    public class AgeComparator implements Comparator<Employee> {
    
        @Override
        public int compare(Employee o1, Employee o2) {
            return o1.getAge()-o2.getAge();
        }
    
    }
    
    


     

    /**
     *
     *按照员工的名字进行比较的比较器
     *
     */
    public class NameComparator implements Comparator<Employee> {
    
        @Override
        public int compare(Employee o1, Employee o2) {
            return o1.getName().compareTo(o2.getName());
        }
    
    }
    
    


     

    public class EmployeeTest {
    
        public static void main(String[] args) {
            Employee employee1 = new Employee(169, 24, "LeiWen");
            Employee employee2 = new Employee(152, 27, "FansUnion");
    
            List<Employee> employeeList = new ArrayList<Employee>();
            employeeList.add(employee1);
            employeeList.add(employee2);
    
            // 原始排序
            println("原始排序");
            println(employeeList);
            
            // 自然排序,默认排序
            println("默认no升序排序");
            Collections.sort(employeeList);
            println(employeeList);
            
            // 按名字排序
            println("自定义name升序排序");
            Collections.sort(employeeList,new NameComparator());
            println(employeeList);
            
            
            // 按年龄排序
            println("自定义age升序排序");
            Collections.sort(employeeList,new AgeComparator());
            println(employeeList);
        }
    
        private static void println(String str){
            System.out.println(str);
        }
        private static void println(List<Employee> employeeList) {
            System.out.println(employeeList);
        }
    }
    
    


    运行结果

    原始排序
    [Employee [no=169, age=24, name=LeiWen], Employee [no=152, age=27, name=FansUnion]]
    默认no升序排序
    [Employee [no=152, age=27, name=FansUnion], Employee [no=169, age=24, name=LeiWen]]
    自定义name升序排序
    [Employee [no=152, age=27, name=FansUnion], Employee [no=169, age=24, name=LeiWen]]
    自定义age升序排序
    [Employee [no=169, age=24, name=LeiWen], Employee [no=152, age=27, name=FansUnion]]


    参考资料

    http://www.iteye.com/problems/3025

    http://ctzlylc.blog.163.com/blog/static/61967136201165981283/

    JDK API中文参考手册

    OpenJDK源码

    相关阅读

    OpenJDK源码研究笔记(一)-参数检查&抛出带关键错误提示信息的异常

    原文参见:http://FansUnion.cn/articles/2808 小雷网(FansUnion.cn)


  • 相关阅读:
    纯CSS气泡对话框
    使用JAVASCRIPT实现的 单行文字 逐个文字变色,可以循环控制
    数字转换成中文汉字
    jquery如何在对表格添加删除后再对其前面加上顺序的序列号
    情路
    【缅怀妈妈系列诗歌】之二十四:一份永不忘却的思念
    我等你,千年之后
    赢道在手,前程无忧
    为你感动
    你为什么对我如此冷漠
  • 原文地址:https://www.cnblogs.com/qitian1/p/6463537.html
Copyright © 2020-2023  润新知