700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Java面试必问之Hashmap底层实现原理(JDK1.7)

Java面试必问之Hashmap底层实现原理(JDK1.7)

时间:2024-01-21 08:46:55

相关推荐

Java面试必问之Hashmap底层实现原理(JDK1.7)

1. 前言

Hashmap可以说是Java面试必问的,一般的面试题会问:

Hashmap有哪些特性?Hashmap底层实现原理(get\put\resize)Hashmap怎么解决hash冲突?Hashmap是线程安全的吗?……今天就从源码角度一探究竟。笔者的源码是OpenJDK1.7

2. 构造方法

首先看构造方法的源码

由以上源码可知,Hashmap的初始容量默认是16, 底层存储结构是数组(到这里只能看出是数组, 其实还有链表,下边看源码解释)。基本存储单元是Entry,那Entry是什么呢?我们接着看Entry相关源码

由Entry源码可知,Entry是链表结构。综上所述,可以得出:Hashmap底层是基于数组和链表实现的

3. Hashmap中put()过程

我已经将put过程绘制了流程图帮助大家理解

先上put源码

上图中多次提到头插法,啥是 头插法 呢?接下来看 addEntry 方法

结合Entry类的构造方法,每次插入新元素的时候,将bucket原链表取出,新元素的next指向原链表,这就是 头插法 。为了更加清晰的表示Hashmap存储结构,再绘制一张存储结构图。

4. Hashmap中get()过程

get()逻辑相对比较简单,如图所示

我们来对应下get()源码

5. Hashmap中resize()过程

只要是新插入元素,即执行addEntry()方法,在插入完成后,都会判断是否需要扩容。从addEntry()方法可知,扩容后的容量为原来的2倍。

这里有个transfer()方法没讲,别着急,扩容时线程安全的问题出现在这个方法中,接下来讲解数组复制过程。

6. Hashmap扩容安全问题

大家都知道结果: 多线程扩容有可能会形成环形链表,这里用图给大家模拟下扩容过程。

首先看下单线程扩容的头插法

然后看下多线程可能会出现的问题

以下是源码,你仔细品一品

7. Hashmap寻找bucket位置

static int indexFor(int h, int length) {// 根据hash与数组长度mod运算 return h & (length-1);}

由源码可知, jdk根据key的hash值和数组长度做mod运算,这里用位运算代替mod。

hash运算值是一个int整形值,在java中int占4个字节,32位,下边通过图示来说明位运算。

想了解更多精彩内容,快来关注计算机java编程

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。