Java 实例 – 使用 Enumeration 遍历 HashTable
在 Java 的集合框架中,HashTable 是一个经典的线程安全的键值对容器,虽然现在更推荐使用 ConcurrentHashMap,但在一些遗留系统或特定场景下,HashTable 依然有其存在的价值。今天我们要深入讲解一个非常实用的 Java 实例:使用 Enumeration 遍历 HashTable。
这个技术看似简单,但掌握它能帮助你理解 Java 早期集合的设计思想,也能让你在处理旧代码时更加游刃有余。尤其对于初学者来说,理解 Enumeration 与 Iterator 的区别,是迈向高级 Java 编程的重要一步。
HashTable 的基本概念与特点
HashTable 是 Java 早期提供的一个映射类,它实现了 Map 接口,用于存储键值对(key-value pairs)。它的核心特点包括:
- 线程安全:所有操作都加了同步锁,适合多线程环境。
- 不允许 null 键或 null 值:如果尝试插入 null 键或值,会抛出 NullPointerException。
- 基于哈希算法:通过 key 的 hashCode() 方法计算存储位置,提高查找效率。
你可以把 HashTable 想象成一个“带密码锁的抽屉柜”——每个抽屉都有一个唯一的编号(key),而里面放着对应的东西(value)。你要找某个东西,就得先知道它的编号,然后去对应的抽屉里拿。
什么是 Enumeration?它与 Iterator 的区别
在 Java 早期版本中,Enumeration 是一种用于遍历集合的接口。虽然现在更推荐使用 Iterator,但 HashTable 依然保留了 Enumeration 的支持,因为它是“历史遗留”的设计。
Enumeration 的核心方法:
hasMoreElements():判断是否还有下一个元素。nextElement():获取下一个元素。
与 Iterator 的对比:
| 特性 | Enumeration | Iterator |
|---|---|---|
| 出现时间 | Java 1.0 | Java 1.2 |
| 是否支持 remove 操作 | 不支持 | 支持 |
| 方法命名 | hasMoreElements / nextElement | hasNext / next |
| 是否通用 | 仅用于旧集合(如 Vector、Hashtable) | 通用,适用于所有 Collection |
简单来说,Enumeration 是一个“只读”的遍历工具,就像你只能看,不能动抽屉里的东西。而 Iterator 更像是一个“可编辑”的助手,可以帮你删东西。
创建 HashTable 并插入数据
我们先来创建一个 HashTable 实例,并加入一些数据,为后续遍历做准备。
import java.util.Enumeration;
import java.util.Hashtable;
public class HashTableEnumerationExample {
public static void main(String[] args) {
// 创建一个 HashTable 实例,指定泛型类型为 String -> Integer
Hashtable<String, Integer> studentScores = new Hashtable<>();
// 向 HashTable 中添加键值对
studentScores.put("张三", 85);
studentScores.put("李四", 92);
studentScores.put("王五", 78);
studentScores.put("赵六", 96);
studentScores.put("钱七", 88);
// 输出当前 HashTable 内容,用于验证
System.out.println("当前学生分数表:");
System.out.println(studentScores);
}
}
✅ 注释说明:
Hashtable<String, Integer>:声明一个键为 String 类型、值为 Integer 类型的 HashTable。put(key, value):将键值对存入 HashTable。System.out.println(studentScores):直接输出 HashTable,会显示所有键值对。
运行这段代码,你将看到类似输出:
当前学生分数表:
{张三=85, 李四=92, 王五=78, 赵六=96, 钱七=88}
使用 Enumeration 遍历 HashTable
现在我们进入核心部分:使用 Enumeration 遍历 HashTable。
// 获取 HashTable 的 Enumeration 对象
Enumeration<String> keys = studentScores.keys();
// 开始遍历
System.out.println("\n使用 Enumeration 遍历所有键:");
while (keys.hasMoreElements()) {
String key = keys.nextElement();
Integer score = studentScores.get(key);
System.out.println("学生:" + key + ",分数:" + score);
}
✅ 注释说明:
studentScores.keys():返回一个 Enumeration,包含所有键(key)的迭代器。hasMoreElements():检查是否还有未遍历的键。nextElement():取出下一个键,并移动指针。get(key):根据键获取对应的值,用于打印分数。
这段代码的执行结果如下:
使用 Enumeration 遍历所有键:
学生:张三,分数:85
学生:李四,分数:92
学生:王五,分数:78
学生:赵六,分数:96
学生:钱七,分数:88
💡 小贴士:由于 HashTable 的底层是哈希表,遍历顺序不保证与插入顺序一致,所以你看到的输出可能和插入顺序不一样。这就像你从一个随机编号的抽屉柜里拿东西,顺序是随机的。
遍历值(Values)的 Enumeration 使用方式
除了遍历键,我们也可以遍历值。HashTable 提供了 elements() 方法来获取值的 Enumeration。
// 获取所有值的 Enumeration
Enumeration<Integer> scores = studentScores.elements();
System.out.println("\n使用 Enumeration 遍历所有分数:");
while (scores.hasMoreElements()) {
Integer score = scores.nextElement();
System.out.println("分数:" + score);
}
✅ 注释说明:
studentScores.elements():返回一个包含所有值的 Enumeration。- 遍历逻辑与键相同,但只处理值。
输出示例:
使用 Enumeration 遍历所有分数:
分数:85
分数:92
分数:78
分数:96
分数:88
与 Iterator 的对比:为什么还要用 Enumeration?
虽然现在更推荐使用 Iterator,但为什么我们还要学习 Enumeration 呢?答案是:兼容性与理解历史设计。
实际场景举例:
- 你接手一个 10 年前的项目,代码里全是
Enumeration。 - 你看到老版本的 API 文档,
Hashtable.keys()返回的是Enumeration。 - 你需要理解这段代码,才能维护或升级。
所以,学习 Enumeration 不是为了“用”,而是为了“懂”。它像是一本 Java 的“古籍”,帮你理解语言的演变过程。
总结:Java 实例 – 使用 Enumeration 遍历 HashTable
通过本篇内容,我们完成了以下目标:
- 理解了 HashTable 的基本结构与特点。
- 学会了如何创建 HashTable 并插入数据。
- 掌握了使用 Enumeration 遍历键和值的完整流程。
- 对比了 Enumeration 与 Iterator 的差异,理解了其历史背景。
虽然 Enumeration 已不是现代开发的首选,但它在 Java 生态中仍有其不可替代的地位。尤其在处理遗留系统或学习 Java 历史时,它是必修课。
如果你正在学习 Java 的集合框架,不妨动手试试这个 Java 实例 – 使用 Enumeration 遍历 HashTable。写几行代码,跑一遍,你会发现,理解远比记忆重要。
延伸思考:未来是否还会用到 Enumeration?
答案是:在新项目中几乎不会用,但在维护老系统时非常有用。
建议你:
- 在新项目中优先使用
Map.keySet().iterator()或Map.entrySet()配合增强 for 循环。 - 在阅读旧代码时,遇到
Enumeration不要慌,按部就班理解即可。 - 掌握
Iterator的使用,它才是现代 Java 遍历的主流方式。
最后提醒一句:代码不是写给别人看的,而是写给自己用的。清晰的注释、合理的命名、正确的遍历方式,都是专业开发者的素养。