1.红黑树
1.1概述【理解】
-
红黑树的特点
平衡二叉B树
每一个节点可以是红或者黑
红黑树不是高度平衡的,它的平衡是通过"自己的红黑规则"进行实现的
-
红黑树的红黑规则有哪些
每一个节点或是红色的,或者是黑色的
根节点必须是黑色
如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,每个叶节点(Nil)是黑色的
如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个红色节点相连 的情况)
-
对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点
-
红黑树添加节点的默认颜色
-
添加节点时,默认为红色,效率高
-
-
红黑树添加节点后如何保持红黑规则
-
根节点位置
直接变为黑色
-
非根节点位置
-
父节点为黑色
不需要任何操作,默认红色即可
-
父节点为红色
-
叔叔节点为红色
将"父节点"设为黑色,将"叔叔节点"设为黑色
将"祖父节点"设为红色
如果"祖父节点"为根节点,则将根节点再次变成黑色
-
叔叔节点为黑色
将"父节点"设为黑色
将"祖父节点"设为红色
以"祖父节点"为支点进行旋转
-
-
-
1.2成绩排序案例【应用】
-
案例需求
用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩,英语成绩),并遍历该集合
要求: 按照总分从高到低出现
-
代码实现
学生类
1 public class Student implements Comparable<Student> {
2 private String name;
3 private int chinese;
4 private int math;
5 private int english;
6
7 public Student() {
8 }
9
10 public Student(String name, int chinese, int math, int english) {
11 this.name = name;
12 this.chinese = chinese;
13 this.math = math;
14 this.english = english;
15 }
16
17 public String getName() {
18 return name;
19 }
20
21 public void setName(String name) {
22 this.name = name;
23 }
24
25 public int getChinese() {
26 return chinese;
27 }
28
29 public void setChinese(int chinese) {
30 this.chinese = chinese;
31 }
32
33 public int getMath() {
34 return math;
35 }
36
37 public void setMath(int math) {
38 this.math = math;
39 }
40
41 public int getEnglish() {
42 return english;
43 }
44
45 public void setEnglish(int english) {
46 this.english = english;
47 }
48
49 public int getSum() {
50 return this.chinese + this.math + this.english;
51 }
52
53 @Override
54 public int compareTo(Student o) {
55 // 主要条件: 按照总分进行排序
56 int result = o.getSum() - this.getSum();
57 // 次要条件: 如果总分一样,就按照语文成绩排序
58 result = result == 0 ? o.getChinese() - this.getChinese() : result;
59 // 如果语文成绩也一样,就按照数学成绩排序
60 result = result == 0 ? o.getMath() - this.getMath() : result;
61 // 如果总分一样,各科成绩也都一样,就按照姓名排序
62 result = result == 0 ? o.getName().compareTo(this.getName()) : result;
63 return result;
64 }
65 }测试类
1 public class TreeSetDemo {
2 public static void main(String[] args) {
3 //创建TreeSet集合对象,通过比较器排序进行排序
4 TreeSet<Student> ts = new TreeSet<Student>();
5 //创建学生对象
6 Student s1 = new Student("jack", 98, 100, 95);
7 Student s2 = new Student("rose", 95, 95, 95);
8 Student s3 = new Student("sam", 100, 93, 98);
9 //把学生对象添加到集合
10 ts.add(s1);
11 ts.add(s2);
12 ts.add(s3);
13
14 //遍历集合
15 for (Student s : ts) {
16 System.out.println(s.getName() + "," + s.getChinese() + "," + s.getMath() + "," + s.getEnglish() + "," + s.getSum());
17 }
18 }
19 }
2.HashSet集合
2.1HashSet集合概述和特点【应用】
底层数据结构是哈希表
存取无序
不可以存储重复元素
没有索引,不能使用普通for循环遍历
2.2HashSet集合的基本应用【应用】
存储字符串并遍历
1 public class HashSetDemo {
2 public static void main(String[] args) {
3 //创建集合对象
4 HashSet<String> set = new HashSet<String>();
5
6 //添加元素
7 set.add("hello");
8 set.add("world");
9 set.add("java");
10 //不包含重复元素的集合
11 set.add("world");
12
13 //遍历
14 for(String s : set) {
15 System.out.println(s);
16 }
17 }
18 }
2.3哈希值【理解】
-
哈希值简介
是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
-
如何获取哈希值
Object类中的public int hashCode():返回对象的哈希码值
-
哈希值的特点
同一个对象多次调用hashCode()方法返回的哈希值是相同的
默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同
2.4哈希表结构【理解】
-
JDK1.8以前
数组 + 链表
-
JDK1.8以后
-
节点个数少于等于8个
数组 + 链表
-
节点个数多于8个
数组 + 红黑树
-
2.5HashSet集合存储学生对象并遍历【应用】
-
案例需求
创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合
要求:学生对象的成员变量值相同,我们就认为是同一个对象
-
代码实现
学生类
1 public class Student {
2 private String name;
3 private int age;
4
5 public Student() {
6 }
7
8 public Student(String name, int age) {
9 this.name = name;
10 this.age = age;
11 }
12
13 public String getName() {
14 return name;
15 }
16
17 public void setName(String name) {
18 this.name = name;
19 }
20
21 public int getAge() {
22 return age;
23 }
24
25 public void setAge(int age) {
26 this.age = age;
27 }
28
29 @Override
30 public boolean equals(Object o) {
31 if (this == o) return true;
32 if (o == null || getClass() != o.getClass()) return false;
33
34 Student student = (Student) o;
35
36 if (age != student.age) return false;
37 return name != null ? name.equals(student.name) : student.name == null;
38 }
39
40 @Override
41 public int hashCode() {
42 int result = name != null ? name.hashCode() : 0;
43 result = 31 * result + age;
44 return result;
45 }
46 }测试类
1 public class HashSetDemo02 {
2 public static void main(String[] args) {
3 //创建HashSet集合对象
4 HashSet<Student> hs = new HashSet<Student>();
5
6 //创建学生对象
7 Student s1 = new Student("林青霞", 30);
8 Student s2 = new Student("张曼玉", 35);
9 Student s3 = new Student("王祖贤", 33);
10
11 Student s4 = new Student("王祖贤", 33);
12
13 //把学生添加到集合
14 hs.add(s1);
15 hs.add(s2);
16 hs.add(s3);
17 hs.add(s4);
18
19 //遍历集合(增强for)
20 for (Student s : hs) {
21 System.out.println(s.getName() + "," + s.getAge());
22 }
23 }
24 } -
总结
HashSet集合存储自定义类型元素,要想实现元素的唯一,要求必须重写hashCode方法和equals方法
3.Map集合
3.1Map集合概述和特点【理解】
-
Map集合概述
interface Map<K,V> K:键的类型;V:值的类型
-
Map集合的特点
双列集合,一个键对应一个值
键不可以重复,值可以重复
-
Map集合的基本使用
1 public class MapDemo01 {
2 public static void main(String[] args) {
3 //创建集合对象
4 Map<String,String> map = new HashMap<String,String>();
5
6 //V put(K key, V value) 将指定的值与该映射中的指定键相关联
7 map.put("itheima001","林青霞");
8 map.put("itheima002","张曼玉");
9 map.put("itheima003","王祖贤");
10 map.put("itheima003","柳岩");
11
12 //输出集合对象
13 System.out.println(map);
14 }
15 }
3.2Map集合的基本功能【应用】
-
方法介绍
方法名 说明 V put(K key,V value) 添加元素 V remove(Object key) 根据键删除键值对元素 void clear() 移除所有的键值对元素 boolean containsKey(Object key) 判断集合是否包含指定的键 boolean containsValue(Object value) 判断集合是否包含指定的值 boolean isEmpty() 判断集合是否为空 int size() 集合的长度,也就是集合中键值对的个数 -
示例代码
1 public class MapDemo02 {
2 public static void main(String[] args) {
3 //创建集合对象
4 Map<String,String> map = new HashMap<String,String>();
5
6 //V put(K key,V value):添加元素
7 map.put("张无忌","赵敏");
8 map.put("郭靖","黄蓉");
9 map.put("杨过","小龙女");
10
11 //V remove(Object key):根据键删除键值对元素
12 // System.out.println(map.remove("郭靖"));
13 // System.out.println(map.remove("郭襄"));
14
15 //void clear():移除所有的键值对元素
16 // map.clear();
17
18 //boolean containsKey(Object key):判断集合是否包含指定的键
19 // System.out.println(map.containsKey("郭靖"));
20 // System.out.println(map.containsKey("郭襄"));
21
22 //boolean isEmpty():判断集合是否为空
23 // System.out.println(map.isEmpty());
24
25 //int size():集合的长度,也就是集合中键值对的个数
26 System.out.println(map.size());
27
28 //输出集合对象
29 System.out.println(map);
30 }
31 }
3.3Map集合的获取功能【应用】
-
方法介绍
方法名 说明 V get(Object key) 根据键获取值 Set<K> keySet() 获取所有键的集合 Collection<V> values() 获取所有值的集合 Set<Map.Entry<K,V>> entrySet() 获取所有键值对对象的集合 -
示例代码
1 public class MapDemo03 {
2 public static void main(String[] args) {
3 //创建集合对象
4 Map<String, String> map = new HashMap<String, String>();
5
6 //添加元素
7 map.put("张无忌", "赵敏");
8 map.put("郭靖", "黄蓉");
9 map.put("杨过", "小龙女");
10
11 //V get(Object key):根据键获取值
12 // System.out.println(map.get("张无忌"));
13 // System.out.println(map.get("张三丰"));
14
15 //Set<K> keySet():获取所有键的集合
16 // Set<String> keySet = map.keySet();
17 // for(String key : keySet) {
18 // System.out.println(key);
19 // }
20
21 //Collection<V> values():获取所有值的集合
22 Collection<String> values = map.values();
23 for(String value : values) {
24 System.out.println(value);
25 }
26 }
27 }
3.4Map集合的遍历(方式1)【应用】
-
遍历思路
-
我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
把所有的丈夫给集中起来
遍历丈夫的集合,获取到每一个丈夫
根据丈夫去找对应的妻子
-
-
步骤分析
获取所有键的集合。用keySet()方法实现
遍历键的集合,获取到每一个键。用增强for实现
根据键去找值。用get(Object key)方法实现
-
代码实现
1 public class MapDemo01 {
2 public static void main(String[] args) {
3 //创建集合对象
4 Map<String, String> map = new HashMap<String, String>();
5
6 //添加元素
7 map.put("张无忌", "赵敏");
8 map.put("郭靖", "黄蓉");
9 map.put("杨过", "小龙女");
10
11 //获取所有键的集合。用keySet()方法实现
12 Set<String> keySet = map.keySet();
13 //遍历键的集合,获取到每一个键。用增强for实现
14 for (String key : keySet) {
15 //根据键去找值。用get(Object key)方法实现
16 String value = map.get(key);
17 System.out.println(key + "," + value);
18 }
19 }
20 }
3.5Map集合的遍历(方式2)【应用】
-
遍历思路
-
我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
获取所有结婚证的集合
遍历结婚证的集合,得到每一个结婚证
根据结婚证获取丈夫和妻子
-
-
步骤分析
-
获取所有键值对对象的集合
Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
-
遍历键值对对象的集合,得到每一个键值对对象
用增强for实现,得到每一个Map.Entry
-
根据键值对对象获取键和值
用getKey()得到键
用getValue()得到值
-
-
代码实现
1 public class MapDemo02 {
2 public static void main(String[] args) {
3 //创建集合对象
4 Map<String, String> map = new HashMap<String, String>();
5
6 //添加元素
7 map.put("张无忌", "赵敏");
8 map.put("郭靖", "黄蓉");
9 map.put("杨过", "小龙女");
10
11 //获取所有键值对对象的集合
12 Set<Map.Entry<String, String>> entrySet = map.entrySet();
13 //遍历键值对对象的集合,得到每一个键值对对象
14 for (Map.Entry<String, String> me : entrySet) {
15 //根据键值对对象获取键和值
16 String key = me.getKey();
17 String value = me.getValue();
18 System.out.println(key + "," + value);
19 }
20 }
21 }
4.HashMap集合
4.1HashMap集合概述和特点【理解】
HashMap底层是哈希表结构的
依赖hashCode方法和equals方法保证键的唯一
如果键要存储的是自定义对象,需要重写hashCode和equals方法
4.2HashMap集合应用案例【应用】
-
案例需求
创建一个HashMap集合,键是学生对象(Student),值是居住地 (String)。存储多个元素,并遍历。
要求保证键的唯一性:如果学生对象的成员变量值相同,我们就认为是同一个对象
-
代码实现
学生类
1 public class Student {
2 private String name;
3 private int age;
4
5 public Student() {
6 }
7
8 public Student(String name, int age) {
9 this.name = name;
10 this.age = age;
11 }
12
13 public String getName() {
14 return name;
15 }
16
17 public void setName(String name) {
18 this.name = name;
19 }
20
21 public int getAge() {
22 return age;
23 }
24
25 public void setAge(int age) {
26 this.age = age;
27 }
28
29 @Override
30 public boolean equals(Object o) {
31 if (this == o) return true;
32 if (o == null || getClass() != o.getClass()) return false;
33
34 Student student = (Student) o;
35
36 if (age != student.age) return false;
37 return name != null ? name.equals(student.name) : student.name == null;
38 }
39
40 @Override
41 public int hashCode() {
42 int result = name != null ? name.hashCode() : 0;
43 result = 31 * result + age;
44 return result;
45 }
46 }测试类
1 public class HashMapDemo {
2 public static void main(String[] args) {
3 //创建HashMap集合对象
4 HashMap<Student, String> hm = new HashMap<Student, String>();
5
6 //创建学生对象
7 Student s1 = new Student("林青霞", 30);
8 Student s2 = new Student("张曼玉", 35);
9 Student s3 = new Student("王祖贤", 33);
10 Student s4 = new Student("王祖贤", 33);
11
12 //把学生添加到集合
13 hm.put(s1, "西安");
14 hm.put(s2, "武汉");
15 hm.put(s3, "郑州");
16 hm.put(s4, "北京");
17
18 //遍历集合
19 Set<Student> keySet = hm.keySet();
20 for (Student key : keySet) {
21 String value = hm.get(key);
22 System.out.println(key.getName() + "," + key.getAge() + "," + value);
23 }
24 }
25 }
5.TreeMap集合
5.1TreeMap集合概述和特点【理解】
TreeMap底层是红黑树结构
依赖自然排序或者比较器排序,对键进行排序
如果键存储的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象时候给出比较器排序规则
5.2TreeMap集合应用案例【应用】
-
案例需求
创建一个TreeMap集合,键是学生对象(Student),值是籍贯(String),学生属性姓名和年龄,按照年龄进行排序并遍历
要求按照学生的年龄进行排序,如果年龄相同则按照姓名进行排序
-
代码实现
学生类
1 public class Student implements Comparable<Student>{
2 private String name;
3 private int age;
4
5 public Student() {
6 }
7
8 public Student(String name, int age) {
9 this.name = name;
10 this.age = age;
11 }
12
13 public String getName() {
14 return name;
15 }
16
17 public void setName(String name) {
18 this.name = name;
19 }
20
21 public int getAge() {
22 return age;
23 }
24
25 public void setAge(int age) {
26 this.age = age;
27 }
28
29 @Override
30 public String toString() {
31 return "Student{" +
32 "name='" + name + '\'' +
33 ", age=" + age +
34 '}';
35 }
36
37 @Override
38 public int compareTo(Student o) {
39 //按照年龄进行排序
40 int result = o.getAge() - this.getAge();
41 //次要条件,按照姓名排序。
42 result = result == 0 ? o.getName().compareTo(this.getName()) : result;
43 return result;
44 }
45 }测试类
1 public class Test1 {
2 public static void main(String[] args) {
3 // 创建TreeMap集合对象
4 TreeMap<Student,String> tm = new TreeMap<>();
5
6 // 创建学生对象
7 Student s1 = new Student("xiaohei",23);
8 Student s2 = new Student("dapang",22);
9 Student s3 = new Student("xiaomei",22);
10
11 // 将学生对象添加到TreeMap集合中
12 tm.put(s1,"江苏");
13 tm.put(s2,"北京");
14 tm.put(s3,"天津");
15
16 // 遍历TreeMap集合,打印每个学生的信息
17 tm.forEach(
18 (Student key, String value)->{
19 System.out.println(key + "---" + value);
20 }
21 );
22 }
23 }