记录面试官把我问蒙的问题-hashMap实现原理

那些很简单我又不会的问题

上周面试,面试管问“知道hashMap怎么实现的吗?”,还好我小脑袋瓜灵光,反问道:“这个问题太简单了,能不能问个难点的?”,面试官说:“回去等通知吧”,好吧!回去等就回去等,出门就把他拉黑了。因为我这人是不可能给你机会否定我的!!!哈哈哈哈哈!!!!!但是该学的知识还得学,咳咳!!!到家我就开始百度。

  • 1.概述

HashMap是基于哈希表的Map接口的非同步实现。元素以键值对的形式存放,并且允许null键和null值,因为key值唯一(不能重复),因此,null键只有一个。另外,hashmap不保证元素存储的顺序,是一种无序的,和放入的顺序并不相同(此类不保证映射的顺序,特别是它不保证该顺序恒久不变)。HashMap是线程不安全的。

  • 2.继承关系
public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable

HashMap的扩容操作是一项很耗时的任务,所以如果能估算Map的容量,最好给它一个默认初始值,避免进行多次扩容。HashMap的线程是不安全的,多线程环境中推荐是ConcurrentHashMap

  • 3. 一张图表明结构

在这里插入图片描述
HashMap底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,就会初始化一个数组,当列表长度超过8时,就会转换为红黑树结构

  • 4.数据存储结构

以下是废话,别看

 HashMap类中的Node<K,V>类里有一个Node<K,V>next。那以Node<K,V>.next.next.next这种结构形式存储元素就是所说的链表,而Node<K,V>[ ]
 tab就是数组,tab所存储元素为每个链表的第一个元素。每个数组的位置就是一个哈希值,如果两个值哈希值一样,就会占用一个位置,他们就成了一个链表;Java8优化了这个地方,如果相同哈希值,链表的长度超过8,就从链表转换成红黑树,Node类是HashMap的一个静态内部类,实现了
 Map.Entry<K,V>接口。在调用put方法创建一个新的键值对时,会调用newNode方法来创建Node对象

HashMap内部结构是数组(Node[] table)和链表结合组成的复合结构,数组被分成一个个桶(bucket),通过哈希值决定键值对在这个数组的寻址;哈希值相同的键值对,则以链表形式存储。需注意的是:链表大小超过阈值(TREEIFY_THRESHOLD = 8)时,链表就会被改造成树形结构。 下面示意图为一个简单的HashMap示意图:
在这里插入图片描述
HashMap由数组+链表+红黑树进行数据的存储
HashMap采用table数组存储Key-Value的,每一个键值对组成了一个Node节点(JDK1.7为Entry实体,因为jdk1.8加入了红黑树,所以改为Node)。Node节点实际上是一个单向的链表结构,它具有Next指针,可以连接下一个Node节点,以此来解决Hash冲突的问题

  • 5 HashMap实现存储和读取

put操作所对应的实现流程如下图所示:
在这里插入图片描述
首先判断数组是否为空,如果是,则进行初始化。
其次,根据**(n - 1) & hash**求出要添加对象所在的索引位置,判断此索引的内容是否为空,如果是,则直接存储,
如果不是,则判断索引位置的对象和要存储的对象是否相同,首先判断hash值知否相等,在判断key是否相等。(1.两个对象的hash值不同,一定不是同一个对象。2.hash值相同,两个对象也不一定相等)。如果是同一个对象,则直接进行覆盖,返回原值。
如果不是,则判断是否为树节点对象,如果是,直接添加
当既不是相同对象,又不是树节点,直接将其插入到链表的尾部。在进行判断是否需要进行树化。
最后,判断hashmap的size是否达到阈值,进行扩容resize()处理。
resize()扩容操作
当hashmap中的元素越来越多的时候,碰撞的几率也就越来越高(因为数组的长度是固定的),所以为了提高效率,就要对hashmap的数组进行扩容,而在hashmap数组扩容之后,最消耗性能的点就出现了:原数组中的数据必须重新计算其在新数组中的位置,并放进去,这就是resize。
那么hashmap什么时候进行扩容呢?当hashmap中的元素个数超过数组大小loadFactor时,就会进行数组扩容,loadFactor的默认值为0.75,也就是说,默认情况下,数组大小为16,那么当hashmap中元素个数超过160.75=12的时候,就把数组的大小扩展为2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知hashmap中元素的个数,那么预设元素的个数能够有效的提高hashmap的性能
来看看这张图
在这里插入图片描述
好了,接下来你可以去搜索一下 HashMap+HashSet+Hashtable的区别,希望下个面试官的问题稍微有点难度,这一下就学会了,多没意思!!!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值