①TreeSet集合的概述和特点
特点:
若想使用TreeSet,需要指定排序规则
1、不包含重复元素
2、没有带索引的方法
3、可以将元素按照规则进行排序
如何指定排序规则:
①自然排序Comparable的使用
- 使用空参构造创建TreeSet集合
- 自定义的Student类实现Comparale接口
- 重写里面的comparaTo()方法
(comparaTo()方法见Java compareTo() 方法 | 菜鸟教程 (runoob.com))
public class Student implements Comparable<Student>{
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
int result = this.age - o.age;
return result;
}
}
TreeSet<String> ts = new TreeSet<>();
TreeSet<Integer> ts2 = new TreeSet<>();
TreeSet<Student> ts3 = new TreeSet<>();
Student s1 = new Student("小龙",23);
Student s2 = new Student("小带",26);
Student s3 = new Student("小则",21);
ts.add("c");
ts.add("a");
ts.add("b");
ts2.add(2);
ts2.add(3);
ts2.add(1);
ts2.add(4);
ts3.add(s1);
ts3.add(s2);
ts3.add(s3);
System.out.println(ts);
System.out.println("--------------------------------");
System.out.println(ts2);
System.out.println("--------------------------------");
//无法按照规则进行排序故报错ClassCastException,需要用StudentComparable
System.out.println(ts3);
运行结果:
自然排序简单原理图
- 如果返回值为负数,存左边
- 如果返回值为0,表示当前存入元素和集合中的元素重复了,不存
- 如果返回值为整数,存右边
练习:要求如果存入的两个年龄相同,就按照姓名的首字母进行排序
//字符串的compareTo()会用ASCII码表里字符的数字顺序进行相减从而得到一个对应的值进行排序,排序规则如上述。
result = result == 0 ? this.name.compareTo(student2.getName()) : result;
②比较器排序Comparator的使用
- TreeSet的代参构造方法使用的是比较器排序对元素进行排序的
- 比较器排序,就是让集合构造方法接受Comparator的实现类对象,重写compara(T o,T o2)方法
- 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
主要代码:
TreeSet<Teacher> ts = new TreeSet<>(new Comparator<Teacher>() {
@Override
public int compare(Teacher t1, Teacher t2) {
//t1表示要存入的元素
//t2表示已经存入的元素
int result = t1.getAge() - t2.getAge();//主要条件
result = result == 0 ? t1.getName().compareTo(t2.getName()) : result ;//次要条件
return result;
}
});
Teacher t1 = new Teacher("zs",23);
Teacher t2 = new Teacher("ls",21);
Teacher t3 = new Teacher("ww",27);
Teacher t4 = new Teacher("zl",18);
ts.add(t1);
ts.add(t2);
ts.add(t3);
ts.add(t4);
System.out.println(ts);
两种方式比较:
- 自然排序:自定义类实现Comparable接口,重写comparaTo方法,根据返回值排序
- 比较器排序:创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方法,根据返回值排序。(不需要实现接口)
- 在使用的时候,默认使用自然排序,当自然排序不满足现在的需求时使用比较器排序。
- 两种方式关于返回值的规则一致
分清两者的使用场景:
String,Integer等类已经实现了Comparable接口,默认用码表进行排序。
例如:
在TreeSet集合中添加字符型String的三个元素(“asd”,“xcv“,”cswweee”)
String源码中已默认实现接口,故排序规则为(“ad”,”cswweee”,“xcv“)
若要求以字符串的长度进行排序,因源码无法进行修改(String是在源码中实现的Comparable接口),故无法使用自然排序,只能选择比较器排序。
源码如下
TreeSet<String> ts = new TreeSet<>();
ts.add("asd");
ts.add("xcv");
ts.add("cswweee");
System.out.println(ts);
结果为:[asd, cswweee, xcv]
TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
@Override
public int compare(String s, String t1) {
int result = s.length() - t1.length();
result = result == 0 ? s.compareTo(t1) : result;
return result;
}
});
ts.add("asd");
ts.add("xcv");
ts.add("cswweee");
System.out.println(ts);
结果:[asd, xcv, cswweee]
练习:尝试使用Lambda表达式进行操作上述内容。