HashMap

HashMap知识点

1、HashMap的内部数据结构

JDK1.8版本的,内部使用数组 + 链表 / 红黑树
在这里插入图片描述
2、HashMap的数据插入原理

  • 判断数组是否为空,为空进行初始化
  • 不为空,计算k的hash值,通过(n-1)&hash计算应当存放在数组下标的index
  • 查看table[index]是否存在数据,没有数据就构造一个Node节点存放在table[index]中
  • 存在数据,说明发生了hash冲突,继续判断key是否相等,相等,用新的value替换原数据(onlyIfAbsent为false)
  • 如果不相等,判断当前节点类型是不是树型节点,如果是是树型节点,创建树型节点插入红黑树中
  • 如果不是树型节点,创建普通Node加入链表中;判断链表长度是否大于8,大于的话链表转换为红黑树
  • 插入完成之后判断当前节点数是否大于阈值,如果大于开始扩容为原数组的2倍

3、HashMap初始容量大小

一般如果new HashMap()不传值,默认大小为16,负载因子是0.75,

如果自己传入初始大小k,初始化大小为大于k的2的整数次方

4、HashMap的哈希函数怎么设计的

hash函数先拿到通过key的hashcode,是32位的int值,然后让hashcode的高16位和低16位进行异或操作

这样设计原因有两点:

(1)一定要尽可能降低hsah碰撞,越分撒越好

(2)算法一定要尽可能高效,因为这是高频操作,因此采用位运算

5、1.8的优化

  • 数组+链表改成了数组+链表或红黑树
  • 链表的插入方式从头插法改为尾插法,简单的说就是插入时,如果数组位置上已经有元素,1.7将新元素放到数组中,原始节点作为新节点的后继节点,1.8遍历链表,将元素放置到链表的最后
  • 扩容的时候1.7需要对原数组中的元素进行重新hash定位在新数组的位置;1.8采用更简单的逻辑判断,位置不变或索引+旧容量大小
  • 在插入时,1.7先判断是否需要扩容,再插入;1.8先进行插入,插入完在判断是否需要扩容

6、为什么做优化

  • 防止发生hash冲突,链表长度过长,将时间复杂度由
    O ( n ) O(n) On
    将为
    O ( l o g n ) O(logn) Ologn

  • 因为1.7头插法扩容时,头插法会使链表发生转移,多线程环境下会产生环

    例如:A线程在插入节点B,B线程也在插入,遇到容量不够开始扩容,重新hash,放置元素,采用头插法,后遍历到的B节点放入了头部,这样就形成了环:
    在这里插入图片描述

  • 扩容的时候为什么1.8不用重新hash就可以直接定位原节点在新数据的位置呢?

    这是由于扩容时扩大为原数组大小的2倍,用于计算数组的掩码仅仅只是高位多了一个1,因为是&运算,1和任何数&都是它本身

7、HashMap是线程安全的么

不是,在多线程环境下,1.7会产生死循环、数据丢失、数据覆盖的问题。1.8中会有数据覆盖的问题

8、怎么解决HashMap线程不安全

java中有Hashtable、Collections.synchronizedMap、以及ConcurrentHashMap可以实现线程安全的Map

  • Hashtable是直接在操作方法上加上synchronized关键字,锁住整个数组,粒度比较大
  • Collections.synchronizedMap是使用Coolections集合工具的内部类,通过传入map封装出一个synchronizedMap对象,内部定义了一个对象锁,方法内通过对象锁实现
  • ConcurrentHashMap使用分段锁,降低了锁粒度,让并发度大大提高

9、链表转红黑树是链表长度达到阈值是多少

链表转红黑树表阈值是8

红黑树转链表的阈值是6

因为经过计算,在Hash函数设计合理的情况下,发送hash碰撞8次的几率是万分之6,所有8够用了,

至于为什么转回来是6,因为如果hash碰撞次数在8附件徘徊,会一直发送链表和红黑树的转化,为了预防这种情况的发生

10、HashMap内部节点是无序的,根据hash值随机插入

11、LinkedHashMap和TreeMap是有序的

12、LinkedHashMap如何实现有序

LinkedHashMap内部维护了一个单链表,有头尾结点,同时LinkedHashMap节点Entry内部除了继承HashMap的Node属性,还有before和after用于标识前置节点和后置节点。可以实现按插入的顺序或访问顺序排序。

13、TreeMap如何实现有序

TreeMap是按照Key的自然顺序或者Comprator的顺序进行排序,内部是通过红黑树来实现。所以要么key所属的类实现Comprator接口,或者自定义一个实现了Comprator接口的比较器,传给TreeMap用户key的比较

14、HashMap和Hashtable

存储元素和取出元素的位置是无序的

而LinkedHashMap存储元素和取出元素是一致的

15、红黑树
在这里插入图片描述

  1. 节点是红色或者黑色
  2. 根节点是黑色
  3. 每个叶子的节点都是黑色的空节点(NULL)
  4. 每个红色节点的两个子节点都是黑色的
  5. 从任意节点到其每个叶子的所有路径都包含相同的黑色节点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值