在程序员这一职业中,集合是咱们使用频率至关高的一个工具,而其中的 HashMap,则更是咱们用以处理业务逻辑的好帮手,同时 HashMap的底层实现和原理,也成了面试题中的常客。程序员
下面我为你们总结了6道面试题,能够帮助你拿下99%的面试官没问题web
由于JDK7中是用数组+链表来做为底层的数据结构的,可是若是数据量较多,或者hash算法的散列性不够,可能致使链表上的数据太多,致使链表过长,考虑一种极端状况:若是hash算法不好,全部的元素都在同一个链表上。那么在查询数据的时候的时间复杂度和链表查询的时间复杂度差很少是同样的,咱们知道链表的一个优势是插入快,可是查询慢,因此若是HashMap中出现了很长的链表结构会影响整个HashMap的查询效率,咱们使用HashMap时插入和查询的效率是都要具有的,而红黑树的插入和查询效率处于彻底平衡二叉树和链表之间,因此使用红黑树是比较合适的。面试
首先,咱们须要知道HashMap为何须要扩容,道理很简单,HashMap底层是用数组+链表实现的,而数组是预先就已经分配好内存的,若是须要对数组进行扩容,须要从新开辟一个新的数组再将旧数组上的元素进行转移,若是不进行扩容,那么会致使HashMap的链表过长,查询效率下降,因此须要对数组进行扩容。算法
在JDK7中,HashMap扩容的条件是 (size >= threshold) && (null !=table[bucketIndex]) , size 为HashMap当前的容量, threshold 初始化值为12, table[bucketIndex] 表明所put进来的key所对应的数组上的元素,因此在JDK7中扩容条件是当当Put操操做传入的 做传入的Key值所对应的数组位置上不为空时而且当前容量大于等于了扩容的阈值时才进行扩容 值所对应的数组位置上不为空时而且当前容量大于等于了扩容的阈值时才进行扩容,JDK7中的扩容思路是:开辟一个新的数组,数组大小为原数组的两倍,而后再将数组上的链表与元素转移到新数组上,此过程可能会出现死锁。数组
JDK8中的扩容条件比JDK7中要少,只有当前容量大于等于了扩容的阈值时才进行扩容 当前容量大于等于了扩容的阈值时才进行扩容,而且扩容的思路也发生了变化,思路比较复杂。安全
跟HashMap有关系,或者说由于HashMap中用到了对象的hashcode方法因此会有关系,由于咱们若是在设计两个对象相等的逻辑时,若是只重写Equals方法,那么一个类有两个对象A1,A2,他们的A1.equals(A2)为true,A1.hashcode和A2.hashcode不同,当将A1和A2都做为HashMap的key时,HashMap会认为它两不相等,由于
HashMap在判断key值相不相等时会判断key的hashcode是否是同样,hashcode同样相等,因此在这种场景下会出现咱们认为这两个对象相等,可是hashmap不这么认为,因此会有问题。数据结构
HashMap的扩容机制是很影响效率的,因此若是事先能肯定有多少个元素须要存储,那么建议在初始化HashMap时对数组的容量也进行初始化,防止扩容。svg
HashMap中使用了对象的hashcode方法,并且很关键,因此再重写对象的equals时建议必定要重写hashcode方法。工具
若是是用对象做为HashMap的key,那么请将对象设置为final,以防止对象被从新赋值,由于一旦从新赋值其实就表明了一个新对象做为了key,由于两个对象的hashcode可能不一样。学习
HashMap 是非线程安全的,HashTable 是线程安全的;HashTable 内部的方法基本都通过 synchronized修饰
由于线程安全的问题,HashMap 要比 HashTable 效率高一点。另外,HashTable 基本被淘汰,不要在代码中使用它
HashMap 中,null 能够做为键,这样的键只有一个,能够有一个或多个键所对应的值为 null。可是在HashTable 中 put 进的键值只要有一个 null,直接抛出 NullPointerException。
JDK1.8 之后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减小搜索时间。Hashtable 没有这样的机制。
提莫在这里也还整理了一些平时本身学习的技术文档与群友平时去面试的面试资料。
若是看完后对你有帮助,记得点赞支持一下哦!
Ps:有须要的小伙伴能够点击直接进入:暗号:csdn,免费获取。
面试专题文档。
技术文档
真实大厂面经
学海无涯,咱们一块儿勉力前行