java-comparable和comparator的区别

这两个类都是接口,首先看看里面的源码:

package java.lang;
import java.util.*;
public interface Comparable<T> {
    public int compareTo(T o);
}
package java.util;

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

上面分别是comparable和comparator的源码,两个都是接口,并且非常简单,仅仅有一两个方法。

下面看用法:
Comparable用法:

import java.util.Arrays;   
public class ComparableUser implements Comparable {  

    private String id;  
    private int age;  

    public ComparableUser(String id, int age) {  
        this.id = id;  
        this.age = age;  
    }  

    public int getAge() {  
        return age;  
    }  

    public void setAge(int age) {  
        this.age = age;  
    }  

    public String getId() {  
        return id;  
    }  

    public void setId(String id) {  
        this.id = id;  
    }  

    public int compareTo(Object o) {  
        return this.age - ((ComparableUser) o).getAge();  
    }  

    /** 
     * 测试方法 
     */  
    public static void main(String[] args) {  
        ComparableUser[] users = new ComparableUser[] {  
                new ComparableUser("u1001", 25),  
                new ComparableUser("u1002", 20),  
                new ComparableUser("u1003", 21) };  
        Arrays.sort(users);  
        for (int i = 0; i < users.length; i++) {  
            ComparableUser user = users[i];  
            System.out.println(user.getId() + " " + user.getAge());  
        }  
    }  

}  

comparator用法:

public class User {  

    private String id;  
    private int age;  

    public User(String id, int age) {  
        this.id = id;  
        this.age = age;  
    }  

    public int getAge() {  
        return age;  
    }  

    public void setAge(int age) {  
        this.age = age;  
    }  

    public String getId() {  
        return id;  
    }  

    public void setId(String id) {  
        this.id = id;  
    }  
}  

import java.util.Arrays;  
import java.util.Comparator;  
public class UserComparator implements Comparator {  

    public int compare(Object arg0, Object arg1) {  
        return ((User) arg0).getAge() - ((User) arg1).getAge();  
    }  

    public static void main(String[] args) {  
        User[] users = new User[] { new User("u1001", 25),  
                new User("u1002", 20), new User("u1003", 21) };  
        Arrays.sort(users, new UserComparator());  
        for (int i = 0; i < users.length; i++) {  
            User user = users[i];  
            System.out.println(user.getId() + " " + user.getAge());  
        }  
    }  
} 

上面分别就是comparable和comparator两个接口的用法。

理论部分:
Comparable & Comparator 都是用来实现集合中元素的比较、排序的,只是 Comparable 是在集合内部定义的方法实现的排序,Comparator 是在类外部实现的排序,所以,如想实现排序,就需要在类外定义 Comparator 接口的方法或在类内实现 Comparable 接口的方法。(这里所说的类外,是值User类的类外。从上面的代码可以很明显的看出来,ComparableUser 类实现了comparable接口,comparable接口就是类内部实现,改变了类的结构。User类不实现比较功能,不能够比较,但是通过类外定义比较器UserComparator 使其具备可比较功能。

Comparator位于包java.util下,而Comparable位于包 java.lang下

Comparable 是一个对象本身就已经支持自比较所需要实现的接口(如 String、Integer 自己就可以完成比较大小操作,已经实现了Comparable接口)

自定义的类要在加入list容器中后能够排序,可以实现Comparable接口,在用Collections类的sort方法排序时,如果不指定Comparator,那么就以自然顺序排序,这里的自然顺序就是实现Comparable接口设定的排序方式。

而 Comparator 是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较。

因此,可以说上面的两个接口,一个是自己完成比较,一个是类外部定义比较器实现比较的差别而已。

用 Comparator 是策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。
这句话,我觉得说得很好!因为Comparator 是比较器,并且是在类外定义的,可以多个类复用!相当于是一种策略,当然可以定义多个策略。如果是在类内部定义的比较功能,那类就不具备这种策略了。

有时在实现Comparator接口时,并没有实现equals方法,可程序并没有报错,原因是实现该接口的类也是Object类的子类,而Object类已经实现了equals方法。
这一点也是需要注意的。按理论上讲,当comparator的compare(T,T)方法返回0的时候,equals方法应当返回true表示两个对象相等。

上面的ComparableUser 类实现了comparable接口,所以有下面的事实:
Comparable接口只提供了 int compareTo(T o)方法,也就是说假如我定义了一个Person类,这个类实现了 Comparable接口,那么当我实例化Person类的person1后,我想比较person1和一个现有的Person对象person2的大小时,我就可以这样来调用:person1.comparTo(person2),通过返回值就可以判断了;
而此时如果你定义了一个 PersonComparator(实现了Comparator接口)的话,那你就可以这样:
PersonComparator comparator= new PersonComparator();
comparator.compare(person1,person2);。

通过比较我们可以发现,两个接口使用情况不同:
1、两种方法各有优劣, 用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码
2、用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。
3、Comparator可以看成一种算法的实现,将算法和数据分离,Comparator也可以在下面两种环境下使用:
3.1 类的设计师没有考虑到比较问题而没有实现Comparable,可以通过Comparator来实现排序而不必改变对象本身
3.2 可以使用多种排序标准,比如升序、降序等。

参考:
http://pengcqu.iteye.com/blog/490149
http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt159
http://blog.csdn.net/mageshuai/article/details/3849143

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值