靠一个HashMap的讲解打动了头条面试官,我的秘诀是

本文详细剖析了HashMap的源码,从预备知识如位运算、ArrayList、LinkedList、RedBlackTree、HashTable讲起,重点分析了HashMap的构造方法、哈希值计算、put和get流程、扩容机制以及JDK7与JDK8的区别。文章揭示了HashMap在面试中的重要性,以及为何理解其工作原理能打动面试官。

 

最近收集了一份github标星81.6k的Java面试突击手册,文末查看

关注 转发+转发+转发 私信回复关键词 【学习】即可获取~

预备知识

位运算知识

位运算操作是由处理器支持的底层操作,底层硬件只支持01这样的数字,因此位运算运行速度很快。尽管现代计算机处理器拥有了更长的指令流水线和更优的架构设计,使得加法和乘法运算几乎与位运算一样快,但是位运算消耗更少的资源。常用的位运算如下:

位与 &

(1&1=1 1&0=0 0&0=0)

位或 |

(1|1=1 1|0=1 0|0=0)

位非 ~

( ~1=0 ~0=1)

位异或 ^

(1^1=0 1^0=1 0^0=0)

有符号右移 >>

在执行右移操作时,若参与运算的数字为正数,则在高位补0;若为负数,则在高位补1。

无符号右移 >>>

无论参与运算的数字为正数或为负数,在执运算时,都会在高位补0。

左移

对于左移是没有正数跟负数这一说的,因为负数在CPU中是以补码的形式存储的,对于正数左移相当于乘以2的N次幂。

敲重点:上面的重重都是简单的只是为了引出下面的结论:

a % (Math.pow(2,n)) 等价于 a&( Math.pow(2,n)-1)

比如a%16最终的结果一定是0~15之间的数字,而a&1111正好把a除16后的余数有效的现实出来了因为如果是1 1111这样的话最前面一位其实代表的16,也就是说二进制从倒数第五位开始只要出现了1那绝对代表的是16的倍数。 结论:位运算比除法运算在运行效率上更高,对一个数取余尽量用a&二进制数这样可以更好的提速。

ArrayList

我们知道ArrayList是一个数组队列,相当于动态数组。与Java中的基本数组相比,它的容量能动态增长。它具有以下几个重点。

ArrayList 实际上是通过一个数组去保存数据的。当我们构造ArrayList时;若使用默认构造函数,则ArrayList的默认容量大小是10

当ArrayList容量不足以容纳全部元素时,ArrayList会重新设置容量:原来容量的1.5倍。

ArrayList的克隆函数,即是将全部元素克隆到一个数组中。

克隆的底层是System.arraycopy(0,oldsrc,0,newsrc,length);

ArrayList实现java.io.Serializable的方式。当写入到输出流时,先写入“容量”,再依次写入“每一个元素”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。

优点:

根据下标遍历元素效率较高。

根据下标访问元素效率较高。

在数组的基础上封装了对元素操作的方法。

这样的动态数组在内地地址上是空间连续的。

可以自动扩容。

缺点:

插入和删除的效率比较低。

根据内容查找元素的效率较低。

扩容规则:每次扩容现有容量的50%。

LinkedList

靠一个HashMap的讲解打动了头条面试官,我的秘诀是

双向链表每一个节点包含三部分(data,prev,next),它不要求空间是连续的。类似于节点跟节点之间通过前后两条线串联起来的。

ArrayList和LinkedList总结:

ArrayList是实现了基于动态数组的数据结构,LinkedList是基于链表结构。

对于随机访问的get和set方法,ArrayList要优于LinkedList,因为LinkedList要移动指针。

对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。

ArrayList使用在查询比较多,但是插入和删除比较少的情况,而LinkedList用在查询比较少而插入删除比较多的情况

RedBlackTree

首先你需要对二叉树有个了解,知道这是什么样子的一个数据组合方式,然后知道二叉树查找的时候缺点,可能发生数据倾斜。因此引入了平衡二叉树,平衡二叉树的左右节点深度之差不会超过1,查找方便构建麻烦,因此又出现了红黑树。红黑树是一种平衡的二叉查找树,是一种计算机科学中常用的数据结构,最典型的应用是实现数据的关联,例如map等数据结构的实现,红黑树重要特性是( 左节点 < 根节点 < 右节点) 红黑树有以下限制:

节点必须是红色或者是黑色

根节点是黑色的

所有的叶子节点是黑色的。

每个红色节点的两个子节点是黑色的,也就是不能存在父子两个节点全是红色

从任意每个节点到其每个叶子节点的所有简单路径上黑色节点的数量是相同的。

如果您对红黑树还不太了解推荐看下博主以前写的RBT

HashTable

Hash表是一种特殊的数据结构,它同数组、链表以及二叉排序树等相比较有很明显的区别,它能够快速定位到想要查找的记录,而不是与表中存在的记录的关键字进行比较来进行查找。这个源于Hash表设计的特殊性,它采用了==函数映射==的思想将记录的存储位置与记录的关键字关联起来,从而能够很快速地进行查找。评价函数的性能关键在于==装填因子==,以及如何合理的解决哈希冲突,具体的可看博主以前写的彻底搞定哈希表

HashMap源码剖析

概述

通常具备前面一些知识点的铺垫就可以很好的开展HashMap的讲解了,既然ArrayList,LinkedList,Red Black Tree各有优缺点,我们能不能集百家之长实现一个综合产物呢 === >HashMap,本文所以讲解都是基于JDK8。

HashMap的组成部分:数组 + 链表 + 红黑树。HashMap的主干是一个Node数组。Node是HashMap的基本组成单元,每一个Node包含一个key-value键值对。HashMap的时间复杂度几乎可以接近O(1)(如果出现了 哈希冲突可能会波动下),并且HashMap的空间利用率一般就是在40%左右。HashMap的大致图如下:

靠一个HashMap的讲解打动了头条面试官,我的秘诀是

PS:其中几个重要节点关系如下:

1.java.util.Map.Entry 这就是个interface定义了一些比较的接口函数。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值