每日一题:Comparable接口和Comparator接口的区别

1、简介
Comparable(java.lang.Comparator) Comparator(java.util.Comparator),从字面上看这两个接口都是用来做比较用的,平时在使用的时候,总是记不清他们到底有什么区别,所以在此记录下,方便以后查看:

1.1、Comparable
Comparable可以认为是一个内比较器,实现了Comparable接口的类有一个特点,就是这些类是可以和自己比较的,其依赖compareTo方法的实现,compareTo方法也被称为自然比较方法。compareTo方法的返回值是int,有三种情况:

1、比较者大于被比较者(也就是compareTo方法里面的对象),那么返回正整数
2、比较者等于被比较者,那么返回0
3、比较者小于被比较者,那么返回负整数

在给集合排序的时候,有个工具类叫做Collections,这个工具类可以用来给集合排序,详见如下代码:

List<Integer> list = new ArrayList<>();
list.add(14);
list.add(35);
list.add(2);
list.add(12);
Collections.sort(list);
System.out.println(list);
这个打印的结果是:[2,12,14,35];

根据结果可知:Collections对于Integer类型的数组默认的排序结果是升序的

    如果我们对自定义对象的数组能否进行排序呢?经过代码实验,结果是不可以的。为什么不可以呢?那我们看一下Collections中的sort方法源码:

public static <T extends Comparable<? super T>> void sort(List<T> list) {
        list.sort(null);
}

在源码中,有一个T extends Comparable的泛型通配符 ,要求集合中的T必须要实现Comparable接口,那么我们动手写个对象类,实现Comparable接口,这个接口中,有一个抽象方法需要我们实现,这个方法就是CompareTo。

样例:
1.定义一个Person类,实现Comparable接口,并且重写compareTo方法:默认比较的是当前Person类,通过age属性进行比较。

public class Person implements Comparable<Person>{
	String name;
	Integer age;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Person() {
		super();
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
     
	public int compareTo(Person o) {
		return this.age - o.age;
    }

2.定义测试类TestPerson.java,定义一个ArrayList保存Person,打乱顺序后,查看输出结果。代码如下:    

        List<Person> list = new ArrayList<>(10);
        Person person;
        for (int i=0; i<10; i++) {
            person = new Person("person" + i, i);
            list.add(person);
        }
        Collections.shuffle(list);
        //Collections.sort(list);
        list.stream().forEach(System.out::println);
        
    }
输出结果:
Person [name=person2, age=2]
Person [name=person6, age=6]
Person [name=person1, age=1]
Person [name=person9, age=9]
Person [name=person0, age=0]
Person [name=person4, age=4]
Person [name=person8, age=8]
Person [name=person3, age=3]
Person [name=person5, age=5]
Person [name=person7, age=7]


输出是乱序的


Person [name=person0, age=0]
Person [name=person1, age=1]
Person [name=person2, age=2]
Person [name=person3, age=3]
Person [name=person4, age=4]
Person [name=person5, age=5]
Person [name=person6, age=6]
Person [name=person7, age=7]
Person [name=person8, age=8]
Person [name=person9, age=9]

 输出是有序的,并且是升序

在测试代码中,使用Collections.sort就可以对Person的List进行排序了。而compareTo方法,实际上就是我们需要设置的排序的规则。使用this对象和参数比较,就是升序,反之就是降序。所以我们如果想要让Person集合中的对象按照年龄进行降序排列,就可以使用o.age -this.age;(基本类型可以使用减法替代compareTo);

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

  1、o1大于o2,返回正整数
  2、o1等于o2,返回0
  3、o1小于o3,返回负整数

样例:

1、定义一个Person类不实现任何接口。
2、定义PersonComparator.java类,实现Comparator接口,重写compare()方法,和前面一样根据age进行比较。

public class PersonComparator implements Comparator<Person> {

    @Override
    public int compare(Person g1, Person g2) {
        return g1.getAge() - g2.getAge();
    }
    
}

3、定义测试类,代码如下:

        List<Person> list = new ArrayList<>(10);
        Person person;
        for (int i=0; i<10; i++) {
            person = new Person("person" + i, i);
            list.add(person);
        }

        list.stream().forEach(System.out::println);
        
    }
输出结果:
Person [name=person0, age=0]
Person [name=person1, age=1]
Person [name=person2, age=2]
Person [name=person3, age=3]
Person [name=person4, age=4]
Person [name=person5, age=5]
Person [name=person6, age=6]
Person [name=person7, age=7]
Person [name=person8, age=8]
Person [name=person9, age=9]

 输出是有序的,并且是升序

这段代码就实现了一个Integer集合的升序排列,这个接口中有一个方法叫做compare,里边包含两个参数:如果用第一个和第二个做比较得到的就是升序,反之得到的就是降序。同样的你也可以使用这种方式对我们自己定义的类记性排序。

3、总结,后者相比前者有如下优点:

  Comparable:    内部比较器,一个类如果想要使用Collections.sort(list) 方法进行排序,则需要实现该接口。

 Comparator:    外部比较器用于对那些没有实现Comparable接口或者对已经实现的Comparable中的排序规则不满意进行排序.无需改变类的结构,更加灵活。
 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值