共两篇,本文是第二篇,包含后六节。ps:你看到的是我写的第二遍!~ 坑 die 的有道云,写完之后居然给我清空了,无力吐槽

目录

引言

基本存储结构

Put 方法原理

Get 方法原理

装填因子默认值及作用

HashMap 默认长度及原因

HashMap 的线程安全问题

Java8 中 HashMap 的优化

HashMap 和 HashSet 的关系

线程安全的 HashMap:CurrentHashMap 简介

装填因子默认值及作用

/**

* The load factor used when none specified in constructor.

*/

static final float DEFAULT_LOAD_FACTOR = 0.75f;

装填因子默认是 0.75,当 put 值时

// The next size value at which to resize (capacity * load factor).

threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);

// 如果大于下一个重置大小的值 则把数组扩大一倍

if ((size >= threshold) && (null != table[bucketIndex])) {

resize(2 * table.length);

hash = (null != key) ? hash(key) : 0;

bucketIndex = indexFor(hash, table.length);

}

意思是说,当数组中的元素的个数 >=总长度*装填因子时,数组长度扩容一倍

HashMap 默认长度及原因

/**

* The default initial capacity - MUST be a power of two.

*/

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;

hashmap 的默认长度是 16,而且长度必须是 2 的倍数

private void inflateTable(int toSize) {

// Find a power of 2 >= toSize

int capacity = roundUpToPowerOf2(toSize);

threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);

table = new Entry[capacity];

initHashSeedAsNeeded(capacity);

}

// 把不是2的倍数的数转换成 > 原始值的2的倍数

private static int roundUpToPowerOf2(int number) {

// assert number >= 0 : "number must be non-negative";

return number >= MAXIMUM_CAPACITY

? MAXIMUM_CAPACITY

: (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;

}

之所以必须是 2 的倍数,是因为 HashMap 进行 Entry 数组定位的时候,不是使用的取模操作,而是进行的位操作默认取 hash 值的后四位。

例如:hash 值为 12345 Entry 数组长度是 16 该 hash 在数组中的位置计算不是 12345 mod 16 = 9 而是 12345 & 15 = 9,虽然结果是一样的,但是计算效率会更高,速度更快。

HashMap 的线程安全问题

HashMap 在并发编程中可能导致程序死循环

在多线程环境下,使用 HashMap 进行 put 操作时,如果多个线程同时进行扩容操作,有可能会使链表形成闭环,造成获取 Entry 时死循环,导致 CPU 利用率接近 100%。主要是因为 HashMap 在插入 Entry 的时候是插在链表头的而不是链表尾,具体原因参考:https://www.cnblogs.com/andy-zhou/p/5402984.html

Java8 中 HashMap 的优化

JDK1.8 中 HashMap 是数组 + 链表 + 红黑树实现的,链表长度是大于 8 的话把链表转换为红黑树

JDK1.8 种优化了扩容机制

JDK1.8 中优化了高位运算的算法

等等 虽然有点贱,但是的确还有很多 ~

HashMap 和 HashSet 的关系

// 构造方法中就是初始化一个默认的HashMap

public HashSet() {

map = new HashMap<>();

}

private static final Object PRESENT = new Object();

// 增加元素 就是在HashMap中增加一个Key为增加的元素,值为Object实例的键值对

public boolean add(E e) {

return map.put(e, PRESENT)==null;

}

// 判断是否存在也是判断元素是否在HashMap中是否存在

public boolean contains(Object o) {

return map.containsKey(o);

}

综上,HashSet 是通过 HashMap 的 Key 实现的

线程安全的 HashMap:CurrentHashMap 简介

HashMap 存在线程安全问题,HashTable 虽然是线程安全的,但是效率太低。所以在多线程的环境下我们一般使用 CurrentHashMap。

CurrentHashMap 使用了锁分段技术,首先把数据分成一段一段地存储,然后给每一段都加上一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

有机会的话我会写一篇文章仔细分析,埋个坑,敬请期待 :)

