HashMap 底层原理详解

HashMap

  • HashMap的底层数据结构?

    是数组 + 链表 + 红黑树的数据结构,每个数组中都保存着key,value的实例
    在java7之前Entry,java8叫Node
    
  • HashMap的存取原理?

    存储:
    		先判断数组是否进行了初始化长度,如果没有就调用初始化方法,默认长度为16
    			如果有赋值的长度,那么回去大于等于这个数的2的幂次方的数作为数组长度
    		计算出key的hashcode值,然后取余,把得到的值作为数组的下标(索引),
    			1.7: 把数据插入到链表的头部
    			1.8: 把这个新的节点作为头结点
    		如果两个key相同
    			根据hashcode找到对应的bucket之后,遍历链表通过equals()方法来对比key值。
    			如果有,则用新的value取代旧的value
    		判断数组是否达到了树形化阈值,达到了就转换成红黑树
    取出:
    		先计算出key的hashcode值,找到对应的bucket,可能会有多个entry对象,遍历链表,
    		通过equals()来比较key值,最后取出entey对象
    
  • Java7和Java8的区别?

    java7之前是头部插入
    	新来的值会取代原有的值,原有的值就顺推到链表中去,因为作者认为后来的值被查找的可能性更大一点,提升查找的效率。
    java8之后是尾部插入
    	使用头插会改变链表的上的顺序,但是如果使用尾插,在扩容时会保持链表元素原本的顺序,就不会出现链表成环的问题了
    
  • 为啥会线程不安全?

    	因为通过源码看到put/get方法都没有加同步锁,多线程情况最容易出现的就是:
    		无法保证上一秒put的值,下一秒get的时候还是原值,所以线程安全还是无法保证
    	多线程进行扩容的时候可能会出现循环链表
    
  • 有什么线程安全的类代替么?

    ConcurrentHashMap
    HashTable 在方法之前都加上了synchronized(锁)
    
  • HashMap与Hashtable的比较

    • HashMap可以保存键值为null,HashTable不允许键值为null:
      • HashTable在保存键值的时候会报空指针异常
        • 快速失败机制(fail-safe),这种机制会使你此次读到的数据不一定是最新的数据
      • 而HashMap做了特殊的处理
    • 初始化容量不同:
      • HashMap 的初始化容量为: 16
      • HashTable的初始化容量为: 11
      • 两者的负载因子都是: 0.75
    • 扩容机制不同:
      • HashMap 扩容为原数组的两倍
      • HashTable 扩容为原数组的两倍 + 1
  • 默认初始化大小是多少?为啥是这么多?为啥大小都是2的幂?

    默认初始化大小为16 = 1 << 4
     为了方便位移运算的算法,也就是将Key映射到index的算法(HashCode % 数组长度),但是位移运算的效率要高很多
     内部会调用一个方法,把自定义的数组长度更改为 大于等于数组长度的2的幂
    
  • HashMap的扩容方式?负载因子是多少?为什么是这么多?

    调用 resize()方法进行扩容
    分为两步:
    	扩容:创建一个新的Entry空数组,长度是原数组长度 * 0.75。
    	ReHash:遍历原Entry数组,把所有的Entry重新Hash到新数组。
    Capacity:HashMap当前长度。
    LoadFactor:负载因子,默认值0.75f。
    	负载因子是0.75的时候,空间利用率比较高,而且避免了相当多的Hash冲突,使得底层的链表或者是红黑树的高度比较低,
    		提升了空间效率。
    
  • HashMap的主要参数都有哪些?

    // 默认初始化长度
    DEFAULT_INITIAL_CAPACITY = 1 << 4
    // 最大容量
    MAXIMUM_CAPACITY = 1 << 30
    // 默认负载因子
    DEFAULT_LOAD_FACTOR = 0.75f
    // 树形化阈值
    TREEIFY_THRESHOLD = 8
    // 解树形化阈值
    UNTREEIFY_THRESHOLD = 6
    // 树形化的最小容量
    MIN_TREEIFY_CAPACITY = 64
    
  • HashMap是怎么处理hash碰撞的?

    hash碰撞:
    	不同key值,hash值却相同
    拉链法:
    	通过计算key值的hash值,找到对应的bucket,把数据添加到对应的位置(1.7头部/1.8尾部)
    
  • hash的计算规则?

    取key值的hashcode值,然后通过位移算法取余数组长度,这样可以使元素分布尽量均匀些,减少hash碰撞
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值