第3课_HashMap与Hashtable
热度🔥:87 免费课程
授课语音
Java 中的 HashMap
与 Hashtable
的区别
在 Java 中,HashMap
和 Hashtable
都是实现了 Map
接口的哈希表类,它们的作用是存储键值对数据。在并发编程的背景下,尽管它们在功能上非常相似,但在设计和性能上存在显著差异。了解这些区别有助于根据具体需求选择适合的容器。
1. HashMap 与 Hashtable 概述
1.1 HashMap
HashMap
是 Java 中最常用的哈希表实现,它允许键和值为 null
,并且是非线程安全的。HashMap
适用于在单线程环境或自己通过外部同步机制保证线程安全的场景。
特点:
- 非线程安全:多线程访问时需要自己做同步处理。
- 允许
null
键和值:可以有一个null
键和多个null
值。 - 性能较高:在单线程环境下,它的性能比
Hashtable
好,因为它没有进行额外的同步控制。 - 遍历顺序不可预测:
HashMap
的键值对是无序的,插入顺序不会影响遍历顺序。
1.2 Hashtable
Hashtable
是早期的哈希表实现,已被 HashMap
取代。它是线程安全的,所有方法都是同步的,但是它的性能相较于 HashMap
较差。
特点:
- 线程安全:所有的方法都使用了同步机制,因此它是线程安全的,但由于同步的原因,性能较差。
- 不允许
null
键和值:Hashtable
不允许插入null
键或null
值。 - 较低性能:由于同步机制,
Hashtable
在并发访问下的性能较差。 - 遍历顺序不可预测:和
HashMap
一样,Hashtable
的键值对顺序是无序的。
2. HashMap 与 Hashtable 的对比
特性 | HashMap | Hashtable |
---|---|---|
线程安全性 | 非线程安全 | 线程安全(同步方法) |
键和值是否可以为 null |
允许一个 null 键和多个 null 值 |
不允许 null 键和值 |
性能 | 较高(适用于单线程或自己同步的场景) | 较低(同步导致性能开销) |
同步机制 | 无内置同步机制 | 使用 synchronized 进行同步 |
适用场景 | 在单线程环境下使用,或外部保证线程安全的场景 | 在多线程环境下使用,但性能较差 |
3. HashMap 与 Hashtable 的代码示例
3.1 HashMap 示例
import java.util.HashMap;
public class HashMapExample {
public static void main(String[] args) {
// 创建一个 HashMap
HashMap<String, String> map = new HashMap<>();
// 向 HashMap 中添加元素
map.put("name", "Alice");
map.put("language", "Java");
map.put("framework", "Spring");
// 允许插入 null 键和值
map.put(null, "Unknown");
map.put("nullValue", null);
// 获取元素
System.out.println("name: " + map.get("name"));
System.out.println("language: " + map.get("language"));
// 删除元素
map.remove("framework");
// 输出 HashMap
System.out.println("HashMap 内容: " + map);
}
}
代码解析:
HashMap
允许使用null
作为键和值。- 在单线程环境下,它的性能非常高。
- 由于
HashMap
是非线程安全的,因此在多线程环境下使用时,必须自行保证同步。
输出示例:
name: Alice
language: Java
HashMap 内容: {name=Alice, null=Unknown, language=Java, nullValue=null}
3.2 Hashtable 示例
import java.util.Hashtable;
public class HashtableExample {
public static void main(String[] args) {
// 创建一个 Hashtable
Hashtable<String, String> table = new Hashtable<>();
// 向 Hashtable 中添加元素
table.put("name", "Bob");
table.put("language", "Java");
// 不允许插入 null 键或 null 值
// table.put(null, "Unknown"); // 会抛出 NullPointerException
// table.put("nullValue", null); // 会抛出 NullPointerException
// 获取元素
System.out.println("name: " + table.get("name"));
System.out.println("language: " + table.get("language"));
// 删除元素
table.remove("language");
// 输出 Hashtable
System.out.println("Hashtable 内容: " + table);
}
}
代码解析:
Hashtable
不允许插入null
键或null
值。- 每个方法都被同步,因此即使在多线程环境下,
Hashtable
也能保证线程安全。 - 由于同步操作的存在,
Hashtable
的性能通常低于HashMap
。
输出示例:
name: Bob
Hashtable 内容: {name=Bob}
4. 总结
特性 | HashMap | Hashtable |
---|---|---|
线程安全性 | 非线程安全 | 线程安全(通过同步) |
允许 null 键和值 |
允许(最多一个 null 键,多个 null 值) |
不允许 null 键和值 |
性能 | 较高(适用于单线程或外部同步的场景) | 较低(同步带来性能开销) |
适用场景 | 单线程或外部同步的场景 | 多线程环境下,但性能较差 |
总结来说,HashMap
和 Hashtable
的主要区别在于线程安全性和性能。HashMap
适用于单线程或需要自己控制同步的场景,而 Hashtable
则适用于需要内建线程安全的多线程环境,但由于同步机制,它的性能通常低于 HashMap
。