HashMap常见面试题整理
花了三天时间来仔细阅读hashMap的源码,期间补了下不少数据结构的知识,刷了不少相关的面试题并进行了整理
1.谈一下HashMap的特性?
1.HashMap存储键值对实现快速存取,允许为null。key值不可重复,若key值重复则覆盖。
2.非同步,线程不安全。
3.底层是hash表,不保证有序(比如插入的顺序)
2.谈一下HashMap的底层原理是什么?
基于hashing的原理,jdk8后采用数组+链表+红黑树的数据结构。我们通过put和get存储和获取对象。当我们给put()方法传递键和值时,先对键做一个hashCode()的计算来得到它在bucket数组中的位置来存储Entry对象。当获取对象时,通过get获取到bucket的位置,再通过键对象的equals()方法找到正确的键值对,然后在返回值对象。
3.谈一下hashMap中put是如何实现的?
1.计算关于key的hashcode值(与Key.hashCode的高16位做异或运算)
2.如果散列表为空时,调用resize()初始化散列表
3.如果没有发生碰撞,直接添加元素到散列表中去
4.如果发生了碰撞(hashCode值相同),进行三种判断
4.1:若key地址相同或者equals后内容相同,则替换旧值
4.2:如果是红黑树结构,就调用树的插入方法
4.3:链表结构,循环遍历直到链表中某个节点为空,尾插法进行插入,插入之后判断链表个数是否到达变成红黑树的阙值8;也可以遍历到有节点与插入元素的哈希值和内容相同,进行覆盖。
5.如果桶满了大于阀值,则resize进行扩容
4.谈一下hashMap中什么时候需要进行扩容,扩容resize()又是如何实现的?
调用场景:
1.初始化数组table
2.当数组table的size达到阙值时即++size > load factor * capacity 时,也是在putVal函数中
实现过程:(细讲)
1.通过判断旧数组的容量是否大于0来判断数组是否初始化过
否:进行初始化
- 判断是否调用无参构造器,
- 是:使用默认的大小和阙值
- 否:使用构造函数中初始化的容量,当然这个容量是经过tableSizefor计算后的2的次幂数
是,进行扩容,扩容成两倍(小于最大值的情况下),之后在进行将元素重新进行与运算复制到新的散列表中
概括的讲:扩容需要重新分配一个新数组,新数组是老数组的2倍长,然后遍历整个老结构,把所有的元素挨个重新hash分配到新结构中去。
PS:可见底层数据结构用到了数组,到最后会因为容量问题都需要进行扩容操作
5.谈一下hashMap中get是如何实现的?
对key的hashCode进行hashing,与运算计算下标获取bucket位置,如果在桶的首位上就可以找到就直接返回,否则在树中找或者链表中遍历找,如果有hash冲突,则利用equals方法去遍历链表查找节点。
6.谈一下HashMap中hash函数是怎么实现的?还有哪些hash函数的实现方式?
对key的hashCode做hash操作,与高16位做异或运算
还有平方取中法,除留余数法,伪随机数法
7.为什么不直接将key作为哈希值而是与高16位做异或运算?
因为数组位置的确定用的是与运算,仅仅最后四位有效,设计者将key的哈希值与高16为做异或运算使得在做&运算确定数组的插入位置时,此时的低位实际是高位与低位的结合,增加了随机性,减少了哈希碰撞的次数。
HashMap默认初始化长度为16,并且每次自动扩展或者是手动初始化容量时,必须是2的幂。
8.为什么是16?为什么必须是2的幂?如果输入值不是2的幂比如10会怎么样?
https://blog.csdn.net/sidihuo/article/details/78489820
https://blog.csdn.net/eaphyy/article/details/84386313
1.为了数据的均匀分布,减少哈希碰撞。因为确定数组位置是用的位运算,若数据不是2的次幂则会增加哈希碰撞的次数和浪费数组空间。(PS:其实若不考虑效率,求余也可以就不用位运算了也不用长度必需为2的幂次)
2.输入数据若不是2的幂,HashMap通过一通位移运算和或运算得到的肯定是2的幂次数,并且是离那个数最近的数字
9.谈一下当两个对象的hashCode相等时会怎么样?
会产生哈希碰撞,若key值相同则替换旧值,不然链接到链表后面,链表长度超过阙值8就转为红黑树存储
10.如果两个键的hashcode相同,你如何获取值对象?
HashCode相同,通过equals比较内容获取值对象
11."如果HashMap的大小超过了负载因子(load factor)定义的容量,怎么办?
超过阙值会进行扩容操作,概括的讲就是扩容后的数组大小是原数组的2倍,将原来的元素重新hashing放入到新的散列表中去。
12.HashMap和HashTable的区别
相同点:都是存储key-value键值对的
不同点:
- HashMap允许Key-value为null,hashTable不允许;
- hashMap没有考虑同步,是线程不安全的。hashTable是线程安全的,给api套上了一层synchronized修饰;
- HashMap继承于AbstractMap类,hashTable继承与Dictionary类。
- 迭代器(Iterator)。HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException。
- 容量的初始值和增加方式都不一样:HashMap默认的容量大小是16;增加容量时,每次将容量变为"原始容量x2"。Hashtable默认的容量大小是11;增加容量时,每次将容量变为"原始容量x2 + 1";
- 添加key-value时的hash值算法不同:HashMap添加元素时,是使用自定义的哈希算法。Hashtable没有自定义哈希算法,而直接采用的key的hashCode()。
13.请解释一下HashMap的参数loadFactor,它的作用是什么?
loadFactor表示HashMap的拥挤程度,影响hash操作到同一个数组位置的概率。默认loadFactor等于0.75,当HashMap里面容纳的元素已经达到HashMap数组长度的75%时,表示HashMap太挤了,需要扩容,在HashMap的构造器中可以定制loadFactor。
14.传统hashMap的缺点(为什么引入红黑树?):
JDK 1.8 以前 HashMap 的实现是 数组+链表,即使哈希函数取得再好,也很难达到元素百分百均匀分布。当 HashMap 中有大量的元素都存放到同一个桶中时,这个桶下有一条长长的链表,这个时候 HashMap 就相当于一个单链表,假如单链表有 n 个元素,遍历的时间复杂度就是 O(n),完全失去了它的优势。针对这种情况,JDK 1.8 中引入了 红黑树(查找时间复杂度为 O(logn))来优化这个问题。
15. 平时在使用HashMap时一般使用什么类型的元素作为Key?
选择Integer,String这种不可变的类型,像对String的一切操作都是新建一个String对象,对新的对象进行拼接分割等,这些类已经很规范的覆写了hashCode()以及equals()方法。作为不可变类天生是线程安全的,
源码解析阅读:
2. https://juejin.im/post/5ad40593f265da23750759ad
3. https://juejin.im/post/5afbff9451882542877353dd
4. https://blog.csdn.net/panweiwei1994/article/details/76555359#commentBox
5.
更多关于hashMap集合的面试题:
https://zhuanlan.zhihu.com/p/32355676
https://zhuanlan.zhihu.com/p/40760616
https://juejin.im/post/5a99544ef265da23a334ab6c
https://www.jianshu.com/p/7af5bb1b57e2
https://baiqiantao.github.io/Java/%E9%9B%86%E5%90%88/3AFbAb/
HashMap常见面试题整理的更多相关文章
- java面试题之----HashMap常见面试题总结
“你用过HashMap吗?” “什么是HashMap?你为什么用到它?” 几乎每个人都会回答“是的”,然后回答HashMap的一些特性,譬如HashMap可以接受null键值和值,而Hashtable ...
- 【持续更新】JavaScript常见面试题整理
[重点提前说]这篇博客里的问题涉及到了了JS中常见的的基础知识点,也是面试中常见的一些问题,建议初入职场的园友Mark收藏,本文会持续更新~ 1. 引入JS的三种方式 1.在HTML标签中直接使用,直 ...
- 常见面试题整理--Python概念篇
希望此文可以长期更新并作为一篇Python的面试宝典.每一道题目都附有详细解答,以及更加详细的回答链接.此篇是概念篇,下一篇会更新面试题代码篇. (一).这两个参数是什么意思:*args,**kwar ...
- Java 常见面试题整理
操作系统 说一下线程和进程,它们的区别 同步和异步的区别 阻塞和非阻塞的区别 操作系统中死锁的四个必要条件 mmap和普通文件读写的区别,mmap的注意点 CPU密集型和IO密集型的区别 Linux ...
- HashMap常见面试题
1.HashMap底层是通过什么来实现的? 在JDK1.7中是通过数组+链表来实现的: 在JDK1.8中是通过数组+链表+红黑树来实现的 2.HashMap在JDK1.8中为什么使用红黑树? 为了弥补 ...
- 整理的最全 python常见面试题(基本必考)
整理的最全 python常见面试题(基本必考) python 2018-05-17 作者 大蛇王 1.大数据的文件读取 ① 利用生成器generator ②迭代器进行迭代遍历:for line in ...
- 整理的最全 python常见面试题
整理的最全 python常见面试题(基本必考)① ②③④⑤⑥⑦⑧⑨⑩ 1.大数据的文件读取: ① 利用生成器generator: ②迭代器进行迭代遍历:for line in file; 2.迭代 ...
- java常见面试题及答案
java常见面试题及答案 来源 https://blog.csdn.net/hsk256/article/details/49052293 来源 https://blog.csdn.net/hsk25 ...
- Mybatis常见面试题
Mybatis常见面试题 #{}和${}的区别是什么? #{}和${}的区别是什么? 在Mybatis中,有两种占位符 #{}解析传递进来的参数数据 ${}对传递进来的参数原样拼接在SQL中 #{}是 ...
随机推荐
- vuex中使用对象展开运算符
使用场景 当需要进行vuex进行数据状态管理的时候,会使用到mapGetters,mapState,还有自身的计算属性的时候,这个时候就会用到这个了! 1.首先需要安装 npm install bab ...
- apache出现forbidden
<Directory /> Options FollowSymLinks AllowOverride All Order deny,allow allow from all Require ...
- code forces 1173 C. Nauuo and Cards
本文链接:https://www.cnblogs.com/blowhail/p/10990833.html Nauuo and Cards 原题链接:http://codeforces.com/con ...
- C++学习书籍推荐《C++标准库(第一版)》下载
百度云及其他网盘下载地址:点我 编辑推荐 <C++标准程序库:自修教程与参考手册>编辑推荐:C++标准程序库提供了一组通用类别(classes)和界面(interfaes),可大幅扩充C+ ...
- java接口自动化(一) - 接口自动化测试整体认知 - 开山篇(超详解)
简介 了解什么是接口和为什么要做接口测试.并且知道接口自动化测试应该学习哪些技术以及接口自动化测试的落地过程.其实这些基本上在python接口自动化的文章中已经详细的介绍过了,不清楚的可以过去看看.了 ...
- [NOIP2013]华容道 题解(搜索)
[NOIP2013]华容道 [题目描述] 这道题根据小时候玩华容道不靠谱的经验还以为是并查集,果断扑街.考后想想也是,数据这么小一定有他的道理. 首先由于是最小步数,所以BFS没跑了.那么我们大可把这 ...
- MMM 数位dp学习记
数位dp学习记 by scmmm 开始日期 2019/7/17 前言 状压dp感觉很好理解(本质接近于爆搜但是又有广搜的感觉),综合了dp的高效性(至少比dfs,bfs优),又能解决普通dp难搞定的问 ...
- 跨站脚本攻击(存储型xss)笔记(二)
测试目标字段:页面下方的红色框位置. 由于编辑状态是编辑器,所以有可能出现跨站! 我插了个input然而并没有当代码执行 可能有些测试人员就认为被过滤掉了,因为尝试了各种尖括号.js事件.转义.编码等 ...
- 通过自研数据库画像工具支持“去O”评估
“去O”,是近些年来一直很火的一个话题,随之也产生了各种疑惑,包括现有数据库评估.技术选型等.去O是项系统工程,需要做好充分的评估.本文通过自研工具,生成数据库画像,为去O评估提供一手数据,希望给大家 ...
- Redis 学习笔记(篇六):数据库
Redis 是一个使用 C 语言编写的 NoSql 的数据库,本篇就讲解在 Redis 中数据库是如何存储的?以及和数据库有关的一些操作. Redis 中的所有数据库都保存在 redis.h/redi ...