一、HashMap 的数据结构

Java7 及之前主要是“数组+链表”,到了 Java8 之后,就变成了“数组+链表+红黑树”

二、Java7 源码浅析:

在Java7 中,HashMap 是数据结构里学的 HashTable 经典的实现!

注意点:Java7 中的 HashMap 当我们new出来的时候,他就给我们初始化了底层的 Entry 数组!

1、HashMap()

它自行调用了一个有参的构造器,并传入了默认的数组长度和负载因子:


2、put()

大致流程:先根据 key 的哈希值获取数组索引,然后挨个在数组上查找是否有Entry key 哈希值和值都和 put 的 key 相同,有的话就覆盖 value 了;没有的话,才进行 Entry 的添加!

3、indexFor()

在这里获取数组索引,哈希值 &(数组长度-1),这也就是为什么数组长度为 2 的幂的原因!

4、addEntry()

在添加节点的时候,会进行是否扩容的判断!

三、Java7 中的问题:

  • 死锁:头插法。因为复制的时候,依次把链表元素复制到新的数组中去,有可能部分元素获取的数组索引还是相同的,因为头插法会导致链表导致,从而形成环形链表,当CPU下次进入这个链表查询时,产生死锁!
  • 安全隐患:Apache Tomcat 底层是使用哈希表来进行存储 Http request 的 parameters,如果此时http请求中的参数中有大量 hash 相同的 key,那么可能导致服务器中形成大量的环形链表,消耗大量CPU,发生Dos!2011年的时候 Tomcat 察觉到并临时想到了一个方法,提供了一个参数,用于限制参数的个数,默认值是 1W!而 Java8 在2014年的时候发布的时候,

四、Java8 的源码浅析:

HashMap()

put()

注意:此时,分配数组索引已经是在判断的时候做的了!

Java 8 相对于 7 的变化:

  • new HashMap() 时,底层没有第一时间创建 默认长度的数组!
  • 底层是 Node 数组,而非 Entry 数组
  • 首次调用 put 方法的时候,才进行数组的创建!(延时加载)
  • put 时,如果添加新节点的话,采用的是尾插法!(可避免 7 的死锁问题!)
  • 7 的底层结构只有 数组+链表,8 则是 数组+链表+红黑树(当 put 的链表长度等于8,且数组长度等于 64 的时候,这个链表就会转为红黑树结构!)!

HashMap的源码浅析的更多相关文章

  1. HashSet其实就那么一回事儿之源码浅析

    上篇文章<HashMap其实就那么一回事儿之源码浅析>介绍了hashMap,  本次将带大家看看HashSet, HashSet其实就是基于HashMap实现, 因此,熟悉了HashMap ...

  2. java并发:jdk1.8中ConcurrentHashMap源码浅析

    ConcurrentHashMap是线程安全的.可以在多线程中对ConcurrentHashMap进行操作. 在jdk1.7中,使用的是锁分段技术Segment.数据结构是数组+链表. 对比jdk1. ...

  3. 【深入浅出jQuery】源码浅析--整体架构

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  4. 【深入浅出jQuery】源码浅析2--奇技淫巧

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  5. Struts2源码浅析-ConfigurationProvider

    ConfigurationProvider接口 主要完成struts配置文件 加载 注册过程 ConfigurationProvider接口定义 public interface Configurat ...

  6. (转)【深入浅出jQuery】源码浅析2--奇技淫巧

    [深入浅出jQuery]源码浅析2--奇技淫巧 http://www.cnblogs.com/coco1s/p/5303041.html

  7. Android 手势识别类 ( 三 ) GestureDetector 源码浅析

    前言:上 篇介绍了提供手势绘制的视图平台GestureOverlayView,但是在视图平台上绘制出的手势,是需要存储以及在必要的利用时加载取出手势.所 以,用户绘制出的一个完整的手势是需要一定的代码 ...

  8. Android开发之Theme、Style探索及源码浅析

    1 背景 前段时间群里有伙伴问到了关于Android开发中Theme与Style的问题,当然,这类东西在网上随便一搜一大把模板,所以关于怎么用的问题我想这里也就不做太多的说明了,我们这里把重点放在理解 ...

  9. 【深入浅出jQuery】源码浅析2--使用技巧

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

随机推荐

  1. 在java中构建高效的结果缓存

    文章目录 使用HashMap 使用ConcurrentHashMap FutureTask 在java中构建高效的结果缓存 缓存是现代应用服务器中非常常用的组件.除了第三方缓存以外,我们通常也需要在j ...

  2. Cacti nagios zabbix 的区别

    Cacti nagios zabbix 的区别 首先 Cacti 是一个用 rrdtool 来画图的网络监控系统, 通常一说到网络管理, 大家首先想到的经常是 mrtg, 但是 mrtg 画的图比较简 ...

  3. 【抓包工具】tcpdump

    tcpdump - dump traffic on a network 根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据包的“头”完全截获下来提供分析.它支 ...

  4. 【Linux常见命令】date命令

    Linux date命令:可以用来显示或设定系统的日期与时间. 在显示方面,使用者可以设定欲显示的格式,格式设定为一个加号后接数个标记,其中可用的标记列表如下: 时间方面: %H : 小时(00..2 ...

  5. SpringBoot内置生命周期事件详解 SpringBoot源码(十)

    SpringBoot中文注释项目Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringBoot事件监听 ...

  6. USACO Training Section 1.2 [USACO1.2]回文平方数

    题目描述 回文数是指从左向右念和从右向左念都一样的数.如12321就是一个典型的回文数. 给定一个进制B(2<=B<=20,由十进制表示),输出所有的大于等于1小于等于300(十进制下)且 ...

  7. qt creator源码全方面分析(4-2)

    目录 global头文件 global.h xx.h global头文件 插件的本质就是动态链接库,对于库,需要导出符号,供用户导入使用.在qt creator的源码中,存在固定的导入导出模式. gl ...

  8. Face The Right Way 开关(POJ3276)

    描述: \( N 头牛排成了一列.每头牛或者向前或者向后.为了让所有的牛都面向前方,农夫约翰买了 一台自动转向的机器. 这个机器在购买时就必须设定一个数值 K,机器每操作一次恰好使 K 头连续的牛转向 ...

  9. 王颖奇 20171010129《面向对象程序设计(java)》第十三周学习总结

      实验十三  图形界面事件处理技术 实验时间 2018-11-22 1.实验目的与要求 (1) 掌握事件处理的基本原理,理解其用途: (2) 掌握AWT事件模型的工作机制: (3) 掌握事件处理的基 ...

  10. 美团分布式ID生成框架Leaf源码分析及优化改进

    本文主要是对美团的分布式ID框架Leaf的原理进行介绍,针对Leaf原项目中的一些issue,对Leaf项目进行功能增强,问题修复及优化改进,改进后的项目地址在这里: Leaf项目改进计划 https ...