JAVA之旅(二十)—HashSet,自定义存储对象,TreeSet,二叉树,实现Comparator方式排序,TreeSet小练习
我们继续说一下集合框架
- Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复
Set集合的功能和Collection是一致的
我们重点关注的是子类对象
我们来聊聊
一.HashSet
HashSet底层结构是哈希表
什么是HashSet?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 1package com.lgl.hellojava;
2
3//公共的 类 类名
4public class HelloJJAVA {
5 public static void main(String[] args) {
6 Demo d1 = new Demo();
7 Demo d2 = new Demo();
8
9 sop(d1);
10 sop(d2);
11 }
12
13 // 输出
14 public static void sop(Object obj) {
15 System.out.println(obj);
16
17 }
18
19}
20
21class Demo {
22
23}
24
我们这样输出的结果就是哈希值
当然,我们是来介绍HashSet的,我们演示一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 1package com.lgl.hellojava;
2
3import java.util.HashSet;
4import java.util.Iterator;
5
6//公共的 类 类名
7public class HelloJJAVA {
8 public static void main(String[] args) {
9 HashSet h = new HashSet();
10 h.add("hello 01");
11 h.add("hello 02");
12 h.add("hello 03");
13 h.add("hello 04");
14
15 // set取出只有一种办法,迭代器
16 Iterator iterator = h.iterator();
17 while (iterator.hasNext()) {
18 sop(iterator.next());
19 }
20
21 }
22
23 // 输出
24 public static void sop(Object obj) {
25 System.out.println(obj);
26
27 }
28
29}
30
31
是不是很类似,但是输出,你们仔细看了
输出是无序的,我们还有一个现象,就是直接输出
1
2
3 1sop(h.add("lgl"));
2sop(h.add("lgl"));
3
相同的
因为他不能重复
二.自定义存储对象
我们可以存数据,那肯定可以自定义存储数据咯?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 1package com.lgl.hellojava;
2
3import java.util.HashSet;
4import java.util.Iterator;
5
6//公共的 类 类名
7public class HelloJJAVA {
8 public static void main(String[] args) {
9 HashSet h = new HashSet();
10 h.add(new Person("lgl1", 18));
11 h.add(new Person("lgl2", 19));
12 h.add(new Person("lgl3", 20));
13 h.add(new Person("lgl4", 21));
14
15 // set取出只有一种办法,迭代器
16 Iterator iterator = h.iterator();
17 while (iterator.hasNext()) {
18 Person p = (Person) iterator.next();
19 sop(p.getName() + ":" + p.getAge());
20 }
21
22 }
23
24 // 输出
25 public static void sop(Object obj) {
26 System.out.println(obj);
27
28 }
29
30}
31
32/**
33 * 存储对象
34 *
35 * @author LGL
36 *
37 */
38class Person {
39 private String name;
40 private int age;
41
42 public Person(String name, int age) {
43 this.setName(name);
44 this.setAge(age);
45 }
46
47 public String getName() {
48 return name;
49 }
50
51 public void setName(String name) {
52 this.name = name;
53 }
54
55 public int getAge() {
56 return age;
57 }
58
59 public void setAge(int age) {
60 this.age = age;
61 }
62}
63
64
这样就可以定下来了
-
HashSet是如何保证元素的唯一性呢?
-
是通过元素的两个方法,hasCode和equals来完成的
- 如果元素的hasCode相同。才会去判断equals是否为true
- 如果元素的hasCode不同。不会调用equals
这里要注意一点的就是,对于判断元素是否存在的话,以及删除的操作,依赖的方法就是元素的hasCode和equals
三.TreeSet
hashSet说完,我们再来看一下TreeSet,我们用小例子来说明
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 1package com.lgl.hellojava;
2
3import java.util.Iterator;
4import java.util.TreeSet;
5
6import org.omg.PortableInterceptor.Interceptor;
7
8//公共的 类 类名
9public class HelloJJAVA {
10 public static void main(String[] args) {
11 TreeSet s = new TreeSet();
12 s.add("abc");
13 s.add("acd");
14 s.add("age");
15 s.add("abf");
16
17 Iterator iterator = s.iterator();
18
19 while (iterator.hasNext()) {
20 sop(iterator.next());
21 }
22 }
23
24 // 输出
25 public static void sop(Object obj) {
26 System.out.println(obj);
27
28 }
29}
30
31
我们仔细看他的输出
他会排序,那我们就知道TreeSet的特性了
- 可以对Set集合中的元素进行排序
如果你用自定义对象去村粗的话,你会发现他可以存一个对象,但是不能存储多个对象,为什么?因为他会强制进行排序,如果是对象的话,他没法排序,是不行的
对了我们没有讲TreeSet的数据结构呢,他的数据结构是二叉树,这是一个比较难的概念了
四.二叉树
二叉树其实通俗一点,就是树形图数据,比如
就是比较,一直分支,很大的节约了计算方式,我们比较,大的话,开一个分支,小的话,再开一个分支,就这样一直比较!
那TreeSet保证元素唯一性的是compareTo方法return 0;
- TreeSet排序的第一种方式,让元素自身具备比较性,元素需要实现Comparable 接口,覆盖compareTo方法,这种也称为元素的自然顺序!
五.实现Comparator方式排序
当元素不具备比较性时,或者具备的元素的比较性不是所需要的,这时就需要让集合自身具备比较性,那就是在集合一初始化时就有了比较方式.这么说有点绕啊,我们还是用代码来说明吧,原理都是二叉树
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 1package com.lgl.hellojava;
2
3import java.util.Comparator;
4import java.util.Iterator;
5import java.util.TreeSet;
6
7//公共的 类 类名
8public class HelloJJAVA {
9 public static void main(String[] args) {
10 /**
11 * 当元素自身不具备比较性或者具备的比较性不是所需要的,这时需要让容器自生具备比较性,定义一个比较器,
12 * 将比较器对象作为参数传递给TreeSet集合的构造函数
13 */
14 TreeSet s = new TreeSet(new MyCompare());
15 s.add(new Student("lgl1", 22));
16 s.add(new Student("lgl2", 26));
17 s.add(new Student("lgl3", 10));
18 s.add(new Student("lgl4", 19));
19
20 Iterator iterator = s.iterator();
21 while (iterator.hasNext()) {
22 Student student = (Student) iterator.next();
23 sop(student.getName() + ":" + student.getAge());
24 }
25
26 }
27
28 // 输出
29 public static void sop(Object obj) {
30 System.out.println(obj);
31
32 }
33}
34
35class Student {
36 private String name;
37 private int age;
38
39 public Student(String name, int age) {
40 this.name = name;
41 this.age = age;
42 }
43
44 // 比较
45 public int compareTo(Object obj) {
46 if (!(obj instanceof Student)) {
47 throw new RuntimeException("不是学生对象");
48 }
49 Student s = (Student) obj;
50 if (this.age > s.age) {
51 return 1;
52 } else if (this.age == s.age) {
53 return this.name.compareTo(s.name);
54 }
55 return -1;
56 }
57
58 public String getName() {
59 return name;
60 }
61
62 public void setName(String name) {
63 this.name = name;
64 }
65
66 public int getAge() {
67 return age;
68 }
69
70 public void setAge(int age) {
71 this.age = age;
72 }
73
74}
75
76// 定义比较器
77class MyCompare implements Comparator {
78
79 public int compare(Object o1, Object o2) {
80 Student s1 = (Student) o1;
81 Student s2 = (Student) o2;
82
83 return s1.getName().compareTo(s2.getName());
84 }
85
86}
87
88
六.TreeSet小练习
我们到这里,就用一个小练习来结束吧,毕竟在后面就需要讲泛型了,我们的需求就是按照字符串長度排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 1package com.lgl.hellojava;
2
3import java.util.Comparator;
4import java.util.Iterator;
5import java.util.TreeSet;
6
7//公共的 类 类名
8public class HelloJJAVA {
9 public static void main(String[] args) {
10 /**
11 * 按照字符串長度排序
12 */
13 TreeSet s = new TreeSet(new StringLengthComparator());
14 s.add("ffffffff");
15 s.add("fffff");
16 s.add("ff");
17 s.add("ffffff");
18
19 Iterator iterator = s.iterator();
20 while (iterator.hasNext()) {
21 sop(iterator.next());
22 }
23
24 }
25
26 // 输出
27 public static void sop(Object obj) {
28 System.out.println(obj);
29
30 }
31}
32
33// 定义比较性
34class StringLengthComparator implements Comparator {
35
36 @Override
37 public int compare(Object o1, Object o2) {
38
39 String s1 = (String) o1;
40 String s2 = (String) o2;
41
42 if (s1.length() > s2.length())
43 return 1;
44 if (s1.length() == s2.length())
45 return 0;
46 return -1;
47
48 }
49
50}
51
52
这样就OK了,输出的结果
这样就O了,好的,但是我们重复元素也会被干掉的,这时候我们就要处理了
1
2
3
4
5
6
7
8
9
10
11
12
13
14 1 @Override
2 public int compare(Object o1, Object o2) {
3
4 String s1 = (String) o1;
5 String s2 = (String) o2;
6
7 int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
8 if (num == 0) {
9 return s1.compareTo(s2);
10 }
11 return -num;
12
13 }
14
到这里,就基本上都搞定了,我们的博文到这里也结束了,如果有机会