简单介绍
HashMap是双列集合Map接口下的实现类,jdk1.8之前其数据结构是数组+链表、jdk1.8之后是数组+链表+红黑树,是线程不安全的,
原理图:
HashMap放值的过程
:
HashMap先是根据Hash算法算出key的hashcode码值,存储对象为 Map.Entry,entry 对象包含四个信息,key、value、hash 值、 链表地址值,因为存储元素时,会根据 hash 值%16 计算元素存储数组中的索引位置,找到对应的数组索引下标,如果当前索引没有存放链表entry实体,则将当前链表存放进去,如果已经存放了一个具有相同hashcode码值的链表,这就发生了Hash碰撞,即两个元素不相同,却有一样的 hash 值,HashMap采用的是拉链法解决hash碰撞的,将元素在数组中存入链表中,以链表的形式进行元素的存储,第一个 entry 存在链表顶端,再有 hash 值一致的 entry 存入,则链接在第一个元素之后,在jdk8以后对链表进行了改进,当链表长度大于8的时候会转化成红黑树,而红黑树的数量小于6是会自动转化为链表。
HashMap取值的过程
:
根据传进来的key对其进行Hash算法获取hashcode值,找到对应的数组索引下标,如果当前索引直接命中则返回value值,如果发生Hash碰撞,因为重写了equals方法其真实的每一个key值都是唯一的,则通过重写的key.equals(k)去查找具体的entry实体,直到找到返回其value值。
HashMap中几个重要的属性:
重要名词
Hash算法:Hash 算法是一个广义的算法,也可以认为是一种思想,使用Hash算法可以提高存储空间的利用率和数据的查询效率。哈希(Hash)也称为散列,就是把任意长度的输入,通过 Hash 算法,变换成固定长度的输出,这个输出值就是散列值
Hash碰撞: hash算法是把任意长度的较长字符串变成固定长度的较短字符串,肯定会存在若干个key通过hash算法得到的hash值是完全相同的,这就叫hash碰撞。
面试问题
1、一问
- 你看过HashMap源码吗,知道底层的原理吗
- 为什么使用数组+链表
- 用LinkedList代替数组可以吗
- 既然是可以的,为什么不用反而用数组
2、二问
- 知道HashMap的put元素的过程是什么样吗?
- 知道get过程是是什么样吗?
- 你还知道哪些的hash算法?
- 说一说String的hashcode的实现
3、三问
- 知道jdk1.8中hashmap改了什么吗。
- 说一下为什么会出现线程的不安全性
- 为什么在解决hash冲突时候,不直接用红黑树,而是先用链表,再用红黑树
- 当链表转为红黑树,什么时候退化为链表
4、四问
- HashMap在并发环境下会有什么问题
- 一般是如何解决的
5、五问
- key可以是null吗,value可以是null吗
- 一般用什么作为key值
- 用可变类当Hashmap1的Key会有什么问题
- 让你实现一个自定义的class作为HashMap的Key该如何实现
参考博客:
看完还不懂HashMap算我输
HashMap底层实现原理/HashMap与HashTable区别/HashMap与HashSet区别
通俗解释hash碰撞是什么以及如何解决