白话讲hashMap
来源:互联网 发布:各省人口普查数据 编辑:程序博客网 时间:2024/06/02 04:47
学了几天hashmap,收获很大。但是我想用自己的大白话说一边。各位看官仔细看,有不对还请提出。感激不尽!
如果你能找到本文的疏漏之处,说明你对hashmap有了更深的理解;
说起hashMap的时候。必须提一下hashtable,因为hashmap是hashtable的轻量级实现,他继承了hashtable除了多线程方面的几乎所有的内容,并且hashmap在单线程的效率比hashTable高一点,原因是hashmap不需要进行同步锁的维护,数据更新也不需要去检测;另外hashmap可以接受null作为键和值,这估计是他的设计者认为null在逻辑中也是可以有意义的;另外,hashmap实现的是map接口,而hashtable是基于陈旧的dictionary类;
当然了,hashmap在线程安全上比不上hashtable,如果你想在多线程中使用hashmap,必须要自己加入同步方法;然而jdk提供一个叫做ConcurrentHashMap的类,相比于hashtable中所有的线程去竞争同一把锁,它在多线程中使用多段锁,每一段锁保护一个fragment,大大缓解了高并发中线程竞争,从而提高了效率。
hashtable已经是一个过时类了,现在很少在代码中见到了。
接下来说一说hashmap的数据结构。hashmap在查询时候的时间复杂度是O(1),原因是他像我们使用数组时一样,直接通过下标去找要得到的值,这一定比挨个查找的O(n)快的多得多;
hashmap在细节上是通过将key对应的对象进行hashcode(),得到的这个值同模map长度后得到了key所对应的value在JVM的地址,直接从地址中取数据就可以了;
接下来讲一下hashcode()散列函数,刚才说到讲key对象转化为32位整形,很显然这带来了一个问题:碰撞冲突问题:如果2个不同的对象得到的hash值是一样的,怎么处理呢?
处理碰撞冲突的办法有很多,在这里Java采用的数组+链表的结构。
(最简单的是开放地址,线性探测法,但是它不能删除元素,只能添加删除标志;其实是再hash法,他是重新算一遍hash值,我感觉这种方法也会带来一些问题;还有就是建立一个公共溢出的地方,这个方法有点太粗暴了,我觉得他也只是暂时解决了冲突问题,如果在溢出区溢出很多呢?所以这几种不完美的解决冲突方案没有被采用,只是留作历史,让后来的人学习他的解决问题的思想)
当冲突发生后,Java会将加进来的value放在索引对应的地址后面的第一个位置,之前的第一个元素成为了第二个;查询的时候只需要在数组后面的链表中遍历一次就好了,这种思想当时确实解决了很多问题,当然他也带来了一个问题;Java中字符串的散列函数是很简单,他的乘法基数是31,对于这个很小的素数,有心人能够很容易的得到大量hash值相等的字符串,恶意地插入你的map中,你以为你的hashmap的复杂度是O(1),其实已经近似成了O(n).所以呢Java最新的1.8做了优化,当散链的长度大于8的时候,把散链重构成一颗红黑树,解决了上面的问题;当然他的代价是重构和维护红黑树的开销咯;
当然,hashmap中的第一难题是冲突解决,那第二难题就是扩容了。当hashmap的元素数目越来越接近的其最大容量时,不可避免,大量的冲突产生,大量的散链也产生了,查询的代价大大提高,这时候就有一个问题,什么标志作为拥挤的信号呢?Java中有一个加载因子,0.75,当元素数量大于最大容量*加载因子的时候进行扩容。hashmap的初始最大容量时16,以后每次扩容都乘2。这样做的好处是可以减少在长度变化后元素位置重新确定的代价。jdk1.8最新的优化:如果最大容量扩容前是2的N次方,那么去看元素hash的倒数第N+1位上是0还是1,如果是0,位置不需要调整,是1,就把索引的值+扩容前的最大容量,也样做的好处就是大概有一半的元素不需要移动,扩容的代价有一定的减少。
- 白话讲hashMap
- HashMap原理详讲
- 白话讲MyIsam和InnoDB的区别
- 白话讲MyIsam和InnoDB的区别
- 白话讲反射技术 --- 适合初学者入门引导
- 白话讲反射技术 --- 适合初学者入门引导
- 神经网络的白话版 (讲得比较白)
- 白话经典算法系列之五 归并排序的实现(讲的真好)
- JavaSE第五十二讲:HashSet 与HashMap源代码深度剖析
- 白话讲山寨SOA,少一些迷惑、多一些理解,你的程序架构SOA了吗?
- 白话讲山寨SOA,少一些迷惑、多一些理解,你的程序架构SOA了吗?
- HashMap
- HashMap
- HashMap
- HashMap
- HashMap
- HashMap
- HashMap
- 4.6 leetcode -6 recover-binary-search-tree
- Neon加速的Hello world例子
- win10安装tensorflow
- Java中为什么局部内部类只能访问方法中的final型成员变量
- 解压版 的Tomcat基本配置和安装
- 白话讲hashMap
- 9个offer/12家公司
- 深入理解Java类加载器(2):线程上下文类加载器
- Window_64位 Python环境搭建
- spark-streaming 编程(五)updateStateByKey
- android SDK 及 安卓开发环境配置
- nginx 编译参数详解
- 16、jQuery插件之Slick幻灯片插件
- 【剑指offer】面试题 50:第一个只出现一次的字符