HashTable、HashMap和ConcurrentHashMap的区别

HashTable

  继承于Dictionary, 不可存储null键和值, 底层基于数组+链表(HashTable数据结构不同于HashMap的是,不会转化为红黑树),父类方法少于AbstractMap, 只有基本的get, put, remote, 没有putAll, keySet等, 线程安全。
  线程安全。线程安全主要依靠synchronized关键字,因此效率较低。初始化最好赋值size。
HashTable继承结构

HashMap

  继承于AbstractMap可存储null键和值, key值不重复无序,线程不安全初始化最好赋值size,因为默认的size是16, 当存储的键值对超过这个size时,会触发扩容,而rehash会对所有键值对rehash,造成不必要的资源浪费。
HashMap继承结构

HashMap变量

在这里插入图片描述

变量 说明
DEFAULT_INITIAL_CAPACITY 默认初始容量: 16
MAXINUM_CAPACITY 默认最大容量
DEFAULT_LOAD_FACTOR 默认负载因子: 0.75
TREEIFY_THRESHOLD 链表长度大于8,链表转化为红黑树
UNTREEIFY_THRESHOLD 链表长度小于6, 树退化为链表
MIN_TREEIFY_CAPACITY 桶数大于64, 才会发生转换

HashMap结构

在这里插入图片描述
HashMap里,是一个数组, 数组的每个元素是一个单向链表,链表中每个每个Node, 包含四个属性:keyvaluenexthash

ConcurrentHashMap(并发哈希映射)

  继承于AbstractMap, 不能存储null键和值,底层基于数组+链表线程安全。默认容量是16(即16个桶),默认负载因子0.75,扩容默认增加一倍。初始化最好赋值size。
  ConcurrentHashMap结构类似于HashMap,ConcurrentHashMap中使用Segment代替了HashMap中的链表,而Segment继承了ReentrantLock。每次加锁的操作, 实际是锁住了每一个Segment,每个Segment只能被一个线程操作,保证了整体的线程安全。称为分桶锁机制。
  JDK1.7,ConcurrentHashMap在分桶锁的基础上引入了读写锁:

  • 读锁:允许多个线程同时读,但是不允许线程写
  • 写锁:只允许一个线程写,但是不允许线程读

  JDK1.8之前,向桶中的链表添加元素的时候,采用的是头插法;从JDK1.8开始,向桶中的链表添加元素的时候,采用的是尾追法
  JDK1.8开始,ConcurrentHashMap引入了红黑树机制:当桶中的元素个数超过8个,桶中链表转成一棵红黑树;当桶中红黑树的节点个数不足7个,红黑树退化为链表。只有当桶的数量>=64的时候,才会开启红黑树机制
ConcurrentHashMap继承结构

ConcurrentHashMap结构

在这里插入图片描述

发布了27 篇原创文章 · 获赞 0 · 访问量 2024

猜你喜欢

转载自blog.csdn.net/qq_32834005/article/details/104981930