1. 概述:

HashMap基于Map接口实现,元素以键值对的方式存储,并且允许使用null 建和null值,因为key不允许重复,因此只能有一个键为null,另外HashMap不能保证放入元素的顺序,它是无序的,和放入的顺序并不能相同。HashMap是线程不安全的。

2.HashMap原理

HashMap的底层实现在JDK1.8以前是通过hash表(数组实现)加链表实现的。每个输入的键值对会首先根据键值来确定它在数组上的唯一位置,然后在这个位置上存放一个链表用来存储具体的键值对。因此,当我们在HashMap中查找元素时,首先要通过hash函数确定其在数组中的位置,这一过程时间复杂度为O(1),然后遍历这一位置上的链表查找即可,时间复杂度为O(n),因此若链表长度较短时,HashMap的查找效率非常高,接近O(1)。在JDK1.8以后,为了提高查找效率,当链表长度达到8以后,链表就会变换为查询效率更高的红黑树。

3.红黑树与二叉平衡树

二叉平衡树是带有平衡条件的二叉查找树,一般是用平衡因子差值判断是否平衡并通过旋转来实现平衡,左右子树树高不超过1,和红黑树相比,AVL树是严格的平衡二叉树,平衡条件必须满足(所有节点的左右子树高度差的绝对值不超过1)。不管我们是执行插入还是删除操作,只要不满足上面的条件,就要通过旋转来保持平衡,而旋转是非常耗时的,由此我们可以知道AVL树适合用于插入与删除次数比较少,但查找多的情况。

红黑树是一种二叉查找树,但在每个节点增加一个存储位表示节点的颜色,可以是红或黑(非红即黑)。通过对任何一条从根到叶子的路径上各个节点着色的方式的限制,红黑树确保没有一条路径会比其它路径长出两倍,因此,红黑树是一种弱平衡二叉树(由于是弱平衡,可以看到,在相同的节点情况下,AVL树的高度低于红黑树),相对于要求严格的AVL树来说,它的旋转次数少,所以对于搜索,插入,删除操作较多的情况下,我们就用红黑树。红黑树的几个特点:①根节点一定是黑的;②如果一个节点是红的,那么它的子节点必须是黑的;③每个叶节点(叶节点即树尾端NULL指针或NULL节点)都是黑的;④对于任意节点而言,其到叶子点树NULL指针的每条路径都包含相同数目的黑节点;⑤每条路径都包含相同的黑节点;

红黑树的使用场景:1.Linux的的进程调度完全公平调度程序,用红黑树管理进程控制块,进程的虚拟内存区域都存储在一颗红黑树上,每个虚拟地址区域都对应红黑树的一个节点,左指针指向相邻的地址虚拟存储区域,右指针指向相邻的高地址虚拟地址空间;2.IO多路复用的epoll的的的实现采用红黑树组织管理的的的sockfd,以支持快速的增删改查;3.Nginx的的的中用红黑树管理定时器,因为红黑树是有序的,可以很快的得到距离当前最小的定时器;4.Java的的的中TreeMap中的中的实现。

其余有关红黑树内容详见:       红黑树和AVL树(平衡二叉树)区别_u010899985的博客-CSDN博客_红黑树与平衡二叉树

4.HashMap存储流程

①元素到达,先判断HashMap是否为空或到达扩容阈值,是则先进行扩容操作;

②使用hash函数确定元素所在数组的索引,若此时该位置为空,直接插入;

③若此时位置不为空,若存储为链表,判断插入后是否大于8,大于则转变为红黑树,否则直接插入即可;

④插入元素后查看HashMap是否达到扩容阈值,若达到则对其进行扩容。

5.HashMap扩容原理

     HashMap允许你指定负载因子的构造器,表示当负载情况达到负载因子水平的时候,容器会自动扩容,HashMap默认使用的负载因子值为0.75f(当容量达到四分之三进行再散列(扩容))。当负载因子越大的时候能够容纳的键值对就越多但是查找的代价也会越高。所以如果你知道将要在HashMap中存储多少数据,那么你可以创建一个具有恰当大小的初始容量这可以减少扩容时候的开销。但是大多数情况下0.75在时间跟空间代价上达到了平衡所以不建议修改。

JDK1.8中扩容机制核心方法Node<K,V>[] resize()
     HashMap扩容可以分为三种情况:

第一种:使用默认构造方法初始化HashMap。从前文可以知道HashMap在一开始初始化的时候会返回一个空的table,并且thershold为0。

因此第一次扩容的容量为默认值DEFAULT_INITIAL_CAPACITY也就是16。同时threshold = DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR = 12。

第二种:指定初始容量的构造方法初始化HashMap。那么从下面源码可以看到初始容量会等于threshold,接着threshold = 当前的容量(threshold) * DEFAULT_LOAD_FACTOR。

