Java基础——Comparable与Comparator两种比较器的使用

前言

在Java中,如Integer、Double等基本数据类型之间可以直接进行比较大小,而Java是一门面向对象语言,一组对象之间进行排序比较显得尤为重要,那对象之间又该如何进行比较呢?

Comparable与Comparator都是Java提供的对象间进行比较的接口,只不过用法上会有差异。
本质是根据类中的属性进行排序,这里的属性通常指基本数据类型,当然也可以是引入数据类型,如String、自定义类,在这里自定义类比较的也是类中的属性。

Comparable接口

使用Comparable给对象进行排序,目标对象只需要实现接口并重写comparTo方法即可。

其中Comparable接口需要传入泛型,一般传入本类,也可以不传或传入Object,再重写方法的时候进行instanceof判断进行强转即可。

public class ComparableTest implements Comparable<ComparableTest>{

	//两个基本属性
    private Integer id;
    private String name;

    public ComparableTest(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "ComparableTest{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    //重写的compareTo方法
    @Override
    //传入的参数时与this比较的对象
    public int compareTo(ComparableTest o) {
    	//先进行id属性的比较,如果this大返回1表示升序排列,相反返回-1表示降序。
        if (this.id > o.id) {
            return 1;
        }else if (this.id < o.id) {
            return -1;
        }
        //如果id属性值相等,那么就根据第二个属性String进行比较
        else {
        	//这里直接返回是因为String类已经实现的Comparable接口
            return this.name.compareTo(o.name);
        }
    }
}

String类实现的comparTo方法

public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

测试

public static void main(String[] args) {
        ComparableTest[] comparableTests = new ComparableTest[5];
        comparableTests[0] = new ComparableTest(1,"孙悟空");
        //其中id属性相等,这里就会比较String属性。
        comparableTests[1] = new ComparableTest(25,"猪八戒");
        comparableTests[2] = new ComparableTest(25,"鲁班");
        comparableTests[3] = new ComparableTest(89,"孙尚香");
        comparableTests[4] = new ComparableTest(74,"百里守约");

        //重写时候调用Arrays工具类sort方法直接进行排序
        Arrays.sort(comparableTests);
        //输出验证
        System.out.println(Arrays.toString(comparableTests));
    }

测试结果

[ComparableTest{id=1, name='孙悟空'},
 ComparableTest{id=25, name='猪八戒'},
 ComparableTest{id=25, name='鲁班'},
 ComparableTest{id=74, name='百里守约'}, 
 ComparableTest{id=89, name='孙尚香'}]

Comparable总结

通过Comparable接口实现比较大小,实际上就是通过compareTo方法进行本对象与传入对象进行属性的逐个比较,如果第一个属性相等,那么就比较第二个,以此类推。

特别的,如果类中含有引用数据(如String或自定义类),那么想要通过引用数据进行比较大小,则引用数据属性也必须实现Comparable接口,如本例中的String类型属性,String就已经实现的Comparable接口。

Comparator接口

相比于Comparable接口更加灵活,所以被称为自定义排序,本类可以不直接实现此接口,而是在调用Arrays.sort()方法时传入实现此接口的对象即可。

基础待比较类

public class ComparatorTest {

    private Integer id;
    private String name;

    public ComparatorTest(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "ComparableTest{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

测试

public static void main(String[] args) {
        ComparatorTest[] ComparatorTests = new ComparatorTest[5];
        ComparatorTests[0] = new ComparatorTest(1,"孙悟空");
        ComparatorTests[1] = new ComparatorTest(25,"猪八戒");
        ComparatorTests[2] = new ComparatorTest(25,"鲁班");
        ComparatorTests[3] = new ComparatorTest(89,"孙尚香");
        ComparatorTests[4] = new ComparatorTest(74,"百里守约");

        //重写时候调用Arrays工具类sort方法直接进行排序
        //这里直接采用匿名内部类写法重写compare方法
        Arrays.sort(ComparatorTests, new Comparator<ComparatorTest>() {
            @Override
            public int compare(ComparatorTest o1, ComparatorTest o2) {
                //Integer等基本数据类型包装类已经实现了Comparator接口
                //直接调用即可
                int compare = Integer.compare(o1.getId(), o2.getId());
                //如果返回值不等于0,说明两属性不相等,直接返回对应值即可。
                if (compare != 0){
                    return compare;
                }
                //如果相等,那就比较第二个属性String
                //这里仍然调用String已经重写的compareTo方法
                return o1.getName().compareTo(o2.getName());
            }
        });
        //输出验证
        System.out.println(Arrays.toString(ComparatorTests));
    }

Integer包装类重写的compare方法

public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }

测试结果

[ComparableTest{id=1, name='孙悟空'},
 ComparableTest{id=25, name='猪八戒'},
 ComparableTest{id=25, name='鲁班'},
 ComparableTest{id=74, name='百里守约'},
 ComparableTest{id=89, name='孙尚香'}]

Comparator总结
相比Comparable接口,Comparator降低了耦合性,不需要本类直接实现接口,而是在调用比较时,直接传入实现接口的匿名类,重写compare方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值