今天来分析一下Comparable和Comparator的区别,以及源码的解读。
Comparable
- 源码:
public interface Comparable<T> {
public int compareTo(T o);
}
我们可以发现Comparable只是一个简单的泛型接口,内部含有一个compareTo接口。
根据接口的说明可知:
- 实现了这个接口的集合(或者数组)可以通过使用Collections.sort()(或者Arrays.sort())进行排序
- 实现了这个接口的对象,并重写了CompareTo()方法,可以无需Comparator比较器按照key值进行排序
- 使用方法:
@Data
@NoArgsConstructor
@AllArgsConstructor
class Person implements Comparable<Person> {
private String name;
private Integer age;
@Override
public int compareTo(Person o) {
return this.getAge().compareTo(o.getAge());
}
}
public static void main(String[] args) {
Person p1 = new Person("stalary", 21);
Person p3 = new Person("hawk", 19);
Person p2 = new Person("claire", 20);
List<Person> list = new ArrayList<>();
list.add(p1);
list.add(p2);
list.add(p3);
Collections.sort(list);
System.out.println(list);
}
- 实现了将对象集合按年龄的升序排序,当想实现降序排序的时候,只需要将this和p的顺序交换
- compareTo()会返回一个整数,小于0代表小于,等于0代表等于,大于0代表大于,当返回正数时,即交换两个数,完成比较
Comparator
当我们想要比较的对象没有实现Comparable接口时,即没发使用上述方法进行比较,这时可以使用Comparator来进行比较。
下面先来看一下Comparator的源码
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
default Comparator<T> reversed() {
return Collections.reverseOrder(this);
}
default Comparator<T> thenComparing(Comparator<? super T> other) {
Objects.requireNonNull(other);
return (Comparator<T> & Serializable) (c1, c2) -> {
int res = compare(c1, c2);
return (res != 0) ? res : other.compare(c1, c2);
};
}
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
return thenComparing(comparingInt(keyExtractor));
}
- 我们排序时需要实现的方法是compare。
- equals在排序时没有用到,是从Object继承来的默认实现
- 后面省略了一些default的方法,这些方法都是jdk1.8中针对lambda实现的默认方法
- 使用方法:
List<People> peopleList = new ArrayList<>();
peopleList.addAll(Arrays.asList(new People("stalary", 21),new People("claire", 20),new People("hawk", 19)));
Collections.sort(peopleList, new PeopleComparator());
@Data
@NoArgsConstructor
@AllArgsConstructor
class People {
private String name;
private Integer age;
}
@Data
@NoArgsConstructor
class PeopleComparator implements Comparator<People> {
@Override
public int compare(People o1, People o2) {
return o1.getAge() - o2.getAge();
}
}
在jdk1.8中我们可以这样进行排序
peopleList.sort(Comparator.comparing(People::getAge));
当想要升序排序时,我们可以修改比较器中的compare或者直接调用reversed方法(1.8中实现的默认方法)
还可以在比较时写一个匿名内部类的比较器进行比较,但使用lambda更加方便,所以不推荐使用。
总结
总体来看Comparator更加灵活,可以不需要对象去继承一个接口,而且在1.8引入了lambda以后使用更加方便