本文主要介绍TreeSet集合的基本使用方法
TreeSet之自然排序
返回0代表元素相同, 返回1代表不同
自然排序(元素具备比较性):让元素所属的类实现自然排序接口 Comparable
先看一个简单的例子,TreeSet集合,存入整数,进行排序
1import java.util.TreeSet;
2
3/*
4 * TreeSet:能够对元素按照某种规则进行排序。
5 * 排序有两种方式
6 * A:自然排序
7 * B:比较器排序
8 *
9 * TreeSet集合的特点:排序和唯一
10 *
11 * 通过观察TreeSet的add()方法,我们知道最终要看TreeMap的put()方法。
12 */
13public class TreeSetDemo {
14 public static void main(String[] args) {
15 // 创建集合对象
16 // 自然顺序进行排序
17 TreeSet ts = new TreeSet();
18
19 // 创建元素并添加
20 // 20,18,23,22,17,24,19,18,24
21 ts.add(20);
22 ts.add(18);
23 ts.add(23);
24 ts.add(22);
25 ts.add(17);
26 ts.add(24);
27 ts.add(19);
28 ts.add(18);
29 ts.add(24);
30
31 // 遍历
32 for (Integer i : ts) {
33 System.out.println(i);
34 }
35 }
36}
输出结果:
- 此处能够对整数进行排序,是因为Integer类实现了Comparable接口.
- Comparable接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。
再来看一个例子,在TreeSet中,存入学生对象的数据,并根据学生的年龄从小到大进行排序
- 创建一个学生类,实现自然排序Comparable接口,传入的泛型为Student
1/*
2 * 如果一个类的元素要想能够进行自然排序,就必须实现自然排序接口
3 */
4public class Student implements Comparable {
5 private String name;
6 private int age;
7
8 public Student() {
9 super();
10 }
11
12 public Student(String name, int age) {
13 super();
14 this.name = name;
15 this.age = age;
16 }
17
18 public String getName() {
19 return name;
20 }
21
22 public void setName(String name) {
23 this.name = name;
24 }
25
26 public int getAge() {
27 return age;
28 }
29
30 public void setAge(int age) {
31 this.age = age;
32 }
33
34 @Override
35 public int compareTo(Student s) {
36 // return 0;
37 // return 1;
38 // return -1;
39
40 // 这里返回什么,其实应该根据我的排序规则来做
41 // 按照年龄排序,主要条件
42 int num = this.age - s.age;
43 // 次要条件
44 // 年龄相同的时候,还得去看姓名是否也相同
45 // 如果年龄和姓名都相同,才是同一个元素
46 int num2 = num == 0 ? this.name.compareTo(s.name) : num;
47 return num2;
48 }
49}
- 编写测试类
1import java.util.TreeSet;
2
3/*
4 * TreeSet存储自定义对象并保证排序和唯一。
5 *
6 * A:你没有告诉我们怎么排序
7 * 自然排序,按照年龄从小到大排序
8 * B:元素什么情况算唯一你也没告诉我
9 * 成员变量值都相同即为同一个元素
10 */
11public class TreeSetDemo2 {
12 public static void main(String[] args) {
13 // 创建集合对象
14 TreeSet ts = new TreeSet();
15
16 // 创建元素
17 Student s1 = new Student("linqingxia", 27);
18 Student s2 = new Student("zhangguorong", 29);
19 Student s3 = new Student("wanglihong", 23);
20 Student s4 = new Student("linqingxia", 27);
21 Student s5 = new Student("liushishi", 22);
22 Student s6 = new Student("wuqilong", 40);
23 Student s7 = new Student("fengqingy", 22);
24
25 // 添加元素
26 ts.add(s1);
27 ts.add(s2);
28 ts.add(s3);
29 ts.add(s4);
30 ts.add(s5);
31 ts.add(s6);
32 ts.add(s7);
33
34 // 遍历
35 for (Student s : ts) {
36 System.out.println(s.getName() + "---" + s.getAge());
37 }
38 }
39}
运行结果:
- 可以看到,成功将学生的信息按照年龄从小到大输出了,并把重复的学生信息去除了
再更改需求添加学生数据,并根据学生的姓名长度,从小到大排序
- 创建一个学生类,实现自然排序Comparable接口,传入的泛型为Student,重写compareTo方法
1public class Student implements Comparable {
2 private String name;
3 private int age;
4
5 public Student() {
6 super();
7 }
8
9 public Student(String name, int age) {
10 super();
11 this.name = name;
12 this.age = age;
13 }
14
15 public String getName() {
16 return name;
17 }
18
19 public void setName(String name) {
20 this.name = name;
21 }
22
23 public int getAge() {
24 return age;
25 }
26
27 public void setAge(int age) {
28 this.age = age;
29 }
30
31 @Override
32 public int compareTo(Student s) {
33 // 主要条件 姓名的长度
34 int num = this.name.length() - s.name.length();
35 // 姓名的长度相同,不代表姓名的内容相同
36 int num2 = num == 0 ? this.name.compareTo(s.name) : num;
37 // 姓名的长度和内容相同,不代表年龄相同,所以还得继续判断年龄
38 int num3 = num2 == 0 ? this.age - s.age : num2;
39 return num3;
40 }
41}
- 编写测试类
1/*
2 * 需求:请按照姓名的长度排序
3 */
4public class TreeSetDemo {
5 public static void main(String[] args) {
6 // 创建集合对象
7 TreeSet ts = new TreeSet();
8
9 // 创建元素
10 Student s1 = new Student("linqingxia", 27);
11 Student s2 = new Student("zhangguorong", 29);
12 Student s3 = new Student("wanglihong", 23);
13 Student s4 = new Student("linqingxia", 27);
14 Student s5 = new Student("liushishi", 22);
15 Student s6 = new Student("wuqilong", 40);
16 Student s7 = new Student("fengqingy", 22);
17 Student s8 = new Student("linqingxia", 29);
18
19 // 添加元素
20 ts.add(s1);
21 ts.add(s2);
22 ts.add(s3);
23 ts.add(s4);
24 ts.add(s5);
25 ts.add(s6);
26 ts.add(s7);
27 ts.add(s8);
28
29 // 遍历
30 for (Student s : ts) {
31 System.out.println(s.getName() + "---" + s.getAge());
32 }
33 }
34}
运行结果:
- 可以看到,成功按照姓名的长度排序,由长到短输出了.
比较器排序(集合具备比较性):让集合的构造方法接收一个比较器接口的子类对象 Comparator
还是上一步的要求:添加学生数据,并根据学生的姓名长度,从小到大排序.改为比较器排序做.
- 创建学生类
1public class Student {
2 private String name;
3 private int age;
4
5 public Student() {
6 super();
7 }
8
9 public Student(String name, int age) {
10 super();
11 this.name = name;
12 this.age = age;
13 }
14
15 public String getName() {
16 return name;
17 }
18
19 public void setName(String name) {
20 this.name = name;
21 }
22
23 public int getAge() {
24 return age;
25 }
26
27 public void setAge(int age) {
28 this.age = age;
29 }
30}
- 创建一个比较器接口的子类对象
1import java.util.Comparator;
2
3public class MyComparator implements Comparator {
4
5 @Override
6 public int compare(Student s1, Student s2) {
7 // int num = this.name.length() - s.name.length();
8 // this -- s1
9 // s -- s2
10 // 姓名长度
11 int num = s1.getName().length() - s2.getName().length();
12 // 姓名内容
13 int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
14 // 年龄
15 int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
16 return num3;
17 }
18
19}
- 编写测试类
1import java.util.TreeSet;
2
3/*
4 * 需求:请按照姓名的长度排序
5 *
6 * TreeSet集合保证元素排序和唯一性的原理
7 * 唯一性:是根据比较的返回是否是0来决定。
8 * 排序:
9 * A:自然排序(元素具备比较性)
10 * 让元素所属的类实现自然排序接口 Comparable
11 * B:比较器排序(集合具备比较性)
12 * 让集合的构造方法接收一个比较器接口的子类对象 Comparator
13 */
14public class TreeSetDemo {
15 public static void main(String[] args) {
16 // 创建集合对象
17 //TreeSet ts = new TreeSet(); //自然排序
18 // public TreeSet(Comparator comparator) //比较器排序
19 TreeSet ts = new TreeSet(new MyComparator());
20
21
22
23 // 创建元素
24 Student s1 = new Student("linqingxia", 27);
25 Student s2 = new Student("zhangguorong", 29);
26 Student s3 = new Student("wanglihong", 23);
27 Student s4 = new Student("linqingxia", 27);
28 Student s5 = new Student("liushishi", 22);
29 Student s6 = new Student("wuqilong", 40);
30 Student s7 = new Student("fengqingy", 22);
31 Student s8 = new Student("linqingxia", 29);
32
33 // 添加元素
34 ts.add(s1);
35 ts.add(s2);
36 ts.add(s3);
37 ts.add(s4);
38 ts.add(s5);
39 ts.add(s6);
40 ts.add(s7);
41 ts.add(s8);
42
43 // 遍历
44 for (Student s : ts) {
45 System.out.println(s.getName() + "---" + s.getAge());
46 }
47 }
48}
-
运行结果:
-
成功按照名字长度排序输出
上题中,匿名内部类的写法:如果一个方法的参数是接口,那么真正要的是接口的实现类的对象,而匿名内部类就可以实现这个东西
1public class TreeSetDemo {
2 public static void main(String[] args) {
3
4 // 如果一个方法的参数是接口,那么真正要的是接口的实现类的对象
5 // 而匿名内部类就可以实现这个东西
6 TreeSet ts = new TreeSet(new Comparator() {
7 @Override
8 public int compare(Student s1, Student s2) {
9 // 姓名长度
10 int num = s1.getName().length() - s2.getName().length();
11 // 姓名内容
12 int num2 = num == 0 ? s1.getName().compareTo(s2.getName())
13 : num;
14 // 年龄
15 int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
16 return num3;
17 }
18 });
19
20 // 创建元素
21 Student s1 = new Student("linqingxia", 27);
22 Student s2 = new Student("zhangguorong", 29);
23 Student s3 = new Student("wanglihong", 23);
24 Student s4 = new Student("linqingxia", 27);
25 Student s5 = new Student("liushishi", 22);
26 Student s6 = new Student("wuqilong", 40);
27 Student s7 = new Student("fengqingy", 22);
28 Student s8 = new Student("linqingxia", 29);
29
30 // 添加元素
31 ts.add(s1);
32 ts.add(s2);
33 ts.add(s3);
34 ts.add(s4);
35 ts.add(s5);
36 ts.add(s6);
37 ts.add(s7);
38 ts.add(s8);
39
40 // 遍历
41 for (Student s : ts) {
42 System.out.println(s.getName() + "---" + s.getAge());
43 }
44 }
45}
-
运行结果:
-
可以看到,使用匿名内部类,可以同样按照姓名的长度输出,匿名内部类的写法看似复杂,但熟练之后,及其方便,不用新建一个类了.
键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台 分析: A:定义学生类 B:创建一个TreeSet集合 C:总分从高到底如何实现呢? D:键盘录入5个学生信息
E:遍历TreeSet集合
//创建学生类创建学生类
1public class Student { 2 // 姓名 3 private String name; 4 // 语文成绩 5 private int chinese; 6 // 数学成绩 7 private int math; 8 // 英语成绩 9 private int english; 10 11 public Student(String name, int chinese, int math, int english) { 12 super(); 13 this.name = name; 14 this.chinese = chinese; 15 this.math = math; 16 this.english = english; 17 } 18 19 public Student() { 20 super(); 21 } 22 23 public String getName() { 24 return name; 25 } 26 27 public void setName(String name) { 28 this.name = name; 29 } 30 31 public int getChinese() { 32 return chinese; 33 } 34 35 public void setChinese(int chinese) { 36 this.chinese = chinese; 37 } 38 39 public int getMath() { 40 return math; 41 } 42 43 public void setMath(int math) { 44 this.math = math; 45 } 46 47 public int getEnglish() { 48 return english; 49 } 50 51 public void setEnglish(int english) { 52 this.english = english; 53 } 54 55 public int getSum() { 56 return this.chinese + this.math + this.english; 57 } 58}
- 编写测试类,采用匿名内部类,实现Comparator的写法
1import java.util.Comparator;
2import java.util.Scanner;
3import java.util.TreeSet;
4
5public class TreeSetDemo {
6 public static void main(String[] args) {
7 // 创建一个TreeSet集合
8 TreeSet ts = new TreeSet(new Comparator() {
9 @Override
10 public int compare(Student s1, Student s2) {
11 // 总分从高到低
12 int num = s2.getSum() - s1.getSum();
13 // 总分相同的不一定语文相同
14 int num2 = num == 0 ? s1.getChinese() - s2.getChinese() : num;
15 // 总分相同的不一定数序相同
16 int num3 = num2 == 0 ? s1.getMath() - s2.getMath() : num2;
17 // 总分相同的不一定英语相同
18 int num4 = num3 == 0 ? s1.getEnglish() - s2.getEnglish() : num3;
19 // 姓名还不一定相同呢
20 int num5 = num4 == 0 ? s1.getName().compareTo(s2.getName())
21 : num4;
22 return num5;
23 }
24 });
25
26 System.out.println("学生信息录入开始");
27 // 键盘录入5个学生信息
28 for (int x = 1; x
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?