面试之HashMap

1.什么是集合框架

Java的集合主要有两个根接口Collection和Map派生出来的,Collection派生出来了三个子接口:List,Queue,Set。因此Java集合大致可分为List,Queue,Set,Map四种体系结构。

2.HashMap与TreeMap

HashMap是直接实现Map接口,而TreeMap是实现SortedMap接口的,所以两个还是有不同点。

3.HashSet与TreeSet

4.HashMap的底层数据结构

在jdk1.7和jdk1.8中底层实现是有所区别的。

在jdk1.7中,由“数组 + 链表”组成,数组是HashMap的主体,链表主要为了解决哈希冲突而存在的。

在jdk1.8中,由“数组 + 链表 + 红黑树”组成,当链表过长,会严重影响HashMap的性能,红黑树搜索的时间复杂度为O(logn),而链表为O(n),因此在jdk1.8引入了红黑树,在达到一定条件之后会进行转换:

  • 当链表超过8且数据总量超过64才会转红黑树
  • 将链表转换成红黑树前会进行判断,如果当前数组的长度小于64,那么会选择先进性扩容,而不是转为红黑树,以减少搜索时间。 

5.HashMap插入数据的原理

  1. 首先根据key值计算哈希值,找到该元素在数组中存储的下标
  2. 如果数组为空,则首先调用resize初始化数组
  3.  如果没有哈希冲突,则直接放在对象下标的位置
  4. 如果冲突了,且key值存在,则直接覆盖掉value值
  5. 如果冲突之后发现该节点是红黑树,就将这个节点挂在红黑树上
  6. 如果冲突后是链表,判断该链表是否大于8,如果大于8并且数组容量小于64,就进行扩容;如果链表大于8并且数组容量大于64,则将这个结构转为红黑树;否则,链表插入键值对,如果key存在,就覆盖掉value.

 6.Hash初始容量大小的设置以及扩容

6.1初始容量的大小

在new 一个HashMap时候,因为它使用的是懒加载的方式,所以并不会立即初始化数组。而是等到第一次添加元素的时候,才会初始化数组。一般如果不传入参数,初始默认大小为16,负载因子为0.75,但是如果我们传入参数时,并不会按照所传入的参数进行初始化,首先判断所传入的参数是不是2的n次方,如果是则按照所传参数初始化,如果不是2的n次方,那么就会按照大于你设置的那个值但是最接近你设置的那个值的2的n次方进行设置。例如:传入10,不是2的n次方,2^4刚好是大于10且为2的n次方,所以初始化大小为16.

6.2扩容

在什么时候进行扩容呢?

threshold = 容量 * 加载因子。所以当键值对的数量大于threshold时候,此时需要扩容,扩容是是将原来数组扩大2倍,并将原来数组的对象放入到新的数组当中。

7.HashMap和HashTable

HashMap不是线程安全的:

HashMap是map接口的子类,是将键映射到值的对象,其中键和值都是对象,并且不能包含重复键,但可以包含重复值。HashMap允许null key和null value,而hashtable不允许。

HashTable是线程安全。

HashMap是Hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区别在于HashMap允许空(null)键值(key),由于非线程安全,效率上可能高于Hashtable。

最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多个线程访问Hashtable时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。 Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差。

8.ConcurrentHashMap

虽然jdk提供了HashMap和HashTable但是如何同时满足线程安全和效率高呢,显然这两个都无法满足,所以就诞生了ConcurrentHashMap神器,让我们应用于高并发场景。

该神器采用了分段锁策略,通过把整个Map分成N个Segment(类似HashTable),可以提供相同的线程安全,效率提升N倍,默认提升16倍。ConcurrentHashMap的优点就是HashMap和HashTable的缺点,当然该神器也是不支持键值为null的

9.解决hash冲突的方法有哪些,HashMap用的哪种方法

解决hash冲突的方法有:开放定址法,再哈希法,链地址法,建立公共溢出区,HashMap采用的是链地址法。

  • 开放定址法:也称为再散列法,基本思想就是,如果p = H(key)出现冲突时,则以p为基础,再次hash,p1 = H(p),如果p1再次冲突,则以p1为基础,以此类推,直到找到一个不冲突的哈希地址。因此开放定址法所需要的hash表长度大于等于所需要存放的元素。
  • 再哈希法:称为双重散列或者多重散列,提供多个不同的hash函数,p1 = H1(key)发生冲突时,再使用不同的哈希函数计算p2  = H2(key),直到没有冲突位置。此方法虽然不会产生堆积,但是计算时间比较长
  • 链地址法:将hash值相同的额元素构成一个单链表,并将单链表的头指针放在哈希表的第i个单元,查找,插入和删除主要在链表中进行。适用于频繁的插入和删除
  • 建立公共溢出区:将哈希表分为公共表和溢出表,当发生溢出时,所有的溢出数据放在溢出表

