您的位置:首页 > 编程语言 > Java开发

java中Comparable和Comparator的区别整理小结

2018-03-28 16:57 453 查看
一、java中,对集合对象或者数组对象排序,有两种实现方式。
总结:
(1)对象实现Comparable接口。 
 即Comparable 自然排序。(实体类实现)
(2)定义比较器,实现Comparator接口。 
 即Comparator 是定制排序。(无法修改实体类时,直接在调用方创建)

二、Comparable简介
1.Comparable是排序接口。若一个类实现了Comparable接口,就意味着该类支持排序。实现了Comparable接口的类的对象的列表或数组可以通过Collections.sort或Arrays.sort进行自动排序。
2.Collections.sort (和Arrays.sort )可以自动对实现此接口的对象进行列表(和数组)排序。 实现该接口的对象,可以使用如在键sorted map或作为在元件sorted set ,而不需要指定一个comparator 。
3.若一个类实现了comparable接口,则意味着该类支持排序。如String、Integer自己就实现了Comparable接口,可完成比较大小操作。
一个已经实现comparable的类的对象或数据,可以通过Collections.sort(list) 或者Arrays.sort(arr)实现排序。通过Collections.sort(list,Collections.reverseOrder());对list进行倒序排列。
4.此外,实现此接口的对象可以用作有序映射中的键或有序集合中的集合,无需指定比较器。
Comparable 接口仅仅只包括一个函数,该接口定义如下:
package java.lang;
import java.util.*;
public interface Comparable<T> 
{
    public int compareTo(T o);
}
T表示可以与此对象进行比较的那些对象的类型。
 此接口只有一个方法compare,比较此对象与指定对象的顺序,如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。

5.comparable实例

import java.util.*; 
public class test {
   public static void main(String[] args) {
      List<UserInfo> list = new ArrayList<UserInfo>();
      list.add(new UserInfo(1,21,"刘备"));
      list.add(new UserInfo(2,27,"曹操"));
      list.add(new UserInfo(3,15,"孙权")); 
      list.add(new UserInfo(5,24,"吕布"));
      list.add(new UserInfo(4,24,"张飞"));

      //对该类排序
      Collections.sort(list);
      for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
      }
  }
}
class UserInfo implements Comparable<UserInfo>{
   private int userid;
   private int age;
   private String name;
   public UserInfo(int userid, int age, String name) {
      this.userid = userid;
      this.age = age;
      this.name = name;
   }
   public int getUserid() {
      return userid;
   }
   public void setUserid(int userid) {
      this.userid = userid;
   }
   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;
   }
   @Override
   public String toString(){
      return this.userid+","+this.age+","+this.name;
   }
   @Override
   public int compareTo(UserInfo o) {
   //如果年龄相同,则比较userid,也可以直接 return this.age-o.age;
      if(this.age-o.age==0){
 return this.userid-o.userid;
      }
      else{
          return this.age-o.age;
      }
   }
}
输出:
3,15,孙权
1,21,刘备
4,24,张飞
5,24,吕布
2,27,曹操

三、Comparator简介
1.Comparator是比较接口,我们如果需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口),那么我们就可以建立一个“该类的比较器”来进行排序,这个“比较器”只需要实现Comparator接口即可。也就是说,我们可以通过实现Comparator来新建一个比较器,然后通过这个比较器对类进行排序。

2.如果引用的为第三方jar包,这时候,没办法改变类本身,可是使用这种方式。
Comparator是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足要求时,可写一个比较器来完成两个对象之间大小的比较。
Comparator体现了一种策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。

3.该接口定义如下:
package java.util;
public interface Comparator<T>
 {
    int compare(T o1, T o2);
    boolean equals(Object obj);
 }
注意:
(1)若一个类要实现Comparator接口:它一定要实现compare(T o1,T o2) 函数,但可以不实现equals(Object obj)函数。
(2)int compare(T o1,T o2) 是“比较o1和o2的大小”。返回“负数”,意味着“o1比o2小”;返回“零”,意味着“o1等于o2”;返回“正数”,意味着“o1大于o2”。

4.comparator实例
import java.util.*; //直接这样写,比下面四条语句简洁
//import java.util.ArrayList;
//import java.util.Collections;
//import java.util.List;
//import java.util.Comparator;

public class day6 {
   public static void main(String[] args) {
      List<UserInfo> list = new ArrayList<UserInfo>();
      list.add(new UserInfo(1,21,"刘备"));
      list.add(new UserInfo(2,27,"曹操"));
      list.add(new UserInfo(3,15,"孙权"));
      list.add(new UserInfo(5,24,"吕布"));
      list.add(new UserInfo(4,24,"张飞"));
      //new一个比较器
      MyComparator comparator = new MyComparator();
      //对list排序
      Collections.sort(list,comparator);
      for(int i=0;i<list.size();i++){
         System.out.println(list.get(i));
      }
   }
}

