概览:

内部存储的数据结构为:数组+链表+红黑树,图示:

重要的属性(内部类):

//存放元素的数组
transient volatile Node<K,V>[] table;
//数组中的Node节点
static class Node<K,V> implements Map.Entry<K,V> {final int hash;//Key计算出来的Hash值final K key;//Keyvolatile V val;//Valuevolatile Node<K,V> next;//链表的下一个节点
Node(int hash, K key, V val, Node<K,V> next) {this.hash = hash;this.key = key;this.val = val;this.next = next;}...//省略
    }
//红黑树中的节点
static final class TreeNode<K,V> extends Node<K,V> {TreeNode<K,V> parent;  // red-black tree linksTreeNode<K,V> left;       //左子节点TreeNode<K,V> right;    //右子节点TreeNode<K,V> prev;    //
        boolean red;...//省略
    }//组合TreeNode
static final class TreeBin<K,V> extends Node<K,V> {TreeNode<K,V> root;volatile TreeNode<K,V> first;}//内部类

方法分析

 /** Implementation for put and putIfAbsent */final V putVal(K key, V value, boolean onlyIfAbsent) {if (key == null || value == null) throw new NullPointerException();int hash = spread(key.hashCode());int binCount = 0;for (Node<K,V>[] tab = table;;) {Node<K,V> f; int n, i, fh;if (tab == null || (n = tab.length) == 0)tab = initTable();//初始化数组大小,默认16//数组指定位置元素为空,直接插入else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {if (casTabAt(tab, i, null,new Node<K,V>(hash, key, value, null)))break;                   // no lock when adding to empty bin
            }else if ((fh = f.hash) == MOVED)tab = helpTransfer(tab, f);else {//不为空,链表存储V oldVal = null;synchronized (f) {if (tabAt(tab, i) == f) {if (fh >= 0) {binCount = 1;for (Node<K,V> e = f;; ++binCount) {K ek;if (e.hash == hash &&((ek = e.key) == key ||(ek != null && key.equals(ek)))) {oldVal = e.val;if (!onlyIfAbsent)e.val = value;break;}Node<K,V> pred = e;if ((e = e.next) == null) {pred.next = new Node<K,V>(hash, key,value, null);break;}}}//红黑树else if (f instanceof TreeBin) {Node<K,V> p;binCount = 2;if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,value)) != null) {oldVal = p.val;if (!onlyIfAbsent)p.val = value;}}}}if (binCount != 0) {//链表长度大于8,转为红黑树存储if (binCount >= TREEIFY_THRESHOLD)treeifyBin(tab, i);if (oldVal != null)return oldVal;break;}}}addCount(1L, binCount);return null;}

/*** Replaces all linked nodes in bin at given index unless table is* too small, in which case resizes instead.*/private final void treeifyBin(Node<K,V>[] tab, int index) {Node<K,V> b; int n, sc;if (tab != null) {if ((n = tab.length) < MIN_TREEIFY_CAPACITY)tryPresize(n << 1);//扩容数组else if ((b = tabAt(tab, index)) != null && b.hash >= 0) {synchronized (b) {if (tabAt(tab, index) == b) {TreeNode<K,V> hd = null, tl = null;              //遍历链表,构造TreeNodefor (Node<K,V> e = b; e != null; e = e.next) {TreeNode<K,V> p =new TreeNode<K,V>(e.hash, e.key, e.val,null, null);if ((p.prev = tl) == null)hd = p;elsetl.next = p;tl = p;}//构建红黑树setTabAt(tab, index, new TreeBin<K,V>(hd));}}}}}

 public V get(Object key) {Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;int h = spread(key.hashCode());if ((tab = table) != null && (n = tab.length) > 0 &&(e = tabAt(tab, (n - 1) & h)) != null) {if ((eh = e.hash) == h) {if ((ek = e.key) == key || (ek != null && key.equals(ek)))return e.val;}else if (eh < 0)//红黑树取值return (p = e.find(h, key)) != null ? p.val : null; //链表取值while ((e = e.next) != null) {if (e.hash == h &&((ek = e.key) == key || (ek != null && key.equals(ek))))return e.val;}}return null;}

写在最后:

为什么使用红黑树?

红黑树的特性:

1、节点是红色或者黑色

2、根是黑色

3、所有叶子都是黑色

4、每个红色节点必须有2个黑色的子节点

5、从任一节点到其每个叶子的所有简单路径包含相同数目的黑色节点

  根据特性5,从根的最长路径不可能>2倍的最短路径,所以这样的二叉树是平衡的;插入、删除、查询操作比较高效

拓展阅读

    1、红黑树介绍    2、深入分析ConcurrentHashMap1.8的扩容实现

转载于:https://www.cnblogs.com/Non-Tecnology/p/6560903.html

ConcurrentHashMap笔记相关推荐

  1. Java基础知识强化之集合框架笔记76:ConcurrentHashMap之 ConcurrentHashMap简介

    1. ConcurrentHashMap简介: ConcurrentHashMap是一个线程安全的Hash Table,它的主要功能是提供了一组和Hashtable功能相同但是线程安全的方法.Conc ...

  2. java温故笔记(二)java的数组HashMap、ConcurrentHashMap、ArrayList、LinkedList

    为什么80%的码农都做不了架构师?>>>    HashMap 摘要 HashMap是Java程序员使用频率最高的用于映射(键值对)处理的数据类型.随着JDK(Java Develo ...

  3. ConcurrentHashMap 学习笔记

    # ConcurrentHashMap HashMap虽然好用,但是它却不是线程安全的,而在并发度较高的现在,在有些情况下它可能就不是那么合适了,所以需要一个线程安全键值对结构. Hashtable是 ...

  4. sheng的学习笔记-ConcurrentHashMap(JDK1.7和16)源码分析

    1.7版本 概述 注意,以下代码都是1.7版本(不同版本代码不一样),最下面有1.8版本部分内容 ConcurrentHashMap是线程安全的key value存储结构,底层也是数组+链表的结构 下 ...

  5. ConcurrentHashMap源码jdk1.8学习笔记

    目录 put方法 initTable方法 helpTransfer方法 transfer方法 addCount方法 put方法 public V put(K key, V value) {// 直接调 ...

  6. 【笔记】ConcurrentHashMap,保证线程安全,并且效率高

  7. 线程关键字、锁、同步集合笔记

    Android开发笔记 onGithub [TOC] 1.原子性.可见性.有序性 1.1 原子性 指一个操作是不可中断的,即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都 ...

  8. 学习笔记:cache 和spring cache 技术(1)

    title: 学习笔记:cache 和spring cache 技术(1) author: Eric liu tags: [] categories: hexo 缓存是实际工作中非常常用的一种提高性能 ...

  9. Spring读书笔记——bean创建(下)

    有关Spring加载bean系列,今天这是最后一篇了,主要接上篇对于从Spring容器中获取Bean的一些细节实现的补充. <Spring读书笔记--bean加载>--Spring如何加载 ...

最新文章

  1. Docker入门六部曲——Stack
  2. nodejs mysql 异步_Gearman + Nodejs + MySQL UDF异步实现 MySQL 到 Redis 的数据同步
  3. 更新网盘(云存储)功能需求,免费网盘需求,手机数据备份
  4. 注册用户模块 password bug
  5. aes c android ios,AES加密在iOS和Android中产生不同的结果
  6. select、poll、epoll使用小结
  7. 双层板在哪层覆铜_PCB覆铜箔层压板分类和工艺解析
  8. flutter用英语怎么说_手机流量套餐用英语怎么说?
  9. 网络基础---NAT穿越技术
  10. html画表盘 随时间转动,HTML5 canvas圆形时钟指针平缓转动随机切换表盘颜色
  11. 山景BP1048使用记录
  12. 微信小程序picker默认请选择
  13. 今日头条运营秘诀分享:让你的文章阅读量和收入都“飞”起来
  14. 教你如何申请个人域名
  15. C语言的access函数的用法
  16. Windows Ubuntu 子系统修改默认登陆用户·
  17. PostgreSQL引入的JSONB解释
  18. 思科EtherChannel链路聚合
  19. 错题日志(哈理工热身赛)
  20. VUE“粘性”阅读进度条

热门文章

  1. 【opencv学习】【图像的数值计算操作】
  2. 每天进步一点点《PCA的简要学习》
  3. 本地计算机用plsql访问虚拟机中的oracle数据库
  4. [深度学习-实践]tensorflow_hub简单理解模型的生成与加载
  5. 面向消费者的自动文本分析(Automated Text Analysis for Consumer Research) 2017 JCR 论文阅读
  6. Tooltip工具提示控件的使用
  7. 爬虫学习二: bs4 xpath re
  8. 欧几里得算法和扩展欧几里得算法的简单例子
  9. 线性代数【8】-1 线性方程组
  10. php mysql开发技术_PHP+MySQL开发技术详解—学习笔记