10.一般用什么作为HashMap的key

一般使用Integer,String 这种不可变类型作为HashMap的kay,而且String最为常用。

  • 因为字符串是不可变的,所在在它被创建的时候hashcode就已经被缓存了,不需要重新计算,这就是String常用作key的原因
  • 因为获取对象的时候要用到equals()和hashcode()方法,那么键对象正确的重写这两个方法非常重要,这些类已经很规范的重写了hashcode()和equals();

11HashMap为什么线程不安全

  • 多线程下扩容死循环:在jdk1.7中的HashMap使用头插法插入元素,在多线程的环境下,扩容的时候有可能导致环形链表的出现,形成死循环;因此在jdk1.8中,使用尾插法插入元素,在扩容时候会保持链表元素的原本顺序,不会出现环形链表的问题
  • 多线程下put可能导致元素丢失:多线程同时执行put元素时候,如果计算出来的索引值是相同的,那会造成前一个put操作会被后一个put操作所覆盖,从而导致元素的丢失
  • put和get并发,可能为空:在线程1执行put操作时候,需要扩容,扩容之后元素拥有了新的位置,导致线程2在执行get操作的时候可能获取为Null值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/59584.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

线上通过Nginx部署前端工程,并且配置SSL

介绍、为了更好的帮助大家学习,减少歧义,IP地址我就不隐藏了,公司也是我自己的公司。你们就别来攻击了。 下面给出步骤: 一、前期准备工作 通过在目标服务器上安装宝塔面板、安装redis、mysql、nginx、jdk环境等 1、 2、前端工程通过npm run build 打…

【Elasticsearch】Elasticsearch快速入门,掌握这些刚刚好!(官网入门案例)

文章目录 1. 简介2. 相关概念3. 安装4. 集群状态查看5. 索引操作6. 文档操作7. 数据搜索数据准备搜索入门(match_all)条件搜索(match)组合搜索(bool)过滤搜索(filter)搜索聚合(aggs) 8. 参考资料 本文的主要功能是带领从0到1入门Elasticsearch的基础使用,重点是Elas…

python机器学习(六)决策树(上) 构造树、信息熵的分类和度量、信息增益、CART算法、剪枝

决策树算法 模拟相亲的过程,通过相亲决策图,男的去相亲,会先选择性别为女的,然后依次根据年龄、长相、收入、职业等信息对相亲的另一方有所了解。 通过决策图可以发现,生活中面临各种各样的选择,基于我们的…

招投标系统简介 企业电子招投标采购系统源码之电子招投标系统 —降低企业采购成本 tbms

​功能模块: 待办消息,招标公告,中标公告,信息发布 描述: 全过程数字化采购管理,打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力,为外…

视频汇聚平台EasyCVR视频广场侧边栏支持拖拽

为了提升用户体验以及让平台的操作更加符合用户使用习惯,我们在EasyCVR v3.3版本中,支持面包屑侧边栏的广场视频、分组列表、收藏这三个模块拖拽排序,并且该操作在视频广场、视频调阅、电子地图、录像回放等页面均能支持。 TSINGSEE青犀视频…

python解析帆软cpt及frm文件(xml)获取源数据表及下游依赖表

#!/user/bin/evn python import os,re,openpyxl 输入:帆软脚本文件路径输出:帆软文件检查结果Excel#获取来源表 def table_scan(sql_str):# remove the /* */ commentsq re.sub(r"/\*[^*]*\*(?:[^*/][^*]*\*)*/", "", sql_str)# r…

探索硬件王国:计算机硬件信息一览(使用powershell获得计算机硬件信息)

获得运行权限: 请确保在运行脚本文件之前,设置了适当的执行策略。如果需要,可以使用 Set-ExecutionPolicy 命令更改执行策略。例如,可以使用以下命令将执行策略设置为 RemoteSigned: Set-ExecutionPolicy RemoteSign…

云真机调研

1. 主流云真机 目前市面上主流的远程真机服务商有:Testin云测、百度MTC、TestBird、精灵云测、腾讯Wetest、泽众云等,设备上基本覆盖Android、iOS和鸿蒙等主流设备,通过远程真机可以进行手工测试、代码调试、自动化脚本录制及执行等 2. testin 登录-云测,助力产业…

