HashMap、HashTable与ConcurrentHashMap的区别与联系

HashMap        

        HashMap 是基于哈希表的 Map 接口实现,它存储的内容是键值对(key-value)。HashMap 的底层实现原理涉及数组、链表和红黑树的结合使用。

HashMap的数据结构

        HashMap 的内部结构是一个数组(Node[] table),这个数组的每个元素都是一个链表的头节点。当链表的长度超过一定阈值(默认为8),并且数组的大小不小于64,链表结构会转换成红黑树结构,这样可以提高查询效率。

键值对的存储原理(put方法)

        当使用 put 方法存储键值对时,HashMap 会首先计算键(key)的 hashCode,然后通过哈希算法将这个 hashCode 转换成数组的下标,从而确定在数组中的存储位置。如果该位置没有其他元素,新的键值对就直接存储在这里。如果位置已经有元素存在,就会发生哈希冲突,新的元素会以链表的形式存储在这个位置的末尾。在 Java 8 中,如果链表的长度超过8,链表会转换成红黑树。

扩容机制

        当 HashMap 中的元素数量达到数组大小与加载因子(默认为0.75)的乘积时,数组会进行扩容,通常是扩容为原来的两倍。扩容是一个成本较高的操作,因为它涉及到重新计算每个元素的存储位置并将它们移动到新的数组中。

红黑树的引入

        为了解决链表长度过长导致的查询效率低下的问题,Java 8 引入了红黑树。红黑树是一种自平衡的二叉查找树,它保证了最坏情况下的时间复杂度为 O(log n),大大优化了长链表的查询速度。

重要考虑

  • 线程安全:HashMap 不是线程安全的,如果需要在多线程环境中使用,可以考虑使用 ConcurrentHashMap

  • 键的不变性:作为键的对象最好是不可变的,或者至少保证在作为 HashMap 键的生命周期内不会改变,因为这会影响 hashCode 的计算和键值对的位置。

  • 负载因子和初始容量:合理的设置负载因子和初始容量可以减少扩容操作,提高 HashMap 的性能。

HashTable

数据结构

        HashTable底层也是使用数组+链表的数据结构来存储数据。但与HashMap不同的是,HashTable中的数组每个元素的初始状态就是一个链表,而HashMap是当发生哈希冲突时才使用链表。

线程安全性

        与HashMap不同,HashTable是线程安全的。这是因为HashTable的主要方法,如put、get、remove等,都有synchronized修饰,确保在多线程环境下,只有一个线程能操作HashTable,从而保证线程安全。

不允许null键和null值

        HashTable不允许使用null作为键或值,如果尝试将null作为键或值放入HashTable,会抛出NullPointerException。而HashMap则允许使用null作为键或值。

性能

        因为HashTable的所有主要方法都加了synchronized关键字,所以在单线程环境下,HashTable的性能会比HashMap差一些。而在多线程环境下,由于HashTable的线程安全特性,其性能可能会优于HashMap。

扩容机制

        当HashTable中的元素数量达到一定的阈值时,也会触发扩容。扩容后的HashTable大小会是原大小的两倍,并且所有的元素都需要被重新哈希,放入新的数组位置。

ConcurrentHashMap

ConcurrentHashMap是线程安全的数组,是HashTable的替代品,同为线程安全,其性能要比HashTable更好

分段锁机制将数据分成多个 segment 来实现锁的粒度更细,从而减小锁的竞争范围,提高并发性能。

CAS 乐观锁算法(Compare and Swap)CAS操作包含三个操作数:内存位置(V)、预期原值(A)和新值(B)。如果内存位置V的值与预期原值A相匹配,那么将内存位置V的值更新为新值B,返回true;如果不匹配,则不做任何操作并返回false。整个过程是原子的。

扩容机制默认的加载因子是0.75,意味着当表填满到3/4时,扩容2倍,默认为16过程将开始。扩容时,会创建一个新的、容量更大的哈希表,新容量通常是旧容量的两倍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰冰很社恐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值