关于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的常见问题的更多相关文章

  1. HashMap实现原理及常见问题

    1.简介 HashMap是基于哈希表的Map接口的实现,用来存放键值对(Entry<Key,Value>),并提供可选的映射操作.使用put(Key,Value)存储对象到HashMap中 ...

  2. hashMap常见问题

    [解析hashMap的源码实现]      点击进入hashMap的源码实现 0.谈谈对hashMap的理解? 从底层结构.存取.扩容.冲突.实现原理.源码等方面说明. 1.你知道哪些常用的Map集合 ...

  3. HashMap底层实现原理及面试常见问题

    HashMap底层源码分析 1.HashMap底层采用的存储结构 1.在JDK1.7及之前采用的存储结构是数组+链表 2.到了JDK1.8之后采用的是数组+链表+红黑树 2.HashMap实现的原理 ...

  4. (转)Java集合框架:HashMap

    来源:朱小厮 链接:http://blog.csdn.net/u013256816/article/details/50912762 Java集合框架概述 Java集合框架无论是在工作.学习.面试中都 ...

  5. JAVA hashmap知识整理

    HashMap和Hashtable的比较是Java面试中的常见问题,用来考验程序员是否能够正确使用集合类以及是否可以随机应变使用多种思路解决问题.HashMap的工作原理.ArrayList与Vect ...

  6. [Java集合] 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联.

    注: 今天看到的一篇讲hashMap,hashTable,concurrentHashMap很透彻的一篇文章, 感谢原作者的分享. 原文地址: http://blog.csdn.net/zhanger ...

  7. Android WebView常见问题及解决方案汇总

    Android WebView常见问题解决方案汇总: 就目前而言,如何应对版本的频繁更新呢,又如何灵活多变地展示我们的界面呢,这又涉及到了web app与native app之间孰优孰劣的争论. 于是 ...

  8. HashMap总结

    最近朋友推荐的一个很好的工作,又是面了2轮没通过,已经是好几次朋友内推没过了,觉得挺对不住朋友的.面试反馈有一方面是有些方面理解思考的还不够,平时也是项目进度比较紧,有些方面赶进度时没有理解清楚的后面 ...

  9. Maven使用常见问题整理

    Maven使用常见问题整理  1.更新eclipse的classpath加入新依赖  1.在dependencyManagement里面加入包括版本在内的依赖信息,如:   <dependenc ...

随机推荐

  1. 银联ISO8583报文解析过程

    主密钥: aabbccddeeff11223344556677889900 1.从签到报文中获取工作密钥,包括MACKEY明文,PINKEY明文 签到: 12-03-31 16:38:09----&g ...

  2. activemq 的延迟队列和幂等性检查

    一. 延迟消息队列 1. 在提交支付之后,可以发送一个延迟检查的队列,来主动查询用户在支付宝上的支付状态 在mq的配置/config/activeMq.xml的broker实例上配置 schedule ...

  3. nyoj 113-字符串替换 (python replace, try ... except)

    113-字符串替换 内存限制:64MB 时间限制:3000ms 特判: No 通过数:31 提交数:71 难度:2 题目描述: 编写一个程序实现将字符串中的所有"you"替换成&q ...

  4. 深入理解Kafka必知必会(2)

    Kafka目前有哪些内部topic,它们都有什么特征?各自的作用又是什么? __consumer_offsets:作用是保存 Kafka 消费者的位移信息 __transaction_state:用来 ...

  5. Linux\CentOS 安装 vsftpd 服务器

    安装 查看电脑是否存在 vsftpd 服务器 rmp -qa|grep vsftpd 如果有就删除,没有就使用yum 安装 vsftpd yum -y install vsftpd 配置 在根目录下创 ...

  6. CentOS7和Ubuntu下安装Docker & Docker-Compose

    本篇介绍如何在CentOS 7.6和Ubuntu 16.04下安装Docker & Docker-Compose. CentOS篇 安装Docker # cat /etc/redhat-rel ...

  7. 一个自动修正数据时间和补全缺失数据的MapReduce程序

    原始数据如下图: 程序: Mapper类: public class DemoMapper extends Mapper<LongWritable,Text,IntWritable,Text&g ...

  8. zip的压缩和解压命令

    以下命令均在/home目录下操作cd /home #进入/home目录 1.把/home目录下面的data目录压缩为data.zip zip -r data.zip data #压缩data目录   ...

  9. 数据库05 使用percona软件来进行数据备份

    1.为什么要与用percona来备份 常见的MySQL备份工具 —跨平台性差 —备份时间长.冗余备份.浪费存储空间 mysqldump备份缺点: —效率较低.备份与还原速度慢,锁表(即备份数据库中的一 ...

  10. MySQL数据库优化技巧有哪些?

    开启查询缓存,优化查询. explain你的select查询,这可以帮你分析你的查询语句或是表结构的性能瓶颈.EXPLAIN的查询结果还会告诉你你的索引主键被如何利用的,你的数据表是如何被搜索和排序的 ...