A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 张11。。。 于 2019-4-23 18:42 编辑

Comparable和Comparator区别


       Java语言中Comparable和Comparator接口都是用来比较大小的。
       Comparable 是排序接口,若一个类实现了 Comparable接口,也就表明“该类支持排序”。而 Comparator 是比较器;我们若需要控制某个类的顺序,可以建立一个 “该类的比较器” 来进行排序。
  前者Comparable接口应该比较固定,和一个具体类相绑定,而后者Comparator接口比较灵活,它可以被用于各个需要比较功能的类使用。可以说前者属于“静态绑定”,而后者可以“动态绑定”。
  不难发现:Comparable 接口相当于内部比较器,而Comparator接口相当于外部比较器。
首先来看一下Comparable的定义:
import java.util.*;public interface Comparable<T> {  
  public int compareTo(T o);
}
Comparator的定义如下:
package java.util;
public interface Comparator<T> {  
  int compare(T o1, T o2);   
  boolean equals(Object obj);
}
       Comparable对实现它的每个类的对象进行整体排序。这个接口需要类本身去实现。若一个类实现了Comparable接口,实现Comparable 接口的类的对象的List列表或数组可以通过 Collections.sort或 Arrays.sort进行排序。此外,实现Comparable接口的类的对象可以用作“有序映射(如 TreeMap)”中的键或“有序集合 (TreeSet)”中的元素,而不需要指定比较器。
public class Person implements Comparable<Person>{   
   private int age;
   private String name;  
  public Person(String name, int age){      
   this.name = name;     
   this.age = age;   
}   
@Override  
  public int compareTo(Person o){   
     return this.age-o.age;  
  }   
@Override
   public String toString(){   
    return name+":"+age;   
}
}
       可以看到Person实现了Comparable接口中的compareTo方法。实现Comparable接口必须修改自身的类,即在自身类中实现接口中相应的方法。
  测试代码:
        Person person1 = new Person("yy",18);   
      Person person2 = new Person("dd",17);      
     Person person3 = new Person("qq",19);     
   List<Person> list = new ArrayList<>();   
        list.add(person1);      
        list.add(person2);      
        list.add(person3);     
       System.out.println(list);
       Collections.sort(list);   
       System.out.println(list);       如果我们的这个类无法修改,譬如String,我们又要对其进行排序,当然String中已经实现了Comparable接口,如果单纯的用String举例就不太形象。对类自身无法修改这就用到了Comparator这个接口(策略模式)。
public final class Person2{  
  private int age;  
  private String name;  
  public Person2(String name, int age) {  
      this.name = name;      
      this.age = age;   
}   
@Override
   public String toString(){   
     return name+":"+age;   
}
}
       如类Person2,这个类已经固定,无法进行对其类自身的修改,也修饰词final了,你也别想继承再implements Comparable,那么此时怎么办呢?在类的外部使用Comparator的接口。如下测试代码:   
     Person2 p1 = new Person2("yy",18);   
     Person2 p2 = new Person2("dd",17);   
     Person2 p3 = new Person2("qq",19);   
    List<Person2> list2 = new ArrayList<Person2>();   
      list2.add(p1);     
      list2.add(p2);      
      list2.add(p3);      
     System.out.println(list2);      
  Collections.sort(list2,new Comparator<Person2>(){   
        @Override         
        public int compare(Person2 o1, Person2 o2){      
          if(o1 == null || o2 == null)            
          return 0;           
          return o1.getAge()-o2.getAge();        
    }      
  });      
   System.out.println(list2);
       这里(public static <T> void sort(List<T> list, Comparator<? super T> c) )采用了内部类的实现方式,实现compare方法,对类Person2的list进行排序。
  再譬如需要对String进行排序,且不区分大小写,我们知道String中的排序是字典排序,譬如:A a D排序之后为A D a,这样显然不对,那么该怎么办呢?        Collections.sort(list, new Comparator<String>() {   
        @Override         
        public int compare(String o1, String o2){        
          if(o1 == null || o2 == null)              
          return 0;         
         return o1.toUpperCase().compareTo(o2.toUpperCase());      
      }     
   });
       这样就可以实现不区分大小进行排序String的集合了,是不是很方便
       细心的朋友可能会发现,明明在Comparator接口中定义了两个方法,为什么继承的时候只实现了一个方法,实际上,我们知道当一个类没有显式继承父类的时候,会有一个默认的父类,即java.lang.Object,在Object类中有一个方法即为equals方法,所以这里并不强制要求实现Comparator接口的类要实现equals方法,直接调用父类的即可,虽然你显式的实现了equals()方法 will be a better choice~
       事实上,Java平台类库中的所有值类都实现了Comparable接口。如果你正在编写一个值类,它具有非常明显的内在排序关系,比如按字母顺序、按数值顺序或者按年代顺序,那你就应该坚决考虑实现这个接口。
        compareTo方法不但允许进行简单的等同性进行比较,而且语序执行顺序比较,除此之外,它与Object的equals方法具有相似的特征,它还是一个泛型。类实现了Comparable接口,就表明它的实例具有内在的排序关系,为实现Comparable接口的对象数组进行排序就这么简单: Arrays.sort(a);
  对存储在集合中的Comparable对象进行搜索、计算极限值以及自动维护也同样简单。列如,下面的程序依赖于String实现了Comparable接口,它去掉了命令行参数列表中的重复参数,并按字母顺序打印出来:
public class WordList{   
public static void main(String args[]){   
    Set<String> s = new TreeSet<String>();   
    Collections.addAll(s,args);  
    System.out.println(s);
   }



1 个回复

倒序浏览
不错,不错,奈斯,歪瑞够的!!!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马