HahsMap原理

1. HashMap的数据结构图

        HashMap采⽤Entry数组来存储key-value对,每⼀个键值对组成了⼀个Entry实体,Entry类实际上是⼀个单向的链表结 构,在JDK1.8中,链表⻓度⼤于8的时候,链表会转成红⿊树。

2. 为什么使用链表+数组

    数组的长度是限制死的,我们在对key值进行散列取到下标以后,放入到数组中时,难免出现两个key值不同,但是却放入到下标相同的格子中,此时我们就可以使用链表来对其进行链式的存放。

3. LinkedList代替数组结构可以吗?

    原则上来说也是可以的。

Entry[] table=new Entry[capacity];

 替换为

List<Entry> table=new LinkedList<Entry>();

4. 那既然可以使用进行替换处理,为什么有偏偏使用到数组呢?

        数组效率查询最⾼! 在HashMap中,定位节点的位置是利⽤元素的key的哈希值对数组⻓度取模得到。此时,我们已得到节点的位置。 LinkedList还需要进行遍历,才能查到对于的位置。

即使是用ArrayList,也不好,因为用基本类型数组,扩容机制可以⾃⼰定义,HashMap中数组扩容刚好是2的次幂,在做取模运算的效率⾼。

5. HashMap是如何获取到下表值的

  hashMap对存放进来的key值进行了hashcode(),生成了一个值,但是这个值很大,我们不可以直接作为下标, 所以Hashmap对其进行了与操作,对Table的表长度减一再与生成的hash值进行相与操作

if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);

6. HashMap 中put的过程

  1.    对key的hashCode()做hash运算,计算index;
  2.    如果没碰撞直接放到bucket⾥;
  3.    如果碰撞了,以链表的形式存在buckets后;
  4.    如果碰撞导致链表过⻓(⼤于等于TREEIFY_THRESHOLD),就把链表转换成红⿊树(JDK1.8中的    改动);
  5.    如果节点已经存在就替换old value(保证key的唯⼀性)
  6.    如果bucket满了(超过load factor*current capacity),就要resize

7 . HashMap 中get的过程

  1. 对key的hashCode()做hash运算,计算index;
  2. 如果在bucket⾥的第⼀个节点⾥直接命中,则直接返回;
  3. 如果有冲突,则通过key.equals(k)去查找对应的Entry;
  4. 若为树,则在树中通过key.equals(k)查找,O(logn);
  5. 若为链表,则在链表中通过key.equals(k)查找,O(n)。

8. 为什么不一开始就使用红黑树,不是效率很高吗?

        因为红⿊树需要进⾏左旋,右旋,变⾊这些操作来保持平衡,⽽单链表不需要。
        当元素⼩于8个当时候,此时做查询操作,链表结构已经能保证查询性能。

        当元素⼤于8个的时候,此时需要红⿊树来加快查 询速度,但是新增节点的效率变慢了。因此,如果⼀开始就⽤红⿊树结构,元素太少,新增效率⼜⽐较慢,⽆疑这是浪费性能的。

9. 什么时候退化为链表

   为6的时候退转为链表。中间有个差值7可以防⽌链表和树之间频繁的转换。
   假设⼀下,如果设计成链表个数超过8则链表转 换成树结构,链表个数⼩于8则树结构转换成链表,   如果⼀个HashMap不停的插⼊、删除元素,链表个数在8左右徘徊,就会 频繁的发⽣树转链表、链表转树,效率会很低。

10. 一些特殊的变量名

  • DEFAULT_INITIAL_CAPACITY Table数组的初始化长度: 1 << 42^4=16(为什么要是 2的n次方?)
  • MAXIMUM_CAPACITY Table数组的最大长度: 1<<302^30=1073741824
  • DEFAULT_LOAD_FACTOR 负载因子:默认值为0.75。 当元素的总个数>当前数组的长度 * 负载因子。数组会进行扩容,扩容为原来的两倍(todo:为什么是两倍?)
  • TREEIFY_THRESHOLD 链表树化阙值: 默认值为 8 。表示在一个node(Table)节点下的值的个数大于8时候,会将链表转换成为红黑树。
  • UNTREEIFY_THRESHOLD 红黑树链化阙值: 默认值为 6 。 表示在进行扩容期间,单个Node节点下的红黑树节点的个数小于6时候,会将红黑树转化成为链表。
  • MIN_TREEIFY_CAPACITY = 64 最小树化阈值,当Table所有元素超过改值,才会进行树化(为了防止前期阶段频繁扩容和树化过程冲突)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值