• 【Java】HashMap、HashTable和ConcurrentHashMap的区别


    在这里插入图片描述


    HashTable、HashMap和ConcurrentHashMap之间的区别主要体现在线程安全、继承关系与实现接口、对null值的处理、性能以及数据结构等几个方面。以下是对这三者之间区别的详细分析:

    区别

    项目HashMapHashTableConcurrentHashMap
    null键允许(仅能有一个)不允许允许(仅能有一个)
    null值允许不允许允许
    性能高(单线程下最高)多线程下优于HashTable
    数据结构数组+链表+红黑树数组+链表数组+链表+红黑树
    继承关系AbstractMap类Dictionary类AbstractMap类
    实现接口实现了Map接口Cloneable接口和Serializable接口实现了Map接口实现了Map接口、Cloneable接口和Serializable接口
    线程安全不安全安全安全
    同步方式synchronized同步方法1.7版本:基于segment分段锁机制,基于ReentrantLock实现;1.8版本:基于CAS+synchronized实现,空节点插入使用CAS,有Node节点则使用synchronized加锁

    一、HashMap

    HashMap是Java中的一种基于哈希表实现的数据结构,它实现了Map接口并允许使用null键和null值。

    1.1基本定义与特性

    基于哈希表: HashMap是基于哈希表实现的,通过哈希函数将键映射到索引位置,实现快速查找。
    允许null键和值: 与HashTable不同,HashMap允许使用null作为键和值。
    非线程安全: HashMap不是线程安全的,因此在多线程环境下使用时需要注意数据一致性问题。

    1.2工作原理与实现

    哈希函数: HashMap使用哈希函数将键转换为索引,该函数需要满足确定性、高效性和散列性。
    冲突解决: 采用链地址法处理哈希冲突,即多个键哈希到同一个索引时,它们会被链接到一个链表中。
    动态扩容: 当元素数量超过当前容量的阈值时,HashMap会进行rehashing,创建一个新的数组,并将原数组中的元素重新哈希到新的数组中。

    1.3常用方法

    put(K key, V value): 向HashMap中添加一个键值对。
    get(Object key): 根据键获取对应的值。
    remove(Object key): 删除HashMap中指定的键值对。
    size(): 返回HashMap中键值对的数量。
    isEmpty(): 判断HashMap是否为空。
    keySet(): 返回HashMap中所有键的集合。
    values(): 返回HashMap中所有值的集合。
    entrySet(): 返回HashMap中所有键值对组成的集合。

    1.4性能与优化

    时间复杂度: HashMap的查找、插入和删除操作的平均时间复杂度为O(1),但在哈希冲突严重时,性能会下降。
    链接: 【哈希表】为什么哈希表的插入/删除/查找时间复杂度为O(1)

    初始容量与加载因子: 合理设置HashMap的初始容量和加载因子可以提高性能。初始容量是HashMap创建时分配的数组大小,加载因子是触发扩容的阈值。
    红黑树优化: 在JDK 1.8及以后的版本中,当链表长度超过一定阈值时,HashMap会将链表转换为红黑树以提高查找性能。

    总之,HashMap是一种高效且灵活的数据结构,适用于需要快速查找键值对的场景。在使用时需要注意其非线程安全的特性,并在必要时采取适当的同步措施。

    二、HashTable

    HashTable(哈希表)是一种根据关键码值直接进行访问的数据结构。它通过特定的哈希函数将关键码值映射到表中的一个位置,以加快数据查找的速度。

    1. HashTable同样是基于哈希表实现,存储的数据同样为key-value键值对,其内部也是通过单链表解决哈希冲突的,容量不足时,同样会自动扩容;

    2. 线程安全,可以用于多线程场景。它的线程安全实现方式是:所有的方法都使用synchronized加锁,像一些读操作不存在线程不安全问题,所以全部方法加锁导致了效率低下。

    3. 现在已经被丢了不再使用了。不涉及线程安全问题时使用HashMap,要保证线程安全时,使用ConcurrentHashMap。

    三、ConcurrentHashMap

    ConcurrentHashMap是Java集合框架中的一个类,它是HashMap的一个线程安全版本,专为高并发场景设计

    3.1基本特点

    线程安全: ConcurrentHashMap通过特殊的锁机制和数据结构来确保线程安全,使得多个线程可以并发地读写不同的数据段,而不需要额外的同步措施。

    高并发性能: 由于采用了分段锁机制(在Java 8之前)或更精细的锁策略(如CAS和synchronized在Java 8及之后),ConcurrentHashMap能够支持多个线程同时访问不同的数据段,从而提高了并发性能。

    支持高效的读操作: 在没有竞争的情况下,读操作几乎没有性能损耗,因为它们可以并行执行。

    不允许null键或值: 与HashMap不同,ConcurrentHashMap不允许键或值为null。

    3.2实现原理

    分段锁机制(Java 7及之前): ConcurrentHashMap在内部将数据分为多个段(Segment),每个段都有自己的锁。当一个线程访问某个段时,它只会锁定该段,而不会锁定整个ConcurrentHashMap。这使得多个线程可以同时访问不同的段,从而提高了并发性能。

    更精细的锁策略(Java 8及之后): 在Java 8中,ConcurrentHashMap的实现进行了改进,不再使用分段锁,而是采用了CAS操作和synchronized关键字来实现更精细的锁控制,进一步提高了并发性能。

    3.3常用方法

    ConcurrentHashMap提供了一系列与HashMap相似的方法,如put、get、remove等,这些方法都是线程安全的。
    此外,它还提供了一些原子操作,如putIfAbsent、remove、replace等。

    3.4适用场景

    ConcurrentHashMap适用于需要在线程安全的环境下使用HashMap的场景,特别是需要实现高并发下的数据访问控制的场景
    例如,在多线程环境中记录日志信息时,可以使用ConcurrentHashMap来存储日志数据,以确保数据的一致性和安全性。

    3.5性能优化

    Java 8对ConcurrentHashMap进行了一些性能优化,包括利用CAS操作替换了之前的Synchronized关键字来减少锁的争用等。这些优化进一步提高了ConcurrentHashMap的并发性能。


    以上就是本文所有内容,如果对你有帮助的话,点赞收藏支持一下吧!💞💞💞

  • 相关阅读:
    自动驾驶技术简史
    软件工程毕业设计课题(65)微信小程序毕业设计PHP食堂餐厅预约订座小程序系统设计与实现
    【Python百日进阶-Web开发-Peewee】Day279 - SQLite 扩展(四)
    C#数据库操作
    centos使用lftp备份文件
    为什么 JVM 叫做基于栈的 RISC 虚拟机?
    springboot读取配置文件自定义参数和自定义配置文件参数
    分布式IO系统BL201 Profinet耦合器
    一种基于闭包函数实现自动化框架断言组件的设计实践
    腾讯插件化框架shadow
  • 原文地址:https://blog.csdn.net/2202_75795446/article/details/138036365