需要给自定义类型实现比较接口
实现了比较接口以后,不需要再写equals了,因为comapreTo已经帮忙比较的事情,如果两个对象相等,compareTo的结果是0,新的值会覆盖旧的值
到 add(p2)的时候
会报错说
ClassCastException: Person cannot be cast to class java.lang.Comparable
因为TreeSet调用add方法,其实是底层调用了 TreeMap 的 put方法
new TreeSet<>()
new 的时候,调用的是无参构造方法
在TreeMap里面的无参构造方法中,会给compatator赋一个null
在TreeMap的put方法中,如果看到comparator是空,会把key强转成 Comparable 类型
而Person类型不是Comparable, Person类没有实现java.lang.Comparable接口
Comparator 和 Comparable
java.util.Comparator
comparator.compare(o1, o2)
java.lang.Comparable
o1.compareTo(o2)
两者怎么选择呢?
如果比较规则经常变化,可以写多个比较器,符合OCP原则
当比较规则只有一个不变化的时候,建议实现Comparable接口
这两者是有区别的
方法一:为自定义类实现Comparable接口
如果要改,改成下面这样:实现Comparable接口
class Customer implements Comparable<Customer>{
int age;
public Customer(int age);
@Override
public int compareTo(Customer c){
return this.age - c.age; //这样默认是升序
// return c.age - this.age; //这样是降序
}
}
另外, TreeSet / TreeMap 集合采用的是:中序遍历方式:左根右
方法二 单独编写比较器
自己创建一个比较器,然后在构造TreeSet的时候,把构造器传到构造函数里面
class MyComparator implements Comparator<MyPet>{
@Override
默认是升序,反过来就是降序
public int compare(MyPet o1, MyPet o2){
return o1.age - o2.age;
}
}
然后把比较器传给TreeSet
TreeSet<MyPet> pets = new TreeSet<MyPet>(new MyComparator());
或者用匿名内部类的方式,直接new接口,后面加大括号
TreeSet<MyPet> pets = new TreeSet<MyPet>(new Comparator<MyPet>(){
@Override
public int compare(MyPet o1, MyPet o2){
return o1.age - o2.age;
}
}
如果要对List集合中的元素排序,也是一个道理:要对集合中的元素实现 Comparable
接口