TreeSet相对于HashSet来说它不仅元素不可重复,而且它还具备比较性(可自己定义),是按特定顺序存入元素的,相对于HashSet复杂一点。
TreeSet:
(1)可以对Set集合中的元素进行排序。
(2)底层数据结构是二叉树。
(3)保证元素的唯一性的依据:compareTo方法return 0。
可以看出因为TreeSet存入元素是按特定顺序存入元素,所以学习TreeSet也主要学习它是如何规定存入元素在集合中的顺序的。
TreeSet具有两种给存入元素排序的方法:
第一种:
让元素具备比较性。
元素需要实现Compareble接口,覆盖compareTo方法。
这种方式也称为元素的自然顺序,或者叫默认顺序。
第二种:
当元素不具备比较性时,或者具备的比较性不是所需要的。
这时就需要让集合自身具备比较性(创建一个比较器)。实现Comparator接口覆盖compare()方法。
在集合初始化时,就有了比较方式。
既然有两种排序但是如果两种排序同时存在时,我们以比较器即第二种排序方式为主。
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Object> ts = new TreeSet<Object>(new Mycompare());//添加了比较器
ts.add(new Person("L01", 18));
ts.add(new Person("L02", 19));
ts.add(new Person("L003", 20));// 存入一个姓名比较特别的,判断是否是按第二种排序方式为主
ts.add(new Person("L04", 21));
ts.add(new Person("L02", 17));// 存入一个名字相同,年龄不同的人
Iterator<Object> it = ts.iterator();
while (it.hasNext()) {// 通过迭代器将所有人的姓名和年龄输出
Person stu = (Person) it.next();
System.out.println("姓名:" + stu.getName() + ",年龄:" + stu.getAge());
}
}
}
// 第一种排序实现Compareble接口,覆盖compareTo方法。按年龄排序
class Person implements Comparable<Object> {
private String name;
private int age;
public Person(String name, int age) {
this.age = age;
this.name = name;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
// compareTo() 返回1是大于,0是等于,-1是小于。
@Override
public int compareTo(Object obj) {
if (!(obj instanceof Person)) {
throw new RuntimeException("不是人類对象");
}
Person p = (Person) obj;
System.out.println(this.name + "...compareto..." + p.name);
if (this.age > p.age)
return 1;
if (this.age == p.age)// 年龄相同时判断第二条件姓名
return this.name.compareTo(p.name);
return -1;
}
}
// 第二种排序方式,集合自身具备比较性(比较器),这里是按姓名排序
class Mycompare implements Comparator<Object> {
@Override
public int compare(Object o1, Object o2) {// 返回1是大于,0是等于,-1是小于。
Person p1 = (Person) o1;
Person p2 = (Person) o2;
int num = p1.getName().compareTo(p2.getName());
if (num == 0) {// 姓名相同时判断第二条件年龄
if (p1.getAge() > p2.getAge())
return 1;
if (p1.getAge() > p2.getAge())
return 0;
return -1;
}
return num;
}
}
只存在第一种排序方式输出的结果(不添加比较器):
存在二种排序方式输出的结果(添加比较器):
从输出结果可以看出当两种比较器同时存在时,输出的结果会以比较器的排序方式经行输出,即定义一个比较器实现Comparator接口覆盖compare()方法的方式。
切记无论是哪种方式,当主要条件相同时。一定判断次要条件。