class MyComparator implements Comparator<UserInfo>{
   @Override
   public int compare(UserInfo o1,UserInfo o2) {
      if(o1.getAge()-o2.getAge()==0){
return o1.getUserid()-o2.getUserid();
      }
      else{
return o1.getAge()-o2.getAge();
      }
   }
}
class UserInfo{
   private int userid;
   private int age;
   private String name;
   
   public UserInfo(int userid, int age, String name) {
      this.userid = userid;
      this.age = age;
      this.name = name;
   }
   public int getUserid() {
      return userid;
   }
   public void setUserid(int userid) {
      this.userid = userid;
   }
   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;
   }
   @Override
   public String toString(){
      return this.userid+","+this.age+","+this.name;
   }
}
输出:
3,15,孙权
1,21,刘备
4,24,张飞
5,24,吕布
2,27,曹操

5. Comparator使用方式主要分三步:
(1)创建一个Comparator接口的实现类,并赋值给一个对象
   在compare方法中针对自定义类写排序规则
(2)将Comparator对象作为参数传递给 排序类的某个方法
(3)向排序类中添加 compare 方法中使用的自定义类

即举个例子:
// 1.创建一个实现 Comparator 接口的对象
Comparator comparator = new Comparator()
//2.将此对象作为形参传递给 TreeSet 的构造器中
TreeSet treeSet = new TreeSet(comparator);
//3.向 TreeSet 中添加 步骤 1 中 compare 方法中设计的类的对象
treeSet.add(new NewBookBean("A",34));
treeSet.add(new NewBookBean("S",1));

四、Comparable和Comparator整体实例
import java.util.*;
public class day6 {
    public static void main(String[] args){
        List<Node> list = new ArrayList<Node>();
        list.add(new Node("关羽",25));
        list.add(new Node("赵云",22));
        list.add(new Node("甘宁",20));
        list.add(new Node("张辽",23));
        System.out.println("Comparator--年龄排序===");
        Collections.sort(list, new Comparator<Node>() {
            @Override
            public int compare(Node o1, Node o2) {
                return o1.getAge()-o2.getAge();
            }
        });

        for(Iterator<Node> it = list.iterator(); it.hasNext();){
            System.out.println(it.next());
        }
        System.out.println("Comparator--姓名排序===");
        Collections.sort(list, new Comparator<Node>() {
            @Override
            public int compare(Node o1, Node o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        for(Iterator<Node> it = list.iterator(); it.hasNext();){
            System.out.println(it.next());
        }
        System.out.println("Comparable--年龄排序...");
        Collections.sort(list);
        for(Iterator<Node> it = list.iterator(); it.hasNext();){
            System.out.println(it.next());
        }
    }
}

class Node implements Comparable<Node>{
    private String name;
    private int age;
    public Node(String name, int age){
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int compareTo(Node other){
        if(age > other.getAge())
            return -1;
        if(age < other.getAge())
            return 1;
        return 0;
    }
    public String toString(){
        return "姓名 "+name+" 年龄 "+age;
    }
}
输出:
Comparator--年龄排序===
姓名 甘宁 年龄 20
姓名 赵云 年龄 22
姓名 张辽 年龄 23
姓名 关羽 年龄 25
Comparator--姓名排序===
姓名 关羽 年龄 25
姓名 张辽 年龄 23
姓名 甘宁 年龄 20
姓名 赵云 年龄 22
Comparable--年龄排序...
姓名 关羽 年龄 25
姓名 张辽 年龄 23
姓名 赵云 年龄 22
姓名 甘宁 年龄 20

五、补充
1.Comparable 是排序接口;若一个类实现了 Comparable 接口,就意味着 “该类支持排序”。而 Comparator 是比较器;我们若需要控制某个类的次序,可以建立一个 “该类的比较器” 来进行排序。 
前者应该比较固定,和一个具体类相绑定,而后者比较灵活,它可以被用于各个需要比较功能的类使用。可以说前者属于 “静态绑定”,而后者可以 “动态绑定”。 
我们不难发现:Comparable 相当于 “内部比较器”,而 Comparator 相当于 “外部比较器”。

2.对于一些普通的数据类型(比如 String, Integer, Double…),它们默认实现了Comparable 接口,实现了 compareTo 方法,我们可以直接使用。
而对于一些自定义类,它们可能在不同情况下需要实现不同的比较策略,我们可以新创建 Comparator 接口,然后使用特定的 Comparator 实现进行比较。

3.两种方法各有优劣, 用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码。 用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。

本篇博文是小白我在大神的肩膀上,吸收整理出来的。衷心感谢大神们的无私奉献、厚薄积发的精神,这种品质给我们小白在技术上的成长带来了很大的帮助。
参考: https://blog.csdn.net/tolcf/article/details/52229068 https://blog.csdn.net/yguoelect/article/details/77435073
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: