美文网首页
HashMap Hashtable HashSet

HashMap Hashtable HashSet

作者: Lemon666 | 来源:发表于2020-08-07 14:39 被阅读0次

    HashMap

    HashMap主要结构
    • 数组加链表
    • 数组加红黑树
    存放数据的对象
    • Node <- Map.Entry
    • TreeNode <- Node <- Map.Entry
    默认构造函数
    • 数组默认初始化容量 1 << 4
    • 数组最大容量 1 << 30
    • 默认负载因子 0.75f
    • 负载阀值 = 容量 * 负载因子
    • 链表树化阀值,链表长度大余等于8
    • 树结构链化,树的大小小余等于6
    • 树化最小数组长度,也就是如果数组长度小于64,如果遇到链表长度大于树化阀值,则是扩容数组,而不是将链表树化
    初始化
    • 构造HashMap时,数组还未真正初始化
    • 构造HashMap时,主要设置数组大小,负载因子,负载阀值
    • 使用旧的HashMap构造新的HashMap,会resize初始化数组,并且把旧数据加入
    • 构造一个空HashMap,在第一次put时才会通过resize初始化数组
    数组长度和扩容规则
    • 数组长度为2的N次幂,如:1、2、4、8、16
    • 扩容就是在原来基础上乘以2
    • 当数据个输超过阀值则扩容
    • 当链表准备树化发现数组长度小于64时,优先扩容
    运算方式
    • 主要通过位运算
    • hash值和数组长度减一与运算(&),获取下标
    备注
    • HashMap非线程安全
    • 计算hash值高16位和低16位进行异或运算,使高低位都参与运算
    • 如果是链表,则在尾部插入
    其他
    • & 与
    • | 或
    • ~ 非
    • ^ 异或

    Hashtable

    默认构造参数
    • 默认的数组容量为 11
    • 默认的负载因子为 0.75
    • 初始化的时候,负载阀值默认为初始化容量
    • 构造方面内就把数组初始化
    简介
    • Hashtable是线程安全的
    • 方法用synchronized关键字修饰,对象级别的锁
    • put的value不能为null,否则报错
    • 下标是通过求余(%)来计算
    • 输入通过链表头部插入
    扩容规则
    • 扩容方法rehash()
    • 数据量大于等于负载阀值开始扩容
    • hash值直接通过Object.hashCode()获取
    • 扩容大小为(旧容量 * 2) + 1
    • 负责阀值为容量大小 * 负载因子
    存放数据的对象
    • HashtableEntry <- Map.Entry

    HashSet

    原理
    • HashSet有个内部成员变量map为HashMap,操作都与map有关
    • 数据存放规则和HashMap一样
    • add存放的值对应HashMap的key,value为PRESENT的一个Object(),所以可以为null
    • HashSet非线程安全
    总结
    • HashSet就是一个只关心key不关心value的HashMap封装类

    HashMap和Hashtable的区别

    • 扩容规则HashMap是2的幂次,Hashtable是当前容量*2+1
    • 链表插入HashMap是尾部插入,Hashtable是头部插入
    • HashMap会树化,Hashtable一直是链表
    • 下标计算HashMap是通过与运算,Hashtable通过求余
    • HashMap非线程安全,Hashtable线程安全
    • 默认情况下,HashMap在put才会初始化数组,Hashtable构造方法内就初始化
    • hash值HashMap是高低16位通过异或运算,Hashtable直接获取Object的hashCode

    相关文章

      网友评论

          本文标题:HashMap Hashtable HashSet

          本文链接:https://www.haomeiwen.com/subject/ookfdktx.html