HashMap的底层实现原理 [Java][jdk7.0]

HashMap在jdk7.0中的底层实现原理:

实例化对象

HashMap map = new HashMap();
  • 在实例化之后,底层创建了一个长度为16的一维数组table(这个数组是Entry类型的);

put();

map.put(key1,value1);
  • key1和value1是以一个整体的Entry对象的形式传递进HashMap底层的table数组中
  • Map中没有add()方法,Map中添加数据我们是通过使用put()方法进行添加

首先,我们先调用key1所在类的hashCode()方法,计算出key1的哈希值,此哈希值经过某种算法之后(散列函数: 其实就是给我们计算出来的hash值取模16,但是这个时候我们取模16在底层中我们是通过&(与运算)15来实现的, 这个时候通过&15来代替 %16,就是因为我们的&15在底层执行的效率更加高一些),就可以得到我们的这个Entry对象在Entry数组中的存放位置

  • 如果这个位置上没有其他数据,这个时候我们就说我们的这个key1对应的Entry对象添加成功 ----- 情况一
  • 如果此位置上已经有了一个或者以链表形式存储的多个Entry对象时,这个时候我们就要通过我们的key1的hash值和原来位置上这里已经存在的Entry对象的key的hash值进行比较
    • 如果这个时候我们key1的hash值和我们这里原本的这些Entry对象的key的hash值都不相同,这个时候我们的key1对应的Entry对象也添加成功 ------ 情况二
    • 如果这个时候我们的key1的hash值和我们这里原本这里存在的Entry对象中的某个的key的hash值相同,这个时候我们使用key1所在类的equals()方法和与key1hash值相同的key进行比较
      • 如果这个时候equals()方法的返回值为false,这个时候我们的key1对应的Entry对象也添加成功 ----情况三
      • 如果这个时候equals()方法的返回值为true,这个时候用我们的value1替换这个与我们的key1所重复的Entry对象中的value
  • 对于这里的情况二和情况三,这个时候我们新添加的key ---- value键值对和原本这个位置上的Entry对象以链表的形式进行存储
    • 这里既然要以链表的形式存储,这个时候就要设计谁链谁:
    • jdk7中,我们新添加的数据在数组中,指向原有数据
    • jdk8中,原有数据在数组中,指向新添加的数据
      • 总结:“七上八下”

关于这里使用put()方法的总结:

我们之前使用的List和Set中的add()方法都是返回一个boolean类型的数据

  • 也就是使用add()方法分为添加成功和添加失败
    • 其实也就是add()方法只有添加元素的功能

我们在Map中使用的put()方法返回的是一个V型的数据,这个V是一个泛型(是value对应的泛型)

  • 我们Map中的put()方法有添加元素的功能还有修改元素的功能
  • 我们使用put()方法如果是要添加一个元素,如果添加成功了,那么就是添加成功了,如果添加失败了,这个时候其实不是添加失败了,这个时候是对这个原有的重复元素进行了修改

扩容问题(后面细讲)

在HashMap集合中添加对象时,在不断添加的过程中,我们会涉及到数组扩容问题,这里默认的扩容方式为扩容为原来的2倍 ,并且我们扩容之后数组中药进行元素的重排,也就是这个时候我们底层的数组变化了,对应不同的散列函数我们要重新以一个新的顺序进行存储

jdk7.0中通过单独方法进行初始化

inflateTable();

jdk7.0中的扩容的方法

resize();

  • 在jdk8.0中我们将初始化也加到了resize()方法中来,也就是我们在jdk8.0中通过使用resize()方法完成数组的初始化和扩容
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值