概述

文章对HashMap的部分细节进行介绍,JDK1.7之前有可能出现环形表的问题,而1.7之后进行了改进,文章对环形表现象的出现进行了解析,然后对HashMap注意的几个问题进行了解答。
HashMap的底层实现是数组,主要具有以下特点 :

  • 键值对都允许为空(重要)
  • 线程不安全
  • 不保证有序

问题描述即原因

首先看一下数据迁移的地方在哪里?JDK1.7 HashMap

  1. public V put(K key, V value)
  2. {
  3. ......
  4. //算Hash值
  5. int hash = hash(key.hashCode());
  6. int i = indexFor(hash, table.length);
  7. //如果该key已被插入,则替换掉旧的value (链接操作)
  8. for (Entry<K,V> e = table[i]; e != null; e = e.next) {
  9. Object k;
  10. if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
  11. V oldValue = e.value;
  12. e.value = value;
  13. e.recordAccess(this);
  14. return oldValue;
  15. }
  16. }
  17. modCount++;
  18. //该key不存在,需要增加一个结点
  19. addEntry(hash, key, value, i);
  20. return null;
  21. }
  22.  
  23. //增加一节点
  24. void addEntry(int hash, K key, V value, int bucketIndex)
  25. {
  26. Entry<K,V> e = table[bucketIndex];
  27. table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
  28. //查看当前的size是否超过了我们设定的阈值threshold,如果超过,需要resize
  29. if (size++ >= threshold)
  30. resize(2 * table.length);
  31. }
  32.  
  33. //重新生成空间
  34. void resize(int newCapacity)
  35. {
  36. Entry[] oldTable = table;
  37. int oldCapacity = oldTable.length;
  38. ......
  39. //创建一个新的Hash Table
  40. Entry[] newTable = new Entry[newCapacity];
  41. //将Old Hash Table上的数据迁移到New Hash Table上
  42. transfer(newTable);
  43. table = newTable;
  44. threshold = (int)(newCapacity * loadFactor);
  45. }
  46.  
  47. //数据迁移过程
  48. void transfer(Entry[] newTable)
  49. {
  50. Entry[] src = table;
  51. int newCapacity = newTable.length;
  52. //下面这段代码的意思是:
  53. // 从OldTable里摘一个元素出来,然后放到NewTable中
  54. for (int j = 0; j < src.length; j++) {
  55. Entry<K,V> e = src[j];
  56. if (e != null) {
  57. src[j] = null;
  58. do {
  59. Entry<K,V> next = e.next; //NO.1
  60. int i = indexFor(e.hash, newCapacity); //NO.2
  61. e.next = newTable[i]; //NO.3 把当前位置的节点放在新插进来节点的next(于是这里的当前位置在下面一步就会变成久节点了)
  62. newTable[i] = e; //NO.4 当前位置的节点放新插入的节点
  63. e = next; //NO.5 e 换成链表中的下一位
  64. } while (e != null);
  65. }
  66. }
  67.  
  68. }

正常的情况下,下图可以看见久的往后移,新的往前插(饭堂排队吃饭插队一样)

并发情况下,假如有两个线程执行,

  • 线程1执行到 NO.1时
  • 线程2执行完了
    就会出现如下

问题

图片来源与参考资料。

哈希表如何解决Hash冲突

JDK1.7之后换成了尾插法,不会出现环形表的但是依然是线程不安全的。

HashMap 中的 key若 Object类型, 则需实现哪些方法?

参考资料

  • https://www.jianshu.com/p/8324a34577a0

