TreeSet集合
目录
TreeSet集合
自然排序:Comparable接口的使用
案例分析
总结
比较器排序Comparator的使用
两种方法比较
public class TreeSetextends AbstractSet implements NavigableSet , Cloneable, Serializable
-
元素有序,但这里的顺序不是元素的存储与取出顺序,而是按照一定规则进行的排序,具体排序方式取决于构造方法 :TreeSet() : 无参构造,根据其元素的自然排序进行排序
TreeSet(Comparator comparator) : 根据指定的比较器进行排序
-
没有带索引的方法,所以不能使用普通for循环
-
是Set集合,所以不包含重复元素
import java.util.TreeSet;
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet ts = new TreeSet(); //<>中不能为基本数据类型
ts.add(10);
ts.add(40);
ts.add(60);
ts.add(20);
ts.add(20);
for(Integer i : ts){
System.out.println(i);
}
}
}
// 自然排序
10
20
40
60
自然排序:Comparable接口的使用
-
该接口对实现它的每个类的对象强加一个整体排序。 这个排序被称为类的自然排序 ,类的compareTo方法被称为其自然比较方法
该接口对实现它的每个类的对象强加一个整体排序。 这个排序被称为类的自然排序 ,类的compareTo方法被称为其自然比较方法
只有唯一方法:
int compareTo(T o) 将此对象与指定的对象进行比较以进行排序。 返回一个负整数,零或正整数,因为该对象小于,等于或大于指定对象。
案例分析
问题
//学生类,没有实现Comparable接口
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//demo,运行会报错
//未覆盖java.lang.Comparable中的抽象方法compareTo(com.Set.TreeSetD.Student)
import java.util.TreeSet;
public class demo {
public static void main(String[] args) {
TreeSet ts = new TreeSet();
Student s1 = new Student("林青霞",33);
Student s2 = new Student("张曼玉",23);
Student s3 = new Student("眼红和",14);
Student s4 = new Student("金城武",32);
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
for(Student s : ts){
System.out.println(s.getName()+","+s.getAge());
}
}
}
解决方法
-
让学生类实现Comparable接口
-
让学生类重写CompareTo方法
public class Student implements Comparable{ ... @Override public int compareTo(Student s) { return 0; } }
执行dome类结果是:
林青霞,33 //只有一个元素,原因是在重写后默认比较规则中,返回值是0,是0则认为添加来的元素跟比较的是一样的
返回值改为恒正数
再次重写
public class Student implements Comparable{ ... @Override public int compareTo(Student s) { return 1; } }
执行dome类结果是:
林青霞,33 张曼玉,23 眼红和,14 金城武,32 //跟存入顺序相同
返回值改为恒负数
再次重写
public class Student implements Comparable{ ... @Override public int compareTo(Student s) { return -1; } }
执行dome类结果是:
金城武,32 眼红和,14 张曼玉,23 林青霞,33 //跟存入顺序相反
按需求改写为 按年龄排序
再次重写
public class Student implements Comparable{ ... @Override public int compareTo(Student s) { return this.getAge()-s.getAge(); } }
执行dome类结果是:
眼红和,14 张曼玉,23 金城武,32 林青霞,33 //跟年龄大小顺序保持一致
bug
import java.util.TreeSet;
public class demo {
public static void main(String[] args) {
TreeSet ts = new TreeSet();
Student s1 = new Student("林青霞",33);
Student s2 = new Student("张曼玉",23);
Student s3 = new Student("眼红和",14);
Student s4 = new Student("金城武",32);
Student s5 = new Student("胡一菲",32);
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
for(Student s : ts){
System.out.println(s.getName()+","+s.getAge());
}
}
}
//
Student s4 = new Student("金城武",32);
Student s5 = new Student("胡一菲",32);
年龄相同则认为他们俩为同一个对象,就不存入此集合
解决办法:
@Override
public int compareTo(Student s) {
int num = this.age-s.age;
int num2 = num == 0 ? this.name.compareTo(s.name):num;
//String类可以直接使用该方法,因为String类实现了Comparable接口并且重写了该方法
return num2;
}
执行dome类结果是:
眼红和,14 张曼玉,23 胡一菲,32 金城武,32 林青霞,33
总结
-
用TreeSet集合存储自定义对象,无参构造方法使用自然排序会报错
-
自然排序,就是让所属的类实现Comparable接口,重写CompareTo()方法
-
重写方法时,一定要注意排序规则必须按照要求的主要次要条件进行
比较器排序Comparator的使用
public static void main(String[] args) {
TreeSet ts = new TreeSet(new Comparator() { //匿名内部类
@Override
public int compare(Student o1, Student o2) { //在Comparator中重写compare方法
int num = o1.getAge()- o2.getAge();
int num2 = num == 0 ? o1.getName().compareTo(o2.getName()):num;
return num2;
}
});
Student s1 = new Student("林青霞",33);
Student s2 = new Student("张曼玉",23);
Student s3 = new Student("眼红和",14);
Student s4 = new Student("金城武",32);
Student s5 = new Student("胡一菲",32);
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
for(Student s : ts){
System.out.println(s.getName()+","+s.getAge());
}
}
//
眼红和,14
张曼玉,23
胡一菲,32
金城武,32
林青霞,33
两种方法比较
用TreeSet集合存储自定义对象,无参构造方法使用自然排序会报错
自然排序,就是让所属的类实现Comparable接口,重写CompareTo()方法
重写方法时,一定要注意排序规则必须按照要求的主要次要条件进行
public static void main(String[] args) {
TreeSet ts = new TreeSet(new Comparator() { //匿名内部类
@Override
public int compare(Student o1, Student o2) { //在Comparator中重写compare方法
int num = o1.getAge()- o2.getAge();
int num2 = num == 0 ? o1.getName().compareTo(o2.getName()):num;
return num2;
}
});
Student s1 = new Student("林青霞",33);
Student s2 = new Student("张曼玉",23);
Student s3 = new Student("眼红和",14);
Student s4 = new Student("金城武",32);
Student s5 = new Student("胡一菲",32);
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
for(Student s : ts){
System.out.println(s.getName()+","+s.getAge());
}
}
//
眼红和,14
张曼玉,23
胡一菲,32
金城武,32
林青霞,33
两种方法比较
| 自然排序 | 比较器排序 | |
|---|---|---|
| 使用的接口或者类 | Comparable接口 | Comparator类(可实例化) |
| 使用方法 | 在TreeSet的无参构造中使用 | 在TreeSet的有参构造中使用(匿名内部类) |
| 重写的内容以及位置 | 在Student(元素类型类)中实现Comparable接口并重写CompareTo方法 | 直接在构造器的匿名内部类中重写Compare方法 |
使用TreeSet集合最需要注意的就是:
- 次要条件的分析



