HashMap和Hashtable的区别

概述
HashMap和Hashtable都是Java常见的基于哈希表实现的Map接口的实现类,它们都用于存储键值对映射关系。
(1)HashMap是非线程安全的,HashTable是线程安全的,内部的方法基本都经过synchronized修饰。
(2)因为同步、哈希性能等原因,性能肯定是HashMap更佳,因此HashTable已被淘汰。
(3)HashMap允许有null值的存在,而在HashTable中put进的键值只要有一个null,直接抛出NullPointerException。
(4)HashMap默认初始化数组的大小为16,HashTable为11。前者扩容时乘2,使用位运算取得哈希,效率高于取模。 而后者为乘2加1,都是素数和奇数,这样取模哈希结果更均匀。
HashMap的键-值都可以为空(null),线程不安全。有一个类ConcurrentHashMap是安全的
Hashtable的键-值都不可以为空(null),线程安全 ,
一般情况下用HashMap
Hashtable中hash数组默认大小是11,扩充方式是old*2+1
HashMap中hash数组的默认大小是16,而且一定是2的指数

1. 数据结构
HashMap和Hashtable都是基于哈希表实现的Map接口的实现类,但是它们采用的哈希算法和数据结构有所不同。
HashMap
HashMap底层采用数组+链表/红黑树的数据结构实现,当哈希冲突发生时,会使用链表或者红黑树来解决冲突。HashMap中有一个负载因子(load factor)的概念,默认情况下负载因子为0.75,如果容量和负载因子的乘积大于元素个数时,就需要进行扩容操作。扩容一般是将原来的HashMap数组翻倍,再重新计算哈希码,将元素插入到新的数组中。
Hashtable
Hashtable底层也采用数组+链表的数据结构进行实现,当哈希冲突发生时,使用链表来解决冲突。与HashMap不同的是,Hashtable在JDK 8及以前没有使用红黑树解决哈希冲突,这导致了其效率相对较低。初始容量为11,负载因子为0.75,每次扩容时容量翻倍再加1。HashTable容量可以为任意整数,最小为1。
2. 线程安全性
线程安全性指在多线程环境下,数据的并发访问是否会产生问题。HashMap和Hashtable在线程安全性上有所不同。
HashMap
HashMap不是线程安全的类,即多个线程同时操作HashMap可能导致出现错误的结果或者抛出ConcurrentModificationException异常。但是,可以通过Collections的synchronizedMap方法来使HashMap变成线程安全的类。下面是一个使用synchronizedMap方法实现的线程安全的HashMap示例代码:
Map<String, String> map = new HashMap<>();
Map<String, String> syncMap = Collections.synchronizedMap(map);
Hashtable
Hashtable是线程安全的类,即多个线程同时操作Hashtable中的元素也不会产生错误的结果或者抛出ConcurrentModificationException异常。
3. null值和null键
null值和null键是Java中非常常见的情况,HashMap和Hashtable在处理null值和null键上也有所不同。
HashMap
HashMap中可以存储null值和null键,但是要注意,当使用null作为键时,由于无法调用null的hashCode()方法,因此只能将其放在哈希表的第一个位置,它们是无序的。对于null值,因为可以使用null调用equals()方法,所以可以用作值。
Hashtable
Hashtable不允许存储null值和null键,否则将会抛出NullPointerException异常。
4. 性能比较
HashMap和Hashtable在性能上也有所不同,下面我们来具体分析一下。
HashMap
由于HashMap采用链表和红黑树的数据结构,可以更好地处理哈希冲突,因此HashMap的查找、插入和删除操作都是常数时间O(1),它的性能相对于Hashtable更高
Hashtable
Hashtable没有使用红黑树解决哈希冲突,而且所有方法都加了同步锁,相对于HashMap而言,Hashtable的效率比较低。另外,由于Hashtable不支持null键和null值,因此对其进行操作时要额外小心。Hashtable的查找、插入和删除操作平均时间复杂度为O(1),但是在极端情况下,因为哈希冲突的原因,可能会退化到O(n)。
5. 应用场景
根据上述的区别和特点,我们可以得出以下建议:
如果线程安全的Map集合,并且不需要存储null键或null值,可以选择Hashtable;
如果需要高效、非线程安全的Map集合,并且需要存储null键或null值,可以选择HashMap;
如果需要高效、线程安全的Map集合,可以选择使用ConcurrentHashMap。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
HashMapHashtable 都是用于存储键值对的数据结构,它们在功能上非常相似,但也存在一些区别。 1. 线程安全性:Hashtable 是线程安全的,即多个线程可以同时访问一个 Hashtable 实例而不需要额外的同步措施。而 HashMap 不是线程安全的,如果多个线程同时访问一个 HashMap 实例,可能会导致数据不一致的问题。如果需要在多线程环境下使用,可以考虑使用 ConcurrentHashMap。 2. null 键和 null 值:Hashtable 不允许键或值为 null,如果尝试将 null 键或 null 值放入 Hashtable 中,会抛出 NullPointerException。而 HashMap 允许键和值为 null,可以正常存储和获取 null 值。 3. 继承关系:Hashtable 是 Dictionary 类的子类,而 HashMap 是 AbstractMap 类的子类。由于继承关系的不同,导致它们在实现上有一些差异。 4. 迭代顺序:HashMap 不保证迭代顺序,即遍历 HashMap 的键值对时,不一定按照插入顺序或者其他顺序进行遍历。而 Hashtable 的迭代顺序是按照插入顺序进行的。 5. 性能:由于 Hashtable 是线程安全的,它在多线程环境下的性能可能会受到一定影响。而 HashMap 在单线程环境下的性能通常会更好。 总的来说,如果在单线程环境下使用,并且需要允许键或值为 null,可以优先选择使用 HashMap。如果在多线程环境下使用,或者需要保证迭代顺序,可以考虑使用 Hashtable
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

思静语

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

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

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

打赏作者

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

抵扣说明:

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

余额充值