HahMap相关问题的更多相关文章

  1. 嵌入式单片机STM32应用技术(课本)

    目录SAIU R20 1 6 第1页第1 章. 初识STM32..................................................................... ...

  2. java中的字符串相关知识整理

    字符串为什么这么重要 写了多年java的开发应该对String不陌生,但是我却越发觉得它陌生.每学一门编程语言就会与字符串这个关键词打不少交道.看来它真的很重要. 字符串就是一系列的字符组合的串,如果 ...

  3. SQL Server相关书籍

    SQL Server相关书籍 (排名不分先后) Microsoft SQL Server 企业级平台管理实践 SQL Server 2008数据库技术内幕 SQL Server性能调优实战 SQL S ...

  4. dotNET跨平台相关文档整理

    一直在从事C#开发的相关技术工作,从C# 1.0一路用到现在的C# 6.0, 通常情况下被局限于Windows平台,Mono项目把我们C#程序带到了Windows之外的平台,在工作之余花了很多时间在M ...

  5. 在ASP.NET Core应用中如何设置和获取与执行环境相关的信息?

    HostingEnvironment是承载应用当前执行环境的描述,它是对所有实现了IHostingEnvironment接口的所有类型以及对应对象的统称.如下面的代码片段所示,一个HostingEnv ...

  6. virtualbox linux虚拟机相关

    linux虚拟机设置为静态IP 在virtualbox中安装好linux虚拟机后,如果采用的是NAT方式的话,linux虚拟机默认采用dhcp方式自动上网,而且用的是NetworkManager服务而 ...

  7. WebGIS中等值面展示的相关方案简析

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 等值面是气象.环保等相关项目上常用到的效果展示.在传统的CS项 ...

  8. .NET同步与异步之相关背景知识(六)

    在之前的五篇随笔中,已经介绍了.NET 类库中实现并行的常见方式及其基本用法,当然.这些基本用法远远不能覆盖所有,也只能作为一个引子出现在这里.以下是前五篇随笔的目录: .NET 同步与异步之封装成T ...

  9. zookeeper集群的搭建以及hadoop ha的相关配置

    1.环境 centos7 hadoop2.6.5 zookeeper3.4.9 jdk1.8 master作为active主机,data1作为standby备用机,三台机器均作为数据节点,yarn资源 ...

随机推荐

  1. POJ2528Mayor's posters 线段树,离散化技巧

    题意:一个坐标轴从1~1e7,每次覆盖一个区间(li,ri),问最后可见区间有多少个(没有被其他区间挡住的) 线段树,按倒序考虑,贴上的地方记为1,每次看(li,ri)这个区间是否全是1,全是1就说明 ...

  2. c++ stl在竞赛里的使用总结

    SET bzoj2761: [JLOI2011]不重复数字 这题... count() 的用法,返回这个值出现的次数,但是在set里只会出现0次和1次,这个可以判断某个值是否在set里出现过 还有si ...

  3. python之爬虫(爬取.ts文件并将其合并为.MP4文件——以及一些异常的注意事项)

    //20200115 最近在看“咱们裸熊——we bears”第一季和第三季都看完了,单单就第二季死活找不到,只有腾讯有资源,但是要vip……而且还是国语版……所以就瞄上了一个视频网站——可以在线观看 ...

  4. 论文阅读笔记(四)【TIP2017】:Video-Based Pedestrian Re-Identification by Adaptive Spatio-Temporal Appearance Model

    Introduction (1)背景知识: ① 人脸识别是具有高可靠性的生物识别技术,但在低解析度(resolution)和姿态变化下效果很差. ② 步态(gait)是全身行为的生物识别特征,大部分步 ...

  5. springboot 扫描不到包 @SpringBootApplication 自动配置原理

    解决方案 在main类中增加注解 @ComponentScan("com.test.test.*") 扫描具体的包 @ComponentScan(basePackages = {& ...

  6. StackExchange.Redis 之 SortedSet 类型示例

    1,增加操作 RedisCacheHelper.Instance.ZSortadd(); RedisCacheHelper.Instance.ZSortadd(); RedisCacheHelper. ...

  7. Linux之温故知新2

    1.关于ssh免密码登陆的ssh-keygen, ssh-copy-id的使用, 然后使用ssh-copy-id user@remote将公钥传给服务器, 以及别名 1 C:\Users\linxmo ...

  8. layer iframe 设置关闭按钮 和刷新和弹出框设置

    layer弹出层的关闭问题   就是在执行添加或修改的时候,需要将数据提交到后台进行处理,这时候添加成功之后最理想的状态是关闭弹出层并且刷新列表的数据信息,之前一直想实现这样,可一直没有成功,今天决定 ...

  9. 解决pycharm创建github工程但push失败的问题

    1.运行git-cmd.exe; 2.d:   cd  工程路径 3.执行命令:git remote set-url origin https://github.com/wawj901124/jmet ...

  10. 从原理到方案,一步步讲解web移动端实现自适应等比缩放

    前言 在移动端做自适应,我们常用的有媒体查询,rem ,em,宽度百分比这几种方案.但是都各有其缺点. 首先拿媒体查询来说,在某一个宽度区间内只能使用一种样式,为了适应不同屏幕要,css的代码量就会增 ...