Hashmap

JDK 1.7

jdk 1.7的HashMap 使用 数组 + 链表的形式保存数据

  1. 数组数据结构是 Node<K,V>[] 和链表的是一样的(图中Node类)
  2. 数组初始长度为 16 扩展因子0.75
  3. 当数组达到 16 * 0.75 = 12时对数组扩容,每次扩展 (原来长度) << 1,就是原来两倍。

    << n 符号就是左移n位
    例如 1 << 1 = [1的2进制,左移1位,右边补0] = 10 = 2 也就是 1 * 2^1 = 2
    n << x = n * 2^x

在这里插入图片描述

get 流程

get 和 put 都必须走的一步就是计算数组下标,找到对应下标再从链表中获取数据。

  1. 取key的hashCode结果是一个整数类型,对应32位的二进制地址

    例如:结果:514287189521 对应地址为:1111 1111 1111 1111 0000 0000 0001 0001

  2. 对hashCode 进行优化,代码中体现为 hashcode = hashcode ^ ( hashCode >>> 16)

    为什么要做这一步?

    首先我们需要知道从hashCode如何计算出数组下标。
    举个简单例子:
    现有数组 Node[4] 长度为4
    当 hashCode = 99 = 1100011【二进制】
    99 % 4 = 3 = 11【二进制】
    当 hashCode = 257= 100000001【二进制】
    257% 4 = 1= 1【二进制】
    我们可以发现都是二进制后面几位(取决于数组长度),也就是取模 hashCode的高位是基本不参与的。除非数组长度很长(很少出现),因此hash冲突比较多,因为参与计算的数少。
    所以想办法让高位参与计算,即可减少hash冲突
    回到 hashcode = hashcode ^ ( hashCode >>> 16) 是如何让高位参与计算的问题上。
    因为:8589869073 >>> 16 = 1111 1111 1111 1111 0000 0000 0001 0001 >>> 16 = 0000 0000 0000 0000 1111 1111 1111 1111
    所以:8589869073 ^ ( 8589869073 >>> 16 ) = 1111 1111 1111 1111 0000 0000 0001 0001 ^ 0000 0000 0000 0000 1111 1111 1111 1111 = 1111 1111 1111 1111 1111 1111 1110 1110
    此时再取模高位也参与进来了

  3. 使用新的hashCode 和 数组长度取模,得到下标

  4. 根据下标获取对应数组元素的链表

  5. 根据key遍历链表取值

put 流程

和get一样找到对应链表往后面加上元素

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值