Java学习Day09------红黑树、HashSet、Map

红黑树、HashSet、Map

红黑树

(1)概述:自平衡的二叉查找树,不是高度平衡的(跟高度差关系不大),他的平衡通过自己的红黑规则决定。
(2)红黑规则
  a) 每个节点都是红色或者黑色
  b) 根节点必须是黑色
  c) 如果一个节点没有子节点或者父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,每个叶子节点都是黑色
  d) 如果某一个节点是红色,那么他的子节点必须是黑色(也就是相邻两个相连接的节点不能都为红色)
  e) 对每一个节点,从该节点到其所有节点的简单路径上,均包含相同数目的黑色节点
在这里插入图片描述
(3)添加节点的默认颜色
  添加节点时,默认为红色,这样效率高
(4)红黑树添加节点后如何保持红黑规则
  a) 如果添加的节点为根节点,那么直接变成黑色
  b) 如果添加的节点为非根节点
    aa) 如果父节点是黑色,那么不需要进行任何操作,默认为红色就行
    bb) 如果父节点是红色
      aaa) 叔叔节点是红色
        aaaa) 将父节点变为黑色,叔叔节点变为黑色
        bbbb) 将祖父节点设为红色
        cccc) 如果祖父节点是根节点,就将祖父节点设置为黑色
      bbb) 叔叔节点是黑色
        aaaa) 将父节点设为黑色
        bbbb) 将祖父节点设置为红色
        cccc)以祖父节点为支点进行旋转(具体左旋还是右旋根据实际情况)
在这里插入图片描述

HashSet

(1)特点
  a) 底层数据结构是哈希表(JDK8里面:数组+链表+红黑树,JDK8之前:数组+链表)
  b)无序: 不能保证存储和去除顺序完全一致
  c) 无索引没有带索引的方法,所以不能使用普通for进行遍历
  d) 无重复:里面的元素唯一,无重复
(2)哈希值(哈希码值):根据对象的地址值或者属性值算出来的int值
  a) 类中如果没有重写hashCode,那么会使用Object类中的方法获取哈希值
    public int hashCode():该方法使用的是对象的地址值进行计算的
  b) 类中重写了hashCode,那么就使用对象的属性值进行计算
  c) 特点:
    aa) 同一个对象多次调用hashCode()获得的值是相同的
    bb) 默认情况下,不同对象的哈希值是不同的,而重写hashCode()方法可以实现让不同的对象有相同的哈希值
(3)哈希表作用:针对于哈希表进行去除重复

哈希表

(1)JDK1.8之前结构:数组+链表
在这里插入图片描述
(2)JDK1.8之后结构:节点数少于8个的时候采用数组+链表的结构,当节点数多于8个的时候,采用的是数组+红黑树的结构
在这里插入图片描述

Map

(1)特点:
  a) 是双列集合,由键值对组成
  b) 键不能重复,值可以重复
(2)应用场景:解决一一对应问题
   键和值是一一对应的,每一个键只能找到自己对应的值
(3)常用方法

方法名说明
V put(K key,V value)添加元素
V remove(Object key)根据键删除键值对元素
void clear()移除所有的键值对元素
boolean containsKey(Object key)判断集合是否包含指定的键
boolean containsValue(Object value)判断集合是否包含指定的值
boolean isEmpty()判断集合是否为空
int size()集合的长度,也就是集合中键值对的个数

(4)Map获取功能

方法名说明
V get(Object key)根据键获取值
Set keySet()获取所有键的集合
Collection values()获取所有值的集合
Set<Map.Entry<K,V>> entrySet()获取所有键值对对象的集合

(5)遍历方式
  a) 通过keySet进行遍历
    aa) 获取所有键值(keySet()方法)
    bb) 遍历所有键值,获取到每一个键值(使用增强for)
    cc) 根据键值找到相应的值(使用 get(Object key)方法)
    示例:

public class MapDemo01 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<String, String>();
        //添加元素
        map.put("111", "111");
        map.put("222", "222");
        map.put("333", "333");
        //获取所有键的集合。用keySet()方法实现
        Set<String> keySet = map.keySet();
        //遍历键的集合,获取到每一个键。用增强for实现
        for (String key : keySet) {
            //根据键去找值。用get(Object key)方法实现
            String value = map.get(key);
            System.out.println(key + "," + value);
        }
    }
}

  b) 通过entrySet进行遍历
    aa) 获取所有键值对,得到的是一个Set集合( Set<Map.Entry<K,V>> entrySet())
    bb) 遍历所有集合,得到每一个entry(使用增强for)
    cc) 通过getKey()和getValue()方法进行访问数据
    示例:

