今天我们来聊聊面试必备之-------HashMap
大家也知道面试以及开发中我们常用HashMap键值对形式存储元素,那么HashMap底层是怎么实现的吗?
一张图带你走进面试常问知识点
1、JDK8与JDK7中的HashMap有哪些改动?
-
1、jdk7是基于链表+数组实现,jdk8将链表长度大于8时转换为红黑树,红黑树大于6时转换成链表,基于链表与红黑树的相互转化,数组+链表+红黑树实现。
请看源码:
-
2、新节点插入链表的位置不同(jdk7是插入头节点,jdk8因为要遍历链表,所以把链表变为红黑树,采用插入尾节点)
图解插入顺序不同:
jdk7:hashcode值相同插入头节点:
-
3、哈希算法简化
jdk1.8源码:简化后的哈希算法(位运算、异或运算)
- 4、扩容的机制不同(resize的逻辑修改) 【jdk7会出现死循环,jdk8不会】
扩容机制:(hashcode值 & (lenth-1))
2、JDK8中为什么要使用红黑树?
链表:查询慢,增删快。
AVL树:查询快,增删慢。
红黑树:基于查询和增删都适中的优点,所以选择红黑树。
3、为什么重写对象的Equals方法时,要重写HashCode方法,跟HashMap有关系吗?
- 从hashmap存储结构理解,同个hashcode存储在同一个“桶”。
- HashMap在进行存储时,先进行判断两个键的HashCode值是否相同,若相同,存放在一个hash桶中,然后比较其值是否相同,若相同,则确定为同一对象。
- 如果不重写Hashcode,只重写equals,两个对象的值相同,但是hashcode不相同,这样就和同一个对象,hashcode必须相同产生歧义。
示例代码:
String s1 = new String("小明",23);
String s2 = new String("小明",23);
s1.equals(s2); //true,但是hashcode不同,不能确定为同一对象
所以重写对象的Equals方法时,必须要重写HashCode方法。
一般有约定
hashCode相同时,equals方法不一定返回true。
equals方法返回true时,hashCode一定相同。
4、HashMap是线程安全吗?遇到过ConcurrenModificationException异常吗?为什么会出现?如何解决?
HashMap线程不安全
HashMap<Integer,String> map = new HashMap<Integer,String>();
map.put(1,"张三");
map.put(2,"李四");
//使用迭代器遍历集合
Iterator<Integer> iterator = map.keySet().iterator();
while(iterator.hasNext()) {
Integer key = iterator.next();
if(key.equals(1)) {
map.remove(key);//错误
Iterator.remove(key);//正确
}
}
写在最后
推荐自己的Github地址:github.com/Lmobject
您的支持与关注是对作者最大的信任,写作容易,坚持不易。谢谢!!!
下一篇博客:手把手教你用数据结构实现---------HashMap