Java 实例 – 使用 Enumeration 遍历 HashTable(手把手讲解)

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 遍历的主流方式。

最后提醒一句:代码不是写给别人看的,而是写给自己用的。清晰的注释、合理的命名、正确的遍历方式,都是专业开发者的素养。