HashMap的学习与面试题汇总

HashMap学习与分享

HashMap的存储逻辑图:

  

上图中可以看出在HashMap的底层使用的是(数组+链表),当链表长度超过8时,将链表转换为红黑树(从JDK1.8版本开始)

HashMap的底层设计思想:(按照自己的理解白话讲解)

1.链表的优势在于插入节点与删除节点

2.数组的优点是通过数组下标查找O(1)

HashMap底层所用到的就是将链表与数组相结合(Entry链表)

Java是一门面向对象的编程语言,万物皆对象

class Node<K,V>{
  private K key;
  private V value;
  private Node next;
}

3.那么数组的表示必然就是:

Node<K,V>[]

4.那么既然是数组,就不可能让其无限增大,所以要设置一个初始值大小

DefaultSize。。。

和上限大小

MaxSize。。。

5.那么数组存不下了怎么办,这里就要用到扩容,

假设初始大小是16,如果数组的大小不够用了,或者达到某个值了,需要扩容resize()

扩容是不是要有一个依据: 16 数组大小达到12的时候就要进行数组大小的扩容

Size > totalSize * 小于1的数 0.75

hashMap的扩容:当使用总容量大于总容量的3/4时,要进行数组扩容

6.链表的长度就可以无限增大了嘛,答案是错误的,链表的大小也是有一个限制的:

链表太长会严重影响效率
改变链表的结构
达到一个限制值之后,也需要一个改变

JDK1.8的时候,在链表的长度达到一个长度的时候就将其结构改成红黑树
链表长度大于8了就修改链表的结构,红黑树

7.对于一个Put进来的节点,要存储在数组或链表的哪里呢?

1.首先通过Hash函数来算出hash值,  (h = key.hashCode())^(h>>>16)  将key值得高16位与低16位做异或运算,目的是使得算出的hash值尽量分散,充分的将int的32位都应用起来了

2.(n-1)&hash函数-->得到下标,然后再存储进数组或链表即可。

3.每一次put都会判断列表的长度

HashMap的常见面试题:

1).HashMap的原理,内部数据结构
底层使用哈希表(数组+列表),当列表过长时会将列表转为红黑树已实现O(logn)时间复杂度内的查找

2).讲一下HashMap中的put方法过程:
1.对key求Hash值,来求标
2.如果没有碰撞直接放入槽中
3.如果发生了碰撞,以链表的方式放到链表的下方
4.如果链表的长度超过阈值(8) 就转成红黑树jdk1.8
5.如果节点已经存在就替换旧值
6.如果槽满了(容量*加载因子)0.75 就resize扩容

3).HashMap中hash函数怎么实现的?还有哪些hash的实现方式
1.高16bit不变,与低16位做异或运算得到hash值
2.(n-1)&hash函数-->得到下标
还有哪些Hash实现方法

4).HashMap怎么解决冲突的,讲一下扩容过程,假如一个值原来在数组中,现在移动了新数组,位置肯定改变了,那是什么定位到这个值在新数组中的位置的
1.将新节点加到列表后
2.容量扩充为原来的二倍,然后对每个节点计算哈希值
3.这个值只可能在两个地方,一个是原下标的位置,另一种在下标为《原下标+元容量》的位置

5).抛开HashMap,hash冲突有哪些解决方法
1.开放地址法
2.链地址法

6).针对Hashmap中某个Entry链太长,查找的复杂的可能达到O(n),怎么优化
1.将链表转换为红黑树,jdk1.8已经实现了(链表长度超过8的时候)

红黑树和链表有一个他们各自数量的节点,当节点数目小于6时要转换成链表,大于8时要把链表转换成红黑树

7).hashMap线程安全问题:

1.在多线程同时操作hashMap的时候,put方法没有设置同步方法,所以不是线程安全的,HashMap在并发执行put操作室会引发死循环,因为多线程会导致HashMap的Entry链表形成环,一旦成环,Entry的Next节点永远不能为空,产生死循环

2.HashTable是线程安全的,但是在并发情况下效率低下,原因是所有访问hashTable的线程都必须竞争同一把锁

3.为线程加锁会影响线程执行效率,使用ConcurrentHashMap:线程安全切高效的HashMap

ConcurrentHashMap简介:

假如一个容器中有多把锁,没把锁英语锁容器中的一部分数据,那么在多线程访问的容器里的不同数据段,线程之间不会存在锁竞争,从而可以有效地提高并发访问的效率,这就是ConCurrentHashMap的锁分段技术
首先将数据分成一段一段的存储
然后给每一段配一把锁
当一个线程占用锁访问其中一个段数据的时候,其他短的数据也能被其他线程所访问

猜你喜欢

转载自www.cnblogs.com/PoorGuy/p/10397346.html