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

    对象排序

    例如我已经有如下的 Person 类,该类具有 name 和 age 2 个属性,现在我们需要对存放 Person 类的数组或集合进行排序。此时有很多的排序策略,例如对 age 按升序或降序排序,或堆 name 按字典序排序,也可以先按 age 进行排序后对 age 属性相同的对象按 name 的字典序排序。

    class Person{
    	private String name;
    	private int age;
    	
    	public PersonSortable(String name,int age){
    		this.name = name;
    		this.age = age;
    	}
    
    	@Override
    	public String toString() {
    		return name + "-" + age;
    	}
    }
    

    之前用 C 语言解决问题,需要分别写多个函数,每个函数根据不同的规则运行排序算法。但是由于 Java 的接口技术,因此可以使用 sort() 享受快速排序的快感,这就要求被排序的类实现了对应的接口,常用的支持排序的接口有 Comparable 接口和 Comparator 接口。

    Comparable 接口

    compare() 方法

    想要对实例化的对象进行快速排序,前提条件是这个对象是可比较的,例如数字可以按照数值的大小进行排序,而字符可以根据字典序进行排序。而对于一个对象来说,往往这个对象会具有很多属性,这就导致了对对象的排序不能简单地按照大小之类的规则来进行。换言之,个人理解的 Comparable 接口标志了这个类是可比较的,而 compare() 方法界定了这个类的比较规则。当时用 Collections.sort 和 Arrays.sort 进行排序时,就需要参考 compare() 方法定义的规则进行排序。
    Comparable 接口指定了类将实现 compare(T o1, T o2) 方法,该方法将定义实例化的对象的比较规则。传入的参数 o1 为要比较的第一个对象,o2 为要比较的第二个对象,根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数。类实现 Comparable 接口后,该对象的列表(和数组)可以通过 Collections.sort 和 Arrays.sort 进行自动排序。

    JDK 文档

    Comparable 接口

    compare() 方法

    实例

    例如将上文的 Person 类实现 Comparable 接口,compareTo 方法实现先对 name 属性进行字典序升序排序,如果 name 相同则对 age 进行升序排序。

    import java.util.*;
    
    class Person implements Comparable<Person>{
    	private String name;
    	private int age;
    	
    	public PersonSortable(String name,int age){
    		this.name = name;
    		this.age = age;
    	}
    
    	@Override
    	public String toString() {
    		return name + "-" + age;
    	}
    	
    	public int compareTo(PersonSortable obj) {
            if(this.name.compareTo(obj.name) != 0){
            	return this.name.compareTo(obj.name);
            }
            if(this.age == obj.age){
            	return 0;
            }
            if(this.age > obj.age){
            	return 1;
            }
            else{
            	return -1;
            }
        }
    }
    

    值的一提的是 String 类也实现了 Comparable 接口,因此可以调用其 compareTo 方法实现按照字典序排序。接下来写个 mian 方法进行测试:

    public static void main(String args[]){
    
          Person array[] = new Person[5];
          array[0] = new Person("zhang", 15);
          array[1] = new Person("zhang", 12);
          array[2] = new Person("wang", 14);
          array[3] = new Person("wang", 17);
          array[4] = new Person("li", 17);
    
          Arrays.sort(array);
          for(int i = 0; i < fre; i++){
                System.out.println(array[i].toString());
          }
          System.out.println(Arrays.toString(PersonSortable.class.getInterfaces()));
    }
    

    Comparator 接口

    compare() 方法

    如果类实现了 Comparable 方法,则该类进行比较的方式就被严格定下来了,但是在实际运用中可能需要让这个类支持多种排序的方式。此时可以引入 Comparator 接口实现这一点,不过 Comparator 接口并非实现在需要被排序的类上,而是用于实现比较器——用于指定比较规则的类。
    此时就不难解释为什么 Comparator 接口可以让类的排序支持多种排序方式了,因为可以写多个实现 Comparator 接口的方法的类,让这些不同的类对应不同的排序规则,用于界定排序规则的是 compare() 方法。此时就可以根据实际的需要,传入对应的实现 Comparator 接口的类给 sort 方法进行排序。

    JDK 文档

    Comparator 接口

    compare() 方法

    实例

    例如将上文的 Person 类需要支持按 age 属性升序排序和按 name 属性的字典序排序 2 种排序规则,这就需要分别写 2 个实现 Comparator 接口的类来支持。

    //NameComparator 类定义了 Person 对象按照 name 属性排序的规则
    class NameComparator implements Comparator<Person>{
    	public int compare(Person obj1, Person obj2){
    		return obj1.getName().compareTo(obj2.getName());
    	}
    	
    }
    
    //AgeComparator 类定义了 Person 对象按照 age 属性排序的规则
    class AgeComparator implements Comparator<Person>{
    	public int compare(Person obj1, Person obj2){
    		return obj1.getAge() - obj2.getAge();
    	}
    }
    

    写个 mian 方法进行测试:

    public static void main(String args[]){
    
          Person array[] = new Person[5];
          array[0] = new Person("zhang", 15);
          array[1] = new Person("zhang", 12);
          array[2] = new Person("wang", 14);
          array[3] = new Person("wang", 17);
          array[4] = new Person("li", 17);
    
          //对 name 属性进行排序
          Arrays.sort(array,new NameComparator());    //对 sort 方法传入 NameComparator 对象
          System.out.println("NameComparator:sort");
          for(int i = 0; i < fre; i++){
                System.out.println(array[i].toString());
          }
          
          //对 age 属性进行排序
          Arrays.sort(array,new AgeComparator());    //对 sort 方法传入 AgeComparator 对象
          System.out.println("AgeComparator:sort");
          for(int i = 0; i < fre; i++){
                System.out.println(array[i].toString());
          }
          System.out.println(Arrays.toString(NameComparator.class.getInterfaces()));
          System.out.println(Arrays.toString(AgeComparator.class.getInterfaces()));
    }
    

    参考资料

    Java第04次实验提纲(面向对象2-继承、多态、抽象类与接口)

  • 相关阅读:
    【原】Shell脚本-判断文件有无进而复制
    【原】个人对win7开机黑屏只有鼠标排障总结
    【原】window上安装elasticserach
    【原】CentOS7上安装Xwiki8.2.1
    Java集合中Map接口的使用方法
    Java集合中Set的常见问题及用法
    Java计时器Timer和TimerTask用法
    Java集合中List的用法
    Java RuntimeException异常处理汇总
    用Java计算某个日期100天后的日期
  • 原文地址:https://www.cnblogs.com/linfangnan/p/14267643.html
Copyright © 2011-2022 走看看