• HashMap存值、取值及哈希碰撞原理分析


    在这里插入图片描述

    HashMap中的put()和get()的实现原理:

    map.put(k,v)实现原理

    首先将k,v封装到Node对象当中(节点)。
    然后它的底层会调用K的hashCode()方法得出hash值。
    通过哈希表函数/哈希算法,将hash值转换成数组的下标,下标位置上如果没有任何元素,就把Node添加到这个位置上。如果说下标对应的位置上有链表(哈希碰撞)。此时,就会拿着k和链表上每个节点的k进行equal。如果所有的equals方法返回都是false,那么这个新的节点将被添加到链表的末尾。如其中有一个equals返回了true,那么这个节点的value将会被覆盖。

    map.get(k)实现原理

    先调用k的hashCode()方法得出哈希值,并通过哈希算法转换成数组的下标。
    通过上一步哈希算法转换成数组的下标之后,在通过数组下标快速定位到某个位置上。如果这个位置上什么都没有,则返回null。如果这个位置上有单向链表,那么它就会拿着K和单向链表上的每一个节点的K进行equals,如果所有equals方法都返回false,则get方法返回null。如果其中一个节点的K和参数K进行equals返回true,那么此时该节点的value就是我们要找的value了,get方法最终返回这个要找的value。

    为何随机增删、查询效率都很高的原因是?

    原因: 增删是在链表上完成的,而查询只需扫描部分,则效率高。
    注: HashMap集合的key,会先后调用两个方法,hashCode and equals方法,这这两个方法都需要重写。
    为什么放在hashMap集合key部分的元素需要重写equals方法?
    因为equals方法默认比较的是两个对象的内存地址

    哈希碰撞概述

    在调用HashMap的put(key k,value v)方法时,若key的哈希值相等了,则发生哈希碰撞(冲突);
    此时,若equals()比较相等,则表示key相同,判断元素相同,会执行覆盖操作;若equals()不相等,则形成链表,追加到链表末尾;
    当链表长度等于8时,优化为红黑树结构(jdk1.8开始优化为红黑树),当调用remove(key k)方法删除元素时,剩余6个的时候,退回链表结构;
    ③.判断table[i]的首个元素是否和key一样,如果相同直接覆盖value,否则转向④,这里的相同指的是hashCode以及equals;

    如何避免哈希碰撞

    避免哈希碰撞,就要尽量让key的hash值不相同,key的hash值和map的容量有很大关系,容量越大越不容易发生碰撞。
    所以避免哈希碰撞的有效方式就是:扩容,
    当map扩容后,size发生改变,所有的key的hash值,都会通过reHash重新计算

    扩展

    因此,我们在扩充HashMap的时候,不需要像JDK1.7的实现那样重新计算hash,只需要看看原来的hash值新增的那个bit是1还是0就好了,是0的话索引没变,是1的话索引变成“原索引+oldCap”,可以看看下图为16扩充为32的resize示意图.

  • 相关阅读:
    医院管理系统(Java+SSM+MySQL开发的医院科室管理系统)
    了解 HTTPS 中间人攻击:保护你的网络安全
    使用反射调用私有内部类方法
    特拉斯成为英国首相后 “英镑危机”的风险正在上升
    轻量级的资源授权:基于 OAuth 规范
    这些来自各领域的全新机器人技术,你了解吗?
    C/C++指针
    Day1--什么是网络安全?网络安全常用术语
    【c++】智能指针
    软件测试:写一个好的测试用例
  • 原文地址:https://blog.csdn.net/m0_64803878/article/details/134335323