java集合框架:Set集合
特点:
- 1 不能存储重复数据
- 2 没有索引,不能使用普通的for循环。 增强for和迭代器都可以
- 3 存取顺序不一致
treeset 自然排序
TreeSet<Integer> set = new TreeSet<>();
set.add(50);
set.add(30);
set.add(70);
set.add(60);
set.add(20);
set.add(100);
System.out.println(set);
结果:
[20, 30, 50, 60, 70, 100]
treeset 自然排序 (对象)
添加学生对象 报错 原因是学生类 没有实现Comparable接口
给学生实现Comparable接口
- 因为后面要比较的是学生对象,索引接口那里添加具体的泛型的类型为Student
- 这里重写的compareTo方法里,是按年龄排序,后续再解释原理
- - compareTo方法如果返回的是正数 新的数据会排到右侧
- - compareTo方法如果返回的是负数 新的数据会排到左侧
- - compareTo方法如果返回的是0 新的数据就不会被添加
返回正数,表明当前存入的值比老值大,应该排在右边
.......
需求 先按你年龄排序 如果年龄相等 按姓名排序
@Override
public int compareTo(Student o) {
int result = this.age - o.age;
//按照年龄从小到大排序 如果年龄相等 按照名字排序
return result == 0 ? this.name.compareTo(o.name) : result;
//return this.age - o.age;
//return o.age - this.age;
}
Comparator比较器方式排序
- 案例需求
- - - 两个集合,各存3个学生
- - - 一个集合按照年龄从小到大排序,另外一个按照年龄从大到小排序
- 实现步骤
- - - 创建TreeSet集合对象时利用构造方法传入比较器对象。
- - - 比较器对象以匿名内部类或者lambda表达式的形式传入,重写compare(T o1,T o2)方法,集合就会按照compare方法的规则排序
- - - 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
Student类代码
public class Student implements Comparable<Student>{
String name;
int age;
...........................................
@Override
public String toString() {
return "{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
return 0;
}
}
测试类代码:
-
-
注意set2中的lambda方式,由于存在泛型,所以添加
(Comparator<Student>)
public static void main(String[] args) {
//按照年龄从小到大排
TreeSet<Student> ts01 = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.age - o2.age;
}
});
ts01.add(new Student("zs", 24));
ts01.add(new Student("xiaom", 30));
ts01.add(new Student("lisi", 19));
ts01.add(new Student("daming", 50));
ts01.add(new Student("wangwu", 25));
ts01.add(new Student("hehe", 30));
ts01.add(new Student("daming", 50));
System.out.println(ts01);
//按照年龄从大到小排
TreeSet<Student> ts02 = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o2.age - o1.age;
}
});
ts02.add(new Student("zs", 24));
ts02.add(new Student("xiaom", 30));
ts02.add(new Student("lisi", 19));
ts02.add(new Student("daming", 50));
ts02.add(new Student("wangwu", 25));
ts02.add(new Student("hehe", 30));
ts02.add(new Student("daming", 50));
System.out.println(ts02);
}
lambda实现
//按照年龄从小到大排
TreeSet<Student> ts01 = new TreeSet<>((o1, o2) -> o1.age - o2.age);
ts01.add(new Student("zs", 24));
ts01.add(new Student("xiaom", 30));
ts01.add(new Student("lisi", 19));
ts01.add(new Student("daming", 50));
ts01.add(new Student("wangwu", 25));
ts01.add(new Student("hehe", 30));
ts01.add(new Student("daming", 50));
System.out.println(ts01);
//按照年龄从大到小排
TreeSet<Student> ts02 = new TreeSet<>((o1, o2) -> o2.age - o1.age);
ts02.add(new Student("zs", 24));
ts02.add(new Student("xiaom", 30));
ts02.add(new Student("lisi", 19));
ts02.add(new Student("daming", 50));
ts02.add(new Student("wangwu", 25));
ts02.add(new Student("hehe", 30));
ts02.add(new Student("daming", 50));
System.out.println(ts02);
两种比较方式总结
-
-
自然排序: 需要比较的对象的类要实现Comparable接口,重写compareTo方法,根据返回值进行排序
-
比较器排序: 创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方法,根据返回值进行排序
-
在使用的时候,默认使用自然排序,当自然排序不满足现在的需求时,必须使用比较器排序
-
-
两种方式中关于返回值的规则
-
-
如果返回值为0,表示当前存入的元素跟集合中元素重复了,不存
-
如果返回值为正数,表示当前存入的元素是较大值,存右边
-