TreeSet/TreeMap 是自平衡二叉树,其迭代器采用的是中序遍历方式。
无序、不可重复,但是可排序:
TreeSet/TreeMap中key 可以⾃动对 String 类型或8⼤基本类型的包装类型进⾏排序
TreeSet ⽆法直接对⾃定义类型进⾏排序
排序规则
直接将⾃定义类型添加到 TreeSet/TreeMap中key 会报错 java.lang.ClassCastException
原因: 是因为⾃定义没有实现 java.lang.Comparable 接口(此时,使⽤的是 TreeSet 的⽆
参构造器)
对 TreeSet/TreeMap 中 key部分元素,必须要指定排序规则。主要有两种解决⽅案:
⽅法⼀: 放在集合中的⾃定义类型实现 java.lang.Comparable 接⼜,并重写 compareTo ⽅法
⽅法⼆: 选择 TreeSet/TreeMap 带⽐较器参数的构造器 ,并从写⽐较器中的 compare ⽅法
此时,在传递⽐较器参数给 TreeSet/TreeMap 构造器时,有 3 种⽅法:
1. 定义⼀个 Comparator 接口的实现类
2. 使⽤匿名内部类
3. lambda 表达式(Comparator 是函数式接口)
利⽤ -> 的 lambda表达式 重写 compare ⽅法
利⽤ Comparator.comparing ⽅法
两种解决⽅案如何选择呢?
1. 当⽐较规则不会发⽣改变的时候,或者说⽐较规则只有⼀个的时候,建议实现Comparable 接口
2. 当⽐较规有多个,并且需要在多个⽐较规则之间频繁切换时,建议使⽤Comparator 接口
方法一的实现案例:
//liyong TreeSet对自定义类型进行排序
public class Person implements Comparable<Person> {
int age;
public Person(int age) {
this.age = age;
}
@Override
public int compareTo(Person o) {
return this.age - o.age;
}
}
public void main(String[] args) {
Set<Person> persons = new TreeSet<>();
persons.add(new Person(1));
persons.add(new Person(25));
persons.add(new Person(10));
persons.add(new Person(8));
}
方法2的实现案例
static class Cat{
int age;
public Cat(int age) {
this.age = age;
}
public static void main(String[] args) {
//1、使用接口实现类
//Set<Cat> set = new TreeSet<>(new MyCmp()); //产地一个比较器对象给TreeSet构造器
//2、使用匿名内部类
Set<Cat> set = new TreeSet<>(new Comparator<Cat>() {
@Override
public int compare(Cat o1, Cat o2) {
return o1.age - o2.age;
}
});
//3、使用lambda表达式,传递一个比较器对象
//Set<Cat> set = new TreeSet<>((o1, o2) -> o1.age- o2.age);
set.add(new Cat(1));
set.add(new Cat(10));
set.add(new Cat(8));
}
//创建一个比较器类
class MyCmp implements Comparator<Cat>{
@Override
public int compare(Cat o1, Cat o2) {
return o1.age-o2.age;
}
}
}