比较器Comparator
在Java中,如果想要对对象进行排序,一般有两种方式:
待比较对象的类实现Comparable接口,重写compareTo(T o)方法(一般称之为自然排序)
自定义Comparator,重写Compare(T o1, T o2)方法(一般称之为定制排序)
Comparable
若一个类实现了Comparable接口,就意味着“该类支持排序”。
对实现Comparable接口的类的对象的List/数组,则该List/数组可以通过Collections.sort/ Arrays.sort进行排序。
对实现Comparable接口的类的对象,可以用作有序键值对容器(如TreeMap)中的键或有序集合(如TreeSet)中的元素,而不需要指定比较器。
它的定义如下:
public interface Comparable<T> {
public int compareTo(T o);
}
compareTo(T o)的返回结果的说明:假设我们通过 x.compareTo(y) 来“比较x和y的大小”。
若返回“负数”,意味着“x比y小”
返回“零”,意味着“x等于y”
返回“正数”,意味着“x大于y”
Comparator
Comparator的定义如下:
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
}
说明:
若一个类实现Comparator接口,则必须要实现compareTo(T o1, T o2) 函数,但可以不实现 equals(Object obj) 函数。
为什么可以不实现 equals(Object obj) : Java中的一切类都是继承于java.lang.Object,在Object.java中实现了equals(Object obj)函数,所以,其它所有的类也相当于都实现了该函数。即任何类默认都是已经实现了equals(Object obj)的。
compare(T o1, T o2) 的返回结果的说明:
返回“负数”,意味着“o1比o2小”;
返回“零”,意味着“o1等于o2”;
返回“正数”,意味着“o1大于o2”。
注意:JDK1.7中,必须返回一对相反数,如1和-1,不能是1和0。因为1.7的排序算法采用TimSort,对返回值有严格要求
无论对于Comparable还是Comparator,都有这样一个推荐做法:
(compare(x, y)==0) == x.equals(y)
x.compare(y) == x.equals(y)
即两个对象通过compare比较等于0, 则最好这两个对象是equals的。反之,如果两个对象通过compare比较不相等,那么这两个对象通过equals比较时,返回fasle。
使用
待排序的对象的类
public class Person implements Comparable<Person>{
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person o) {
int res = 0;
if(age > o.age){
res = 1;
}else if(age < o.age){
res = -1;
}
return res;
}
@Override
public String toString() {
return String.format("%s: %d", this.name, this.age);
}
//省略getter和setter方法
}
排序
public class Example {
public static void main(String[] args) {
//初始化对象集合
List<Person> personList = new ArrayList<>();
personList.add(new Person("a", 18));
personList.add(new Person("aa", 6));
personList.add(new Person("aaa", 32));
personList.add(new Person("aaaa", 21));
System.out.println("默认按年龄排序");
Collections.sort(personList);
personList.forEach(person -> {
System.out.println(person);
});
System.out.println("自定义按名字的长度排序");
Collections.sort(personList, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
int length1 = o1.getName().length();
int length2 = o2.getName().length();
int res = 0;
if (length1 > length2) {
res = 1;
} else if (length1 < length2) {
res = -1;
}
return res;
}
});
personList.forEach(person -> {
System.out.println(person);
});
}
}
//输出如下
默认按年龄排序
aa: 6
a: 18
aaaa: 21
aaa: 32
自定义按名字的长度排序
a: 18
aa: 6
aaa: 32
aaaa: 21
按照年龄排序时,我们定义:进行compare时,年龄大的Person>年龄小的Person,通过Collections.sort()时,会按照我们定义的规则,对集合中的Person按照年龄进行从小到大的排序;
按照名字长度排序时,我们定义:进行compare时,名字长的Person>名字短的Person,通过Collections.sort()时,会按照我们定义的规则,对集合中的Person按照名字长度从小到大的排序;
Last updated