Java中Comparable和Comparator区别

Comparable

只有一个方法
public int compareTo(T o);

compareTo方法的返回值是int,有三种情况:

1、比较者(调用compareTo方法者)大于被比较者(也就是compareTo方法接受对象),那么返回 1

2、比较者等于被比较者,那么返回0

3、比较者小于被比较者,那么返回 -1

Comparable可以认为是一个内比较器,很多类都会实现这个接口以提供对该类对象之间比较的默认实现;比如String,Integer,Float,Double类都实现了Comparable接口。实现Comparable接口的类有一个特点,就是这些类提供了自己对象之间比较大小的默认实现,如果开发者add进入一个Collection的对象想要通过Collections的sort方法帮你自动进行排序的话,那么这个add进入的对象类必须实现Comparable接口。

package org.vincent.strategy.test;

/**
 * 实现一个类如果需要实现比较大小,那么继承Comparable接口,泛型参数T 是比较谁就写谁
 * 
 * @ClassName: Domain
 * @Description: TODO(这里用一句话描述这个类的作用)
 * @author PengRong
 * @date 2017年3月10日 下午6:41:54
 */
public class Domain implements Comparable<Domain> {

    private String string;

    public String getString() {
        return this.string;
    }

    public void setString(String string) {
        this.string = string;
    }

    public Domain(String name) {
        this.string = name;
    }

    public int compareTo(Domain o) {
        // TODO Auto-generated method stub
        if (this.string.compareTo(o.getString()) > 0)
            return 1;
        else if (this.string.compareTo(o.getString()) == 0)
            return 0;
        else
            return -1;
    }

}

测试代码:

package org.vincent.strategy.test;

public class Test {
    public static void main(String[] args) {
        Domain d1 = new Domain("c");
        Domain d2 = new Domain("c");
        Domain d3 = new Domain("b");
        Domain d4 = new Domain("d");
        System.out.println(d1.compareTo(d2));
        System.out.println(d1.compareTo(d3));
        System.out.println(d1.compareTo(d4));
    }
}

输出:


0
1
-1

实现Comparable接口的类是为了支持类对象之间是可以比较的,但是其实代码里面Comparable的泛型未必就一定要是Domain,将泛型指定为String或者指定为其他任何任何类型都可以—-只要我们知道具体的比较类型就行。
比如讲Comparable的泛型参数指定为String,相应compareTo函数变为:

    public int compareTo(String o) {
        // TODO Auto-generated method stub
        if (this.string.compareTo(o) > 0)
            return 1;
        else if (this.string.compareTo(o) == 0)
            return 0;
        else
            return -1;
    }

但是一般我们不这样做,泛型参数直接为我们定义的类Domain
总结:Comparable接口就是用于给类提供默认比较功能的。

Comparator

Comparator可以认为是是一个外比较器,认为有两种情况可以使用实现Comparator接口的方式:

  • 一个对象不支持自己和自己比较(没有实现Comparable接口),但是又想对两个对象进行比较;一般同类型对象比较很少实现这个接口。

  • 一个对象实现了Comparable接口,但是开发者认为compareTo方法中的比较方式并不是自己想要的那种比较方式。Comparator接口更多是实现这个功能。对特定比较需求提供支持。

int compare(T o1, T o2);

Comparator接口里面有一个compare方法,方法有两个参数T o1和T o2,是泛型的表示方式,分别表示待比较的两个对象,方法返回值和Comparable接口一样是int,有三种情况:

  • 1、o1大于o2,返回1

  • 2、o1等于o2,返回0

  • 3、o1小于o3,返回-1

实例:


package org.vincent.strategy;

import java.util.Comparator;

/**
 * 定义一个按照绝对值排序的比较器
 *
 * @ClassName: AbsComparator
 * @Description: TODO(这里用一句话描述这个类的作用)
 * @author PengRong
 * @date 2017年3月10日 下午6:06:41
 */
public class AbsComparator implements Comparator {
    public int compare(Object o1, Object o2) {
        int v1 = Math.abs(((Integer) o1).intValue());
        int v2 = Math.abs(((Integer) o2).intValue());
        return v1 > v2 ? 1 : (v1 == v2 ? 0 : -1);
    }
}

测试:

package org.vincent.strategy;

import java.util.Arrays;
import java.util.Random;

public class Test {
    @SuppressWarnings("unchecked")
    public static void main(String[] args) {

        // 产生一个20个随机整数的数组(有正有负)
        Random rnd = new Random();
        Integer[] integers = new Integer[20];
        for (int i = 0; i < integers.length; i++) {
            integers[i] = new Integer(rnd.nextInt(100) * (rnd.nextBoolean() ? 1 : -1));
        }

        System.out.println("用Integer内置方法排序:也就是Integer实现Comparable接口所描述的比较方法");
        Arrays.sort(integers);
        System.out.println(Arrays.asList(integers));

        System.out.println("用AbsComparator排序:按绝对值大小排序");
        Arrays.sort(integers, new AbsComparator());
        System.out.println(Arrays.asList(integers));
    }
}

输出结果:

Integer内置方法排序:也就是Integer实现Comparable接口所描述的比较方法
[-88, -82, -82, -78, -70, -70, -58, -58, -48, -48, -46, -35, -10, 4, 7, 19, 39, 45, 53, 85]AbsComparator排序:按绝对值大小排序
[4, 7, -10, 19, -35, 39, 45, -46, -48, -48, 53, -58, -58, -70, -70, -78, -82, -82, 85, -88]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章