第三种:HashMap不是第一次扩容。如果HashMap已经扩容过的话,那么每次table的容量以及threshold量为原有的两倍。
     有关扩容更多详细内容详见:jdk1.8 HashMap工作原理和扩容机制(源码解析)_青元子的博客-CSDN博客_hashmap1.8扩容机制

HashMap的原理及扩容相关推荐

  1. Hashmap实现原理及扩容机制详解

    目录 HashMap基础 HashMap实现原理 Node和Node链 拉链法 关于Node数组 table 散列算法 HashMap和红黑树 关于TreeNode 红黑树基础 HashMap扩容机制 ...

  2. HashMap实现原理和扩容机制

    一.HashMap实现原理 1. HashMap概述 HashMap是基于哈希表的Map接口的非同步实现.此实现提供所有可选的映射操作,并允许使用null值和null键.此类不保证映射的顺序,特别是它 ...

  3. java map扩容机制_Java HashMap的原理、扩容机制、以及性能思考

    Java HashMap 说明 此文档所介绍的HashMap是基于JDK1.8之后的.此文受到网上很多其他Java生态爱好者文章的影响,写此文的目的是系统的概括下HashMap,并把一些优秀文章的脉络 ...

  4. 深入理解HashMap(原理,查找,扩容)

    面试的时候闻到了Hashmap的扩容机制,之前只看到了Hasmap的实现机制,补一下基础知识,讲的非常好 原文链接: http://www.iteye.com/topic/539465 Hashmap ...

  5. 调试JDK源码-一步一步看HashMap怎么Hash和扩容

    调试JDK源码-一步一步看HashMap怎么Hash和扩容 调试JDK源码-ConcurrentHashMap实现原理 调试JDK源码-HashSet实现原理 调试JDK源码-调试JDK源码-Hash ...

  6. 面试官再问你 HashMap 底层原理,就把这篇文章甩给他看

    来自:烟雨星空 前言 HashMap 源码和底层原理在现在面试中是必问的.因此,我们非常有必要搞清楚它的底层实现和思想,才能在面试中对答如流,跟面试官大战三百回合.文章较长,介绍了很多原理性的问题,希 ...

  7. 【Java集合学习系列】HashMap实现原理及源码分析

    HashMap特性 hashMap是基于哈希表的Map接口的非同步实现,继承自AbstractMap接口,实现了Map接口(HashTable跟HashMap很像,HashTable中的方法是线程安全 ...

  8. 面试高频问题:HashMap实现原理

    2019独角兽企业重金招聘Python工程师标准>>> 今天给同学们讲讲一个面试经常遇到的高频问题,HashMap实现原理,希望在金三银四的季节对同学们有帮助. HashMap结构图 ...

  9. HashMap 实现原理

    转载自 HashMap 实现原理 HashMap是常考点,而一般不问List的几个实现类(偏简单).以下基于JDK1.8.0_102分析. 内部存储 HashMap的内部存储是一个数组(bucket) ...

最新文章

  1. mysql隐藏用户名_系统默认的MySQL用户名消失的解决方法(修正版)
  2. 云曦服务器,云曦南羡最新章节_云曦南羡全本小说
  3. iOS 静态库代码混淆方案
  4. 万字长文重新解剖产品经理(内含大量图片)
  5. 反编译之将脱壳后的dex文件重新打包成apk
  6. 借助JVM生日的时机,说说关于JVM你所不知道的那些事
  7. Boost:顺序一致性的测试程序
  8. java 性能 优化_Java十大简单性能优化
  9. java中0x07_JAVA里0X00的表示
  10. 《微软的软件测试之道》读书笔记 之 结构测试技术
  11. Java 数组操作
  12. Kaggle实战之食尸鬼、地精、鬼魂分类
  13. 如何正确给锂电池充电
  14. Modbus家族之 RTU
  15. 山东大学项目实训(二十七)—— 微信小程序开发总结,一年时间真的可以改变一个人很多
  16. 又拍云叶靖:基于Docker的云处理服务平台
  17. 关于tp-link 路由器
  18. 梅捷主板去掉启动自检_持续交付–第五部分–启动–自检
  19. 短线黄金做波段的策略分析
  20. 机器人教练SWOT分析_水田植保机器人的SWOT分析

热门文章

  1. java Pattern和Matcher详解
  2. 后端程序员要会linux吗,后端程序员必备的Linux基础知识
  3. python 成长笔记 序章
  4. JVM命令与调优工具的使用(OOM与GC回收例)
  5. javascript中使用split对多个分割符进行分割
  6. violate 修饰的用法
  7. sql语句,sql文件加注释
  8. 知识图谱构建中的抽取方法
  9. 什么是Oauth2.0授权,四种授权模式
  10. 异形隔离java剧情_异形隔离攻略 系统上手教程 全剧情流程图文攻略(20)