HashMap的学习笔记

  HashMap的存储结构可以理解成数组+链表的结构,但是也不完全这样理解,因为数组查找元素的时候,需要进行遍历,严格来说,数组是一种顺序查找,当数组进行查找的时候,第一个元素找到的时间肯定比最后一个元素找到的时间短。而HashMap不同,因为存在一个Key,这个Key很关键,有了它就可以通过Hash函数找到散列的地址,在找到散列地址下的值,所以查找方式和数组不同。再接着理解链表的结构,Hash函数在计算散列值(也就是散列地址)的时候,会出现散列值相同的情况(碰撞),这个时候就会出现存储在同一个散列地址下的元素,这个解决办法就是通过链表的形式来进行存储多个同散列地址下的元素。

<分割线----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------分割线>

  但是HashMap的精华在于,散列值和索引值的求取。

 static int hash(int h) {
            h ^= (h >>> 20) ^ (h >>> 12);
            return h ^ (h >>> 7) ^ (h >>> 4);
        }
这是JDK1.7的Hash函数,利用Hash函数的若干次位运算,将HashCode变的松散,这样得到的Hash值可以达到充分的散列均匀。

 static int hash(object key) {
            int h;
            return (key == null)?0:(h = key.hashCode())^(h>>>16));
        }
这是JDK1.8的Hash函数,对1.7进行了优化,但是本质没有变化。



对索引值的求取,HashMap默认table(上面所说的类似数组的结构)的长度是16,在通过扰乱后的Hash值进行索引值的计算,也就是table的散列地址

static int indexFor(int h, int length) {
        return h & (length-1);
     }
这里需要说明的是length就是我们的table的长度,h就是我们扰乱后的Hash值,对正常来说,我们将Hash值与长度进行取模,就OK了,但是取余非常慢,我们还有更高效的相与&,进行位相与比取模要快上许多。到这里,还需要了解的是length最好是超过HashMap容量最小2的n次幂,至于为什么要进行减1,那是因为length是偶数的话,进行相与的时候,偶数二进制最低位为0这样会导致table【0】上会散列很多值,而且会使空间很浪费,减1后,奇数二进制最低为1,相与的时候,就会均匀分布。

另外,如果内存足够大,可以考虑使用大的length,这样可以使散列的更加松散,碰撞的几率更加低,get的速度就会更加快,但是会使迭代器的速度变慢,所以在使用的时候预估一下容量是非常有必要的。

<分割线----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------分割线>

还有一点,HashMap是线程不安全的,线程安全可以使用HashTable,那么HashMap线程不安全怎么体现?

如果我有两个线程同时put那么刚好碰撞到一起,那么对出现的覆盖的情况,有个put的数据会被覆盖丢失,当两个线程同时对HashMap进行扩容,在写入新的数据在扩容后的HashMap里面的时候,就会其他线程就会丢失数据。


以上就是我学习HashMap的心得,以后有新的会继续补充。。。

------------------------------------------------------------------------------------------------------------------------------------

2017/9/25  补充说明:HashMap在多线程下不安全,因为其中put方法会很容易发生死循环,具体信息学习笔记重HashMap死循环连接。

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、下4载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、下4载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值