HashMap是一个数据结构 实现Map接口 复杂度O(1) 线程非安全 key和value都可以为空  

以jdk7为例说明:

HashMap map=new HashMap();

在实例化以后 底层创建了长度是16的一维数组Entry[ ] table.

...可能已经执行过多次put

map.put(key1value1);

首先 调用key1所在类的hashCode()计算key1哈希值  此哈希值经过某种算法以后得到在Entry数组中的存放位置 

如果此位置上的数据为空 此时的key-value1添加成功

如果此位置上的数据不为空 (意味着此位置上存在一个或多个数据(以链表形式存在性能O(n))) 比较key1和已经存在的一个或者多个数据的哈希值 :

        如果key1的哈希值与已经存在的数据的哈希值都不相同 此时key1-value1添加成功。

        如果key1的哈希值和已经存在的某个数据的哈希值相同 继续比较 调用key1所在类的equals()方法。比较:

               如果equals()返回false:此时key1-value1添加成功

               如果equals()返回true:使用value1替换value2添加成功

       补充:关于情况2和情况3:此时key1-value和原来的数据以链表的方式存储

       在不断地添加过程中 会涉及到扩容问题 默认的扩容方式 扩容为原来的2倍 并将原有的数据复制过来

HashMap 数据结构底层是一个数组 通过hash算法来进行散列  根据key通过hash散列将key和value散列到比如位置2 

算法是否高级  是否可以降低碰撞

如果有碰撞 eg:2中存放了Entry(key,value,Entry next)解决碰撞的方法有俩种:

1.数组位置下挂载单向列表法:如果再来会往下压 形成链表

2、线性探测法:检测是否碰撞 碰撞之后查找周边  index+1到第三个位置  如果为空  就塞进去  (1.7及以下冲突的解决办法)

hash冲突概率很小 原因如下:

hash算法 将hashCode重写

1、 将数组长度length通常定义为2的指数  会与hashCode值进行取余运算 hashCode(key)与运算length-1

2、hash本身的大量位移操作来降低冲突概率

Java面试---HashMap的底层实现原理?

jdk8相较于jdk7底层实现方面的不同:

1.new HashMap():底层没有创建一个长度为16的数组

2.jdk8底层的数组是:Node[ ] 而非Entry[ ]

3.首次调用put()方法时 底层创建长度为16的数组

4.jdk7底层结构只有数组+链表 jdk8中底层结构: 数组+链表+红黑树。

   当数组的某一个索引位置上的元素以链表形式存在的数据个数>8且当前数组的长度>64时 

   此时索引位置上的所有数据改为红黑树存储。

相关文章: