Java中HashMap和Hashtable的区别

Java中HashMap和Hashtable的区别

技术背景

在Java编程中,HashMapHashtable都是用于存储键值对的数据结构,它们都使用哈希技术来存储唯一的键。Hashtable是Java 1.0中引入的遗留类,而HashMap是Java 1.2引入的,是Java集合框架的一部分。了解它们之间的区别,有助于开发者根据具体的应用场景选择合适的数据结构。

实现步骤

1. 同步性

  • Hashtable是同步的,这意味着它是线程安全的,可以在多个线程之间共享。
  • HashMap是非同步的,不是线程安全的,在多线程环境下使用需要额外的同步代码。如果需要同步的HashMap,可以使用Collections.synchronizedMap(hashMap)方法。

2. 空键和空值

  • Hashtable不允许null键或值,若尝试插入null键或值,会抛出NullPointerException
  • HashMap允许一个null键和任意数量的null值。

3. 继承和迭代方式

  • Hashtable继承自Dictionary类,它可以通过EnumeratorIterator进行遍历,其中Enumerator不是快速失败的。
  • HashMap继承自AbstractMap类,它只能通过Iterator进行遍历,并且Iterator是快速失败的。

4. 初始容量和负载因子

  • HashMap构造一个空的哈希表,默认初始容量为16,默认负载因子为0.75。
  • Hashtable构造一个空的哈希表,默认初始容量为11,负载因子为0.75。

5. 结构修改和性能

  • 从Java 8开始,对于HashMap,如果哈希桶中的元素数量超过一定阈值(TREEIFY_THRESHOLD = 8),桶将从链表转换为平衡树(红黑树),当元素数量减少到一定程度(UNTREEIFY_THRESHOLD = 6)时,树将转换回链表。这提高了HashMap在高哈希冲突情况下的最坏情况性能,从O(n)提升到O(log n)。而Hashtable在发生哈希冲突时,仍然只使用链表存储元素。
  • 由于Hashtable是同步的,其性能通常比HashMap稍慢。

核心代码

以下是一个简单的示例,展示了HashMapHashtable的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class MapExample {
public static void main(String[] args) {
// HashMap示例
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("apple", 1);
hashMap.put(null, 2); // HashMap允许null键
hashMap.put("banana", null); // HashMap允许null值

// 同步的HashMap
Map<String, Integer> synchronizedHashMap = Collections.synchronizedMap(hashMap);

// Hashtable示例
Hashtable<String, Integer> hashtable = new Hashtable<>();
hashtable.put("cherry", 3);
// hashtable.put(null, 4); // 会抛出NullPointerException
// hashtable.put("date", null); // 会抛出NullPointerException
}
}

最佳实践

  • 单线程应用:如果应用程序是单线程的,建议使用HashMap,因为它没有同步带来的额外开销,性能更好。
  • 多线程应用:如果需要线程安全的集合,并且对性能要求不是特别高,可以使用Hashtable。但更推荐使用ConcurrentHashMap,它是Hashtable的现代替代品,具有更高的并发性能。

常见问题

1. ConcurrentModificationException问题

在使用HashMapIterator进行遍历时,如果在遍历过程中对HashMap进行了结构修改(除了通过Iteratorremove()方法),会抛出ConcurrentModificationException。而HashtableEnumerator不会抛出此异常,但不保证遍历结果的一致性。

2. 性能问题

在高并发场景下,Hashtable的同步机制可能会导致性能瓶颈。此时应考虑使用ConcurrentHashMap

3. 兼容性问题

如果需要与旧代码或遗留系统兼容,可能需要使用Hashtable。但在新开发的代码中,应优先考虑HashMapConcurrentHashMap


Java中HashMap和Hashtable的区别
https://119291.xyz/posts/2025-05-09.differences-between-hashmap-and-hashtable-in-java/
作者
ww
发布于
2025年5月9日
许可协议