currenthashmap扩容原理_HashMap 深入解析(二)相关推荐

  1. currenthashmap扩容原理_高并发编程系列:深入探讨ConcurrentHashMap的实现原理(JDK1.7和JDK1.8)...

    HashMap.CurrentHashMap 的实现原理基本都是BAT面试必考内容,阿里P8架构师谈:深入探讨HashMap的底层结构.原理.扩容机制深入谈过hashmap的实现原理以及在JDK 1. ...

  2. currenthashmap扩容原理_ConcurrentHashMap之扩容实现(基于JDK1.8)

    1. 概述 ConcurrentHashMap是JDK提供的一种线程安全的HashMap实现,JDK1.8对ConcurrentHashMap进行了大量优化,除了增加了函数式编程特性,还对加锁方式进行 ...

  3. currenthashmap扩容原理_ConcurrentHashMap实现原理和源码解读

    前言 HashMap是java编程中最常用的数据结构之一,由于HashMap非线程安全,因此不适用于并发访问的场景.JDK1.5之前,通常使用HashTable作为HashMap的线程安全版本,Has ...

  4. Tensorflow2.0---SSD网络原理及代码解析(二)-锚点框的生成

    Tensorflow2.0-SSD网络原理及代码解析(二)-锚点框的生成 分析完SSD网络的原理之后,一起来看看代码吧~ 代码转载于:https://github.com/bubbliiiing/ss ...

  5. halfstone 原理_HashMap的结构以及核心源码分析

    摘要 对于Java开发人员来说,能够熟练地掌握java的集合类是必须的,本节想要跟大家共同学习一下JDK1.8中HashMap的底层实现与源码分析.HashMap是开发中使用频率最高的用于映射(键值对 ...

  6. ORB-SLAM / ORB-SLAM2原理解读+代码解析(汇总了资料,方便大家学习)

    注释:本文非原创,初学搜集了很多资料附上链接,方便初学者学习,避免盲目搜索浪费时间. 目录 官方代码链接 代码框架思维导图 参考解读 参考链接- -一步步带你看懂orbslam2源码 ORB-SLAM ...

  7. Dubbo原理和源码解析之服务引用

    github新增仓库 "dubbo-read"(点此查看),集合所有<Dubbo原理和源码解析>系列文章,后续将继续补充该系列,同时将针对Dubbo所做的功能扩展也进行 ...

  8. Git内部原理之深入解析Git的引用和包文件

    一.Git 分支本质 如果对仓库中从一个提交(比如 1a410e)开始往前的历史感兴趣,那么可以运行 git log 1a410e 这样的命令来显示历史,不过需要记得 1a410e 是查看历史的起点提 ...

  9. 音视频开发(7)---流媒体服务器原理和架构解析

    流媒体服务器原理和架构解析 多媒体数据文件 一个完整的多媒体文件是由音频和视频两部分组成的,H264.Xvid等就是视频编码格式,MP3.AAC等就是音频编码格式,字幕文件只是附加文件.目前大部分的播 ...

最新文章

  1. vue写一个通用的toast弹窗 toast 弹窗 提示
  2. 年近 40,我在互联网大厂做高龄“大头兵”
  3. php依次替换文本字符串中的图片src地址
  4. BOOST使用 proto 转换进行任意类型操作的简单示例
  5. 计算机组成原理第04章在线测试,计算机组成原理第四章单元测试(二)(含答案).docx...
  6. 华为与美国公司就授权5G平台展开初期谈判;Linux 中存在严重漏洞;Microsoft 发布 Cosmos DB GA 版……...
  7. 数据结构之线性表:单链表
  8. HDU 3487 Play with Chain(Splay)
  9. c++第三次上机实验项目四
  10. centos搭建NFS服务器
  11. Silverlight动态创建XAML对象和遍历对象
  12. Java 开源 CMS :magnolia
  13. DH参数法 例题 机器人学
  14. 计算机视觉知识体系图,计算机视觉系统框架的新构思
  15. MATLAB | MATLAB配色不够用 全网最全的colormap补充包来啦
  16. 软件开发学习的5大技巧,你知道吗?
  17. centOS最全下载地址
  18. 多任务多目标 CTR 预估技术
  19. 张量学习(6):张量代数
  20. Navicat中设计表时int类型的长度说明

热门文章

  1. jQuery中eq与get的区别(整理)
  2. Bind variables in 'in' condition(在in中动态的绑定参数(参数个数可变))
  3. Yaml spring boot 二维数组写法
  4. chromium 一些设置 --插件安装
  5. 【原创】定制ROM时自定义默认主题
  6. [转载] 随机游走和随机重启游走_网络动画API的随机游走
  7. 突然情怀就上来啦,‘闭包’ 今天咱们讲一下子
  8. Python基础---循环、条件判断
  9. UNP Chapter 19 - 多播
  10. Java学习之JDBC(1)