- 两者都 是接口
- Comparable
- 继承了这个接口,实现接口的方法(自定义排序规则),就表示“该类支持排序”
- 相当于“内部比较”
- 如果某个类实现了这个接口,就可以通过 Arrasys.sort() 对该类的数组排序
- 如果这个类装在容器中(List,Set),就可以用Collections.sort()排序
- Comparato
- 是比较器的意思,器 相当于工具 ,某个类实现这个接口就可以有比较的规则
- 相当于“外部比较”
例子**
/**
* @author bigguy_hc
* @create 2018-09-03 11:32
*/
public class Person implements Comparable<Person>{ // 实现接口,重写方法
int age;
int score;
public Person(){}
public Person(int age,int score){
this.age = age;
this.score = score;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", score=" + score +
'}';
}
@Override
// 重写方法,自定义排序规则,这里表示按年龄排序,
public int compareTo(com.bigguy.Person o) {
return this.getAge()-o.getAge();
}
}
测试 Arrays.sort()
// 数组排序
public void test2(){
Person []pers ={new Person(23,91),new Person(21,85),new Person(24,100)};
// 内部判断的依据是实现了 Comparable 接口,排序规则是 Person 重写compareTo()方法定义的规则
Arrays.sort(pers);
for (Person per : pers) {
System.out.println(per);
}
}
输出
Person{age=21, score=85}
Person{age=23, score=91}
Person{age=24, score=100}
测试 Collections.sort()
public void test2(){
Person []pers ={new Person(23,91),new Person(21,85),new Person(24,100)};
List list = Arrays.asList(pers);
Collections.sort(list); // 内部的比较规则是内部原始的 compareTo()方法
for (Person person : list) {
System.out.println(person);
}
}
输出
Person{age=21, score=85}
Person{age=23, score=91}
Person{age=24, score=100}
如果就按照上面的代码(person 实现了Comparable 接口并重写了对应的方法)
此时,需求改变,现在需要通过 score 从大到小排序,不更改 person 原来代码,就需要自定义比较器类
class PersonScoreComparator implements Comparator{
public int compare(Person o1, Person o2) {
return o2.getScore()-o1.getScore();
}
}
public void testComparator(){
Person []pers ={new Person(23,91),new Person(21,85),new Person(24,100)};
List list = Arrays.asList(pers);
// 这里传入一个比较器,里面自定义了排序规则
Collections.sort(list,new PersonScoreComparator());
for (Person person : list) {
System.out.println(person);
}
}
/*输出:
Person{age=24, score=100}
Person{age=23, score=91}
Person{age=21, score=85}
*/
注意:
至于什么时候是升序,什么时候是降序,就是重写方法时的规则:
public int compare(Person o1, Person o2) {
return o2.getScore()-o1.getScore(); // 用 o2 - o1 的就是 大 -> 小
}
Comparator 的灵活性更高,不修改比较累的原代码,可以自定义类并重写方法,但是比较麻烦,
Comparable 简单,灵活性差,如果需要改变,需要更改原代码
Arrays.sort()
public static void sort(Object[] a) {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a);
else
ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
}
Collections.sort() 没有传入比较器
public static super T>> void sort(List list) {
list.sort(null); // 传入 null 表示传入的比较器为 null
}
default void sort(Comparator super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
public static void sort(T[] a, Comparator super T> c) {
if (c == null) { // 因为上面传入 null ,所以走 sort(a)
sort(a);
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
Collections.sort() 传入比较器
public static void sort(List list, Comparator super T> c) {
list.sort(c);
}
// 这个方法其实是和上面方法时同一个方法,提高了代码的复用性
default void sort(Comparator super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
总结:
Arrays.sort() 和 Collections.sort() 先判断是否传入比较器
如果传入比较器按比较器的规则比较
否则如果实现了Comparable 接口,按照重写 的compareTo()方法规则比较
否则,如果还比较则报错(里面的元素没有比较性)