HashMap的常见问题
关于HashMap的一些常见的问题,自己总结一下:
首选HashMap在jdk1.7和jdk1.8里面的实现是不同的,在jdk1.7中HashMap的底层实现是通过数组+链表的形式实现的,在jdk1.8中HashMap的底层是通过数组+链表+红黑树来实现的。
Question1: 数组链表是怎么切换的(1.7)?
答:在put的时候采用hash(key)&(len-1)来计算数据存放的index,以此存放元素。当出现哈希冲突的时候,因为有限的数组长度,遭遇哈希冲突,此时就可以使用链表来存储哈希值相同但是值不同的对象。
Question2:Entry节点如何插入链表(1.7)?
答: Entry节点插入链表是使用头插法来实现的,主要的实现是通过其CreateEntry来实现的,Entry的构造方法中可以协助头插的顺利进行,使用头插法是考虑到热点数据的问题,当时的想法是最近插入的元素,最近也可能被使用,头插入的实现可以缩短链表查找元素的时间。
Question3:jdk1.8以后为什么改用尾插入?
答:根据initialCapacity*LoadFactoor=capacity以后,如果插入的元素容量达到了capacity,此时会进行扩容,扩容操作按照源码中的写法,主要有两步:1.扩容一个新的Entry,容量为原来的两倍。2.进行Rehash操作,将原来的数据复制到新的Entry中。(1.7)如果是头插入的话,当多线程处理的时候,此时如果存在a->b->c链表,当我们rehash以后,有可能变为b->a,然而其他的线程处理完之后,结果可能会造成b->a->b,造成loop成环。一旦寻找数据会造成死循环。
而1.8以后改成尾插入以后,源码中使用了一个高位来识别之前的数据和插入的新数据,保持了之前的顺序,解决了1.7中可能造成成环的问题。具体的实现是扩容只有最高位会多出一个1,如果之前的数据一旦e & oldCapacity = 0,表明是原来的数据,保持就好,如果是为1,表明是即将插入的新数据,此时保持插入高位,这样就避免了成环的问题。
Question4:为什么要进行Rehash操作?
答: 因为此时的长度遍历按照index=hashcode & (len - 1)的计算,此时的规则变了,所以需要进行rehash操作。
Question5:HashMap为什么不是线程安全?
答:在jdk1.7中即使不出现死循环,由于put操作未加锁,我们也不能确保对于多个线程同时执行put操作时,上一秒修改完的put的值,下一秒get是否是修改后的值,容易被其他线程的值所覆盖,线程安全无法保证(1.7&1.8都是如此)
Question6:为啥源码的容量初始化大小为16?
答:在源码中有个方法叫做tableSizeFor(),这个方法是为了将当前的容量扩容到一个距离当前容量的2的整次方幂。阿里巴巴手册上也建议使用HashMap需要设置一个初始化的容量值,一般来说是设置为16,为什么是16而不是8或者4,因为4或者8容易导致hashMap扩容,影响性能。只要输入的HashCode分布是相对均匀的,那么hash算法就是均匀的,所以给16主要也是为了实现均匀分布。
Question7:为啥重写equals方法的同时需要重写hashCode方法?使用HashMap举例子说明?
答: 首先,equals方法继承了Object的equals方法,比较的对于值对象比较的是两个对象的值是否相等,对于引用对象比较的是两个对象的内存地址是否相等。上面也说到HashMap是通过hash(key)&(len-1)去寻找index的,index相同就形成链表存储数据,但是假如一个index中存储了object1、object2对象,他们的hash值相同,此时如果我们get数据object2,get(key)此时将会有两个值,你怎么能确保获取到的是object2而不是object1,此时就需要使用equals来比较对象的key是否相同,这样才可以获取到对的对象。实质上在底层get方法的实现是通过getNode(hash(key),key)来实现的,前面的是hash值,后面的是equals对比的对象。
Question8:HashMap线程不安全不适合多线程,那用什么可以替代?
答:可以使用HashTable或者ConcurrentHashMap来替代HashMap,但是HashTable仅仅是使用synchronized来实现同步锁,从而使得线程安全,但是并发度不高。所以一般使用ConcurrentHashMap来替代
Question9:为什么在1.8中当链表长度为8时转换为红黑树,数据长度为6时转化为链表?
答: 首先从时间复杂度方面来分析的话,当长度为6时查找的平均长度为6/2=3,(底层会判断偏后还是偏前,以此来从后或者从前遍历),而红黑数log6=2.6,如果为8的时候,此时8/2=4,而log8为3,至于具体这样选,是一种空间和时间的权衡。
HashMap的常见问题的更多相关文章
- HashMap实现原理及常见问题
1.简介 HashMap是基于哈希表的Map接口的实现,用来存放键值对(Entry<Key,Value>),并提供可选的映射操作.使用put(Key,Value)存储对象到HashMap中 ...
- hashMap常见问题
[解析hashMap的源码实现] 点击进入hashMap的源码实现 0.谈谈对hashMap的理解? 从底层结构.存取.扩容.冲突.实现原理.源码等方面说明. 1.你知道哪些常用的Map集合 ...
- HashMap底层实现原理及面试常见问题
HashMap底层源码分析 1.HashMap底层采用的存储结构 1.在JDK1.7及之前采用的存储结构是数组+链表 2.到了JDK1.8之后采用的是数组+链表+红黑树 2.HashMap实现的原理 ...
- (转)Java集合框架:HashMap
来源:朱小厮 链接:http://blog.csdn.net/u013256816/article/details/50912762 Java集合框架概述 Java集合框架无论是在工作.学习.面试中都 ...
- JAVA hashmap知识整理
HashMap和Hashtable的比较是Java面试中的常见问题,用来考验程序员是否能够正确使用集合类以及是否可以随机应变使用多种思路解决问题.HashMap的工作原理.ArrayList与Vect ...
- [Java集合] 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联.
注: 今天看到的一篇讲hashMap,hashTable,concurrentHashMap很透彻的一篇文章, 感谢原作者的分享. 原文地址: http://blog.csdn.net/zhanger ...
- Android WebView常见问题及解决方案汇总
Android WebView常见问题解决方案汇总: 就目前而言,如何应对版本的频繁更新呢,又如何灵活多变地展示我们的界面呢,这又涉及到了web app与native app之间孰优孰劣的争论. 于是 ...
- HashMap总结
最近朋友推荐的一个很好的工作,又是面了2轮没通过,已经是好几次朋友内推没过了,觉得挺对不住朋友的.面试反馈有一方面是有些方面理解思考的还不够,平时也是项目进度比较紧,有些方面赶进度时没有理解清楚的后面 ...
- Maven使用常见问题整理
Maven使用常见问题整理 1.更新eclipse的classpath加入新依赖 1.在dependencyManagement里面加入包括版本在内的依赖信息,如: <dependenc ...
随机推荐
- 数据仓库ETL案例学习(一)
来自课程案例学习 某跨国食品超市的信息管理系统,每天都会记录成千上万条各地连锁超市的销售数据.基于大数据的背景,该公司的管理层决定建立FoodMart数据仓库,期望能从庞大的数据中挖掘出有商业价值 ...
- 实现支持多用户在线的FTP程序(C/S)
1. 需求 1. 用户加密认证 2. 允许多用户登录 3. 每个用户都有自己的家目录,且只能访问自己的家目录 4. 对用户进行磁盘分配,每一个用户的可用空间可以自己设置 5. 允许用户在ftp ser ...
- java中线程同步的几种方法
1.使用synchronized关键字 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法.在调用该方法前,需要获得内置锁,否则就处于阻塞状态. 注: synchro ...
- MySQL 1364 错误提示:#1364 - Field "details" doesn't have a default value
原因:mysql字段设计的时候为not null,结果此字段没有插入值,解决方法: 运行以下命令. SET @@GLOBAL.sql_mode="NO_AUTO_CREATE_USER,NO ...
- windows版本 MongoDB副本集搭建及开启身份验证
------------恢复内容开始------------ ------------恢复内容开始------------ MongoDB副本集搭建 我搭建的是一个主节点,两个副节点 构建目录结构如下 ...
- 业务领域建模Domain Modeling
我的工程实践选题为ESP32低功耗的实现,本项目基于ESP32嵌入式开发平台.下文将以需求为基础,对该项目进行领域建模. 一.概念介绍 1.业务建模 1.1 概念介绍 业务建模(Business Mo ...
- Spring Boot: Spring Doc生成OpenAPI3.0文档
1. 概述 公司正好最近在整理项目的文档,且文档对于构建REST API来说是至关重要的.在这篇文章中,我将介绍Spring Doc , 一个基于OpenAPI 3规范简化了Spring Boot 1 ...
- Error: invalid "instanceof" keyword value Promise的解决方法
执行npm run dev 时,发现错误 Error: invalid "instanceof" keyword value Promise 经过一番查找,发现原因是webpack ...
- Laravel 菜鸟的晋级之路
第一阶段:简单的增删改查 这是最开始接触Laravel的一个阶段.如果有PHP经验,那么应该能很快找到MVC的路径,然后驾轻就熟的开始写起来.虽然还显得有些笨拙,不过很快就能做出一些内容了.如果没有P ...
- tcp和udp的网络编程(发送消息及回复)
一.UDP 无连接的 高效的 基于数据报的 不可靠 的连接 主要的应用场景: 需要资源少,网络情况稳定的内网,或者对于丢包不敏感的应用,比如 DHCP 就是基于 UDP 协议的.不需要一对一沟 ...