public class MapDemo02 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<String, String>();
        //添加元素
        map.put("111", "111");
        map.put("222", "333");
        map.put("333", "333");
        //获取所有键值对对象的集合
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        //遍历键值对对象的集合,得到每一个键值对对象
        for (Map.Entry<String, String> me : entrySet) {
            //根据键值对对象获取键和值
            String key = me.getKey();
            String value = me.getValue();
            System.out.println(key + "," + value);
        }
    }
}

  c) forEach进行遍历(lambda表达式)

public class MapDemo02 {
    public static void main(String[] args) {
        //创建集合对象
        Map<String, String> map = new HashMap<String, String>();
        //添加元素
        map.put("111", "111");
        map.put("222", "333");
        map.put("333", "333");
        //获取所有键值对对象的集合
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        //遍历
        map.forEach((key,value)-> System.out.println(key + "," + value));
    }
}

HashMap

(1) 特点
  a) HashMap底层是哈希表结构的
  b) 依赖hashCode方法和equals方法保证键的唯一
  c) 如果键要存储的是自定义对象,需要重写hashCode和equals方法
(2)案例:

/*
* 案例需求
* 创建一个HashMap集合,键是学生对象(Student),值是居住地 (String)。存储多个元素,并遍历。
* 要求保证键的唯一性:如果学生对象的成员变量值相同,我们就认为是同一个对象
*/
// 学生类
public class Student {
    private String name;
    private 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 boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        if (age != student.age) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }
    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }
}

// 测试类
public class HashMapDemo {
    public static void main(String[] args) {
        //创建HashMap集合对象
        HashMap<Student, String> hm = new HashMap<Student, String>();
        //创建学生对象
        Student s1 = new Student("111", 30);
        Student s2 = new Student("222", 35);
        Student s3 = new Student("333", 33);
        Student s4 = new Student("444", 33);
        //把学生添加到集合
        hm.put(s1, "西安");
        hm.put(s2, "武汉");
        hm.put(s3, "郑州");
        hm.put(s4, "北京");
        //遍历集合
        Set<Student> keySet = hm.keySet();
        for (Student key : keySet) {
            String value = hm.get(key);
            System.out.println(key.getName() + "," + key.getAge() + "," + value);
        }
    }
}

TreeMap

(1)特点:
  a) TreeMap底层是红黑树结构
  b)依赖自然排序或者比较器排序,对键进行排序
  c) 如果键存储的是自定义对象,需要实现Comparable接口或者在创建TreeMap对象时候给出比较器排序规则
(2)案例:

/*
* 案例需求
* 创建一个TreeMap集合,键是学生对象(Student),值是籍贯(String),学生属性姓名和年龄,按照年龄进行排序并遍历
* 要求按照学生的年龄进行排序,如果年龄相同则按照姓名进行排序
*/
// 学生类
public class Student implements Comparable<Student>{
    private String name;
    private 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 = o.getAge() - this.getAge();
        //次要条件,按照姓名排序。
        result = result == 0 ? o.getName().compareTo(this.getName()) : result;
        return result;
    }
}

// 测试类
public class Test1 {
    public static void main(String[] args) {
        // 创建TreeMap集合对象
        TreeMap<Student,String> tm = new TreeMap<>();
        /* // 使用比较器
        TreeMap<Student,String> tm = new TreeMap<>(new Comparator<Student>() {
            @Override
            public int compare(Student student, Student t1) {
                //按照年龄进行排序
                int result = o.getAge() - this.getAge();
                //次要条件,按照姓名排序。
                result = result == 0 ? o.getName().compareTo(this.getName()) : result;
                return result;
            }
        });*/
        // 创建学生对象
        Student s1 = new Student("xiaohei",23);
        Student s2 = new Student("dapang",22);
        Student s3 = new Student("xiaomei",22);
        // 将学生对象添加到TreeMap集合中
        tm.put(s1,"江苏");
        tm.put(s2,"北京");
        tm.put(s3,"天津");
        // 遍历TreeMap集合,打印每个学生的信息
        tm.forEach(
                (Student key, String value)->{
                    System.out.println(key + "---" + value);
                }
        );
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值