TreeSet的自然排序(Comparable)
重点知识:
- TreeSet中的加入的元素会自动进行排序
- TreeSet中只能加入同一个类类型创建出来的对象
- 因为我们的TreeSet中加入的元素会自动将进行排序,那么到底是如何进行排序的?
- 我们就是根据TreeSet集合中的元素的某个属性进行排序,这个时候如果集合中的元素是不同类型的对象,这个时候就可能一个对象有的属性而另一个对象没有,这个时候我们就要求TreeSet集合中的存储的元素要是同一个类型的对象
- 如果我们装入多个类的元素,编译器也不会出错,运行期会出现运行期异常(ClassCastException)类型转化异常
- TreeSet要比List查询速度更快
- 如果要创建一个由自定义对象构成的TreeSet集合,那么我们的自定义类中就要去实现Comparable接口,或者使用有参构造方法创建TreeSet集合,实参为Comparator接口实现类的对象,这个时候也就是使用Comparator比较器进行排序
什么是自然排序?
通过实现Comparable接口来进行排序就是自然排序
什么是选择排序
通过实现Comparator接口来进行排序就是选择排序
- 在这里我们先讲述TreeSet集合的自然排序
首先我们要知道我们的TreeSet存储的元素会自动进行排序
那么我们的TreeSet集合是如何进行排序的?
- 其实TreeSet集合之所以可以进行排序就是因为我们的TreeSet中装入的对象的模板类中实现了Comparable接口,或者实现了Comparable接口
- 如果TreeSet集合中添加的元素所在类没有进行实现我们的任何一种java比较器,那么这个时候如果我们要在这个TreeSet集合中去添加元素,这个时候就会抛出一个运行时异常(ClassCaseException),这个时候其实底层就是默认调用了这个添加元素类的compareTo()方法,这个时候我们底层存储元素时就将这些元素默认转型为了Object类型的,这个时候我们在TreeSet添加元素的时候我们的时候底层也是和使用了向下转型将我们的Object类型的元素转型为Comparable类型的对象,这个时候因为我们的实际的存储的对象的模板类没有实现Comparable接口,这个时候我们就会出现类型转换异常
如何实现自然排序?
- 这里我们说我们的自然排序就是实现Comparable接口的方式,只要我们让我们的TreeSet集合中装入的元素模板类实现Comparable接口,然后让我们的重写compareTo()方法就可以了
eg:这里我们举一个例子
- 这个例子中的Dog2类就是我们TreeSet集合中的元素,这个时候我们就让Dog2类实现Comparable接口并且实现compare()方法
package 集合.set;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet treeSet = new TreeSet();
treeSet.add(new Dog2("小黑",2));
treeSet.add(new Dog2("小白",2));
treeSet.add(new Dog2("小蓝",2));
treeSet.add(new Dog2("小绿",2));
treeSet.add(new Dog2("小紫",2));
}
}
/**
* 这里我们创建了一个Dog2类,让这个类实现了Comparable接口,然后重写了compareTo()方法,并且重写这个方法是
* 通过多级排序实现的,第一级是判断name属性的大小,第二级是判断age属性的大小
* 这个时候我们这个自定义类实现了Comparable接口,这个时候我们这个类创建的对象装入TreeSet中时就不会出现类
* 型转换异常
*/
class Dog2 implements Comparable{
private String name;
private int age;
public Dog2(){
}
public Dog2(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Object o) {
Dog2 d = (Dog2)o;
if(this.name.equals(d.name)){
return age - d.age;
}
return name.compareTo(d.name);
}
}
为什么这里我们比较时会抛出类型转换异常?
因为在底层是将我们的Object类型的引用(实际为自定义类类型)转型为Comparable类型,这个时候如果我们这个自定义类没有实现Comparable接口,自然就会出现类型转换异常
- 我们一般的自定义类型的数组和集合在底层都是以Object类型进行存储的
关于TreeSet中判断我们要存储的对象是否重复时:
我们这个时候不是通过equals()方法判断是否重复,也没有使用hashCode()方法进行判断
- 我们在TreeSet中是使用了Comparable接口中的compareTo()方法或者是使用的Comparator接口中的compare()方法判断的元素是否重复
- 当我们使用自然排序的方式时,这个时候我们就是通过Comparable接口中的compareTo()方进行判断,如果我们的compareTo()方法的返回值为0,这个时候就表示我们要添加的元素和这个TreeSet集合中的元素重复了
- 当我们使用定制排序时,这个时候我们就是通过Comparator接口中的compare()方法进行判断,如果这个时候我们的compare()方法的返回值为0,这个时候就表示我们要添加的元素和这个TreeSet集合中的元素重复了