通用指令(汇编)

一、数据处理指令1)数学运算数据运算指令的格式数据搬移指令立即数伪指令加法指令带进位的加法指令减法指令带借位的减法指令逆向减法指令乘法指令数据运算指令的扩展 2)逻辑运算按位与指令按位或指令按位异或指令左移指令右移指令位清零指令 3&#xff…

【枚举+trie+dfs】CF514 C

Problem - 514C - Codeforces 题意: 思路: 其实是trie上dfs的板题 先把字符串插入到字典树中 对于每次询问,都去字典树上dfs 注意到字符集只有3,因此如果发现有不同的字符,去枚举新的字符 Code: #in…

学习单片机的秘诀:实践与坚持

在学习单片机时,将实践与学习结合起来是一个很好的方法。不要一上来就死磕指令和名词,而是边学边做实验,循序渐进地理解和应用指令。通过实验,你能亲身感受到指令的控制效果,增强对单片机的理解和兴趣。 学习单片机不…

【iOS】App仿写--天气预报

文章目录 前言一、首页二、搜索界面三、添加界面四、浏览界面总结 前言 最近完成了暑假的最后一个任务——天气预报,特此记录博客总结。根据iPhone中天气App的功能大致可以将仿写的App分为四个界面——首页,搜索界面,添加界面,浏…

dflow工作流使用1——架构和基本概念

对于容器技术、工作流等概念完全不懂的情况下理解dflow的工作方式会很吃力,这里记录一下个人理解。 dflow涉及的基本概念 工作流的概念很好理解,即某个项目可以分为多个步骤,每个步骤可以实现独立运行,只保留输入输出接口&#x…

WebGL Shader着色器GLSL语言

在2D绘图中的坐标系统,默认情况下是与窗口坐标系统相同,它以canvas的左上角为坐标原点,沿X轴向右为正值,沿Y轴向下为正值。其中canvas坐标的单位都是’px’。 WebGL使用的是正交右手坐标系,且每个方向都有可使用的值的…

c语言野指针int*p、空指针int*p = NULL、万能指针void* p

1、野指针&#xff0c;既没有初始化的指针&#xff0c;//如果没有给指针初始化&#xff0c;则指针p的内容为随机地址&#xff0c;会随机指向&#xff0c;故成为野指针&#xff0c;不可以操作野指针 #include "stdio.h" #include <stdlib.h>int main() {//1、野…

ORACLE常用基础

. 1.oracle开机启动流程 su - oracle lsnrctl start lsnrctl status sqlplus / as sysdba startup 2、如何查看数据库版本 select * from v$version; 3.如何查看用户从那个设备连接的数据库 SELECT DISTINCT machine , terminal FROM V$SESSION; 4.如何查看表结构 selec…

FANUC机器人SRVO-300机械手断裂故障报警原因分析及处理办法

FANUC机器人SRVO-300机械手断裂故障报警原因分析及处理办法 首先,我们查看报警说明书上的介绍: 总结:即在机械手断裂设置为无效时,机器人检测出了机械手断裂信号(不该有的信号,现在检测到了,所以报警) 使机械手断裂设定为无效/有效的具体方法:  按下示教器的MENU菜单…

Vue前端框架入门

文章目录 Vue快速入门Vue指令生命周期 Vue 经过一小段时间学习 我认为vue就是在原js上进行的一个加强 简化JS中的DOM操作 vue是分两个层的 一个叫做视图层(View)&#xff0c;你可以理解为展现出来的前端页面 一个叫数据模型层(Model),包含数据和一些数据的处理方法 MVVM就是实…

数据结构10 -查找_树表查找

创建二叉搜索树 二叉搜索树 二叉搜索树是有数值的了&#xff0c;二叉搜索树是一个有序树。 若它的左子树不空&#xff0c;则左子树上所有结点的值均小于它的根结点的值&#xff1b; 若它的右子树不空&#xff0c;则右子树上所有结点的值均大于它的根结点的值&#xff1b; 它…

从0到1开发go-tcp框架【2-实现Message模块、解决TCP粘包问题、实现多路由机制】

从0到1开发go-tcp框架【2-实现Message模块、解决TCP粘包问题、实现多路由机制】 1 实现\封装Message模块 zinx/ziface/imessage.go package zifacetype IMessage interface {GetMsdId() uint32GetMsgLen() uint32GetMsgData() []byteSetMsgId(uint32)SetData([]byte)SetData…