概述

文章对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. 基于 Ant Desigin 的后台管理项目打包优化实践

    背景 按照 Ant Design 官网用 React 脚手构建的后台项目,刚接手项目的时候大概30条路由左右,我的用的机子是 Mac 8G 内存,打包完成需要耗时2分钟左右,决定优化一下. 项目技术栈 ...

  2. VS 2017——解决运行C++程序后出现(进程xxxx)已退出,返回代码为:0的问题

    工具-选项-调试-常规,“调试停止时自动关闭控制台”选项打钩.

  3. createElement(九)

    Vue.js 利用 createElement 方法创建 VNode,它定义在 src/core/vdom/create-elemenet.js 中: // wrapper function for ...

  4. 最短路(Dijkstra,Floyd,Bellman_Ford,SPFA)

    当然,这篇文章是借鉴大佬的... 最短路算法大约来说就是有4种——Dijkstra,Floyd,Bellman_Ford,SPFA 接下来,就可以一一看一下... 1.Dijkstra(权值非负,适用 ...

  5. 将用户名密码邮箱制成表格,以用户名为q结束

    print("输入用户名.密码.邮箱长度不能超过20个") s="" while True: v = input("用户名:") if v= ...

  6. Android Studio3.0.0之前首次安装通用配置

    一.第一次安装: 温馨提示:在安装Android Studio之前,建议先提前准备好单独的Android SDK,这个可以在AndroidDevTools网站下载.以前用Eclipse做过Androi ...

  7. Codeforces 524C.The Art of Dealing with ATM(暴力)

    我先采用了智障解法(n * n枚举...刚开始把n看成1000了还以为能过) 理所当然的t了,不过我怀疑优化一下能过?(感觉数据不太行的亚子 然后就是O(n * k * k)的解法,看到好多人快乐二分 ...

  8. Docker(一)概念与基础

    Docker 基础 为什么需要docker?在传统部署下,我们会遇到不同机器.不同依赖版本的兼容性等问题,解决此问题一般会消耗大量时间,并且在不同机器上均要执行统一环境的部署也是一个耗时较长的工作.除 ...

  9. K3/Cloud点按钮打开单据,列表,动态表单,简单账表和直接Sql报表示例

    BOS IDE中配置了个界面,拖了动态表单界面,加了5个测试按钮. 点击“打开单据”维护界面, 会跳转到一个新的主界面页签,[物料]新增 点击“打开列表”,会弹出[物料]列表界面 点击“打开动态表单” ...

  10. 计算a除b的第一位小数 in C++.

    my codes: #include<iostream> #include<cstdio> using namespace std; int main() { int a,b; ...