Java笔记(十八)

16HashMap

哈希表存储原理

概念: 哈希表:一种数据结构的名字。 哈希函数: 通过哈希函数可以将一个Java对象映射为一个数字。(就像现实世界中,每个人(对象)都会映射一个身份证号(哈希值)一样。) 也就是说通过哈希函数的执行可以得到一个哈希值。

在Java中,hashCode()方法就是哈希函数。 也就是说hashCode()方法的返回值就是哈希值。 一个好的哈希函数,可以让散列分布均匀。 哈希值:也叫做哈希码。是哈希函数执行的结果。 哈希碰撞:也叫做哈希冲突。 当两个对象“哈希值%数组长度”之后得到的下标相同时,就发生了哈希冲突。 如何解决哈希冲突?将冲突的挂到同一个链表上或同一个红黑树上。 以上描述凡是“哈希”都可以换为“散列”。

重点: 存放在HashMap集合key部分的元素必须同时重写hashCode+equals方法。 equals返回true时,hashCode必须相同。

手写HashMap的put方法

【第一步】:处理key为null的情况 如果添加键值对的key就是null,则将该键值对存储到table数组索引为0的位置。

【第二步】:获得key对象的哈希值 如果添加键值对的key不是null,则就调用key的hashcode()方法,获得key的哈希值。

【第三步】:获得键值对的存储位置 因为获得的哈希值在数组合法索引范围之外,因此我们就需要将获得的哈希值转化为[0,数组长度-1]范围的整数, 那么可以通过取模法来实现,也就是通过“哈希值 % 数组长度”来获得索引位置(i)。

【第四步】:将键值对添加到table数组中 当table[i]返回结果为null时,则键键值对封装为Node对象并存入到table[i]的位置。 当table[i]返回结果不为null时,则意味着table[i]存储的是单链表。我们首先遍历单链表,如果遍历出来节点的 key和添加键值对的key相同,那么就执行覆盖操作;如果遍历出来节点的key和添加键值对的key都不同,则就将键键 值对封装为Node对象并插入到单链表末尾。

手写HashMap的get方法

【第一步】:处理key为null的情况 如果查询的key就是null,则就在table数组索引为0的位置去查询。

【第二步】:获得key对象的哈希值 如果查询的key不是null,则就调用key的hashcode()方法,获得key的哈希值。

【第三步】:获得键值对的存储位置 因为获得的哈希值在数组合法索引范围之外,因此我们就需要将获得的哈希值转化为[0,数组长度-1]范围的整数, 那么可以通过取模法来实现,也就是通过“哈希值 % 数组长度”来获得索引位置(i)。

【第四步】:遍历单链表,根据key获得value值 如果table[i]返回的结果为null,则证明单链表不存在,那么返回null即可 如果table[i]返回的结果不为null时,则证明单链表存在,那么就遍历整个单链表。如果遍历出来节点的key和查询 的key相同,那么就返回遍历出来节点的value值;如果整个单链表遍历完毕,则遍历出来节点的key和查询的key都不 相等,那么就证明查询key在链表中不存在,则直接返回null即可。

关于HashMap的初始化容量的设置

当哈希表中的元素越来越多的时候,散列碰撞的几率也就越来越高(因为数组的长度是固定的),从而导致单链表过长,降低了哈希表的性能,此时我们就需要对哈希表进行扩容操作。 那么HashMap什么时候进行扩容呢?当执行put()操作的时候,如果HashMap中存储元素的个数超过“数组长度* loadFactor”的结果(loadFactor指的是负载因子,loadFactor的默认值一般为0.75),那么就需要执行数组扩容操作。 所谓的扩容操作,就是把数组的空间大小扩大一倍,然后遍历哈希表中元素,把这些元素重新均匀分散到扩容后的哈希表中。例如,默认情况下,数组大小为16,那么当HashMap中元素个数超过16*0.75=12的时候,就需要执行扩容操作,把数组的大小扩展为2*16=32,然后重新计算每个元素在数组中的位置,这是一个非常消耗性能的操作。 为了避免扩容带来的性能损坏,建议使用哈希表之前,先预测哈希表需要存储元素的个数,提前为哈希表中的数组设置合适的存储空间大小,避免去执行扩容的操作,进一步提升哈希表的性能。例如:我们需要存储1000个元素,按照哈希表的容量设置为2的整数次幂的思想,我们设置哈希表的容量为1024更合适。但是0.75*1024 < 1024,需要执行消耗性能的扩容操作,因此我们设置哈希表的容量为2048更加合适,这样既考虑了&的问题,也避免了扩容的问题。

17LinkedHashMap

18Hashtable

19Properties

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值