杰瑞科技汇

java hashtable 遍历

Hashtable 是一个遗留类(Legacy Class),存在于 Java 的 java.util 包中,它和 HashMap 非常相似,都是键值对(Key-Value)集合,但有一个关键区别:Hashtable 是线程安全的(synchronized),而 HashMap 不是,这意味着在多线程环境下,可以直接使用 Hashtable 而不需要额外的同步措施。

java hashtable 遍历-图1
(图片来源网络,侵删)

由于 Hashtable 实现了 Map 接口,因此遍历它的方法与遍历 HashMap 或其他 Map 实现类的方法基本相同,下面我们介绍几种最常用和最推荐的遍历方式。


准备工作:创建一个 Hashtable 示例

在开始遍历之前,我们先创建一个 Hashtable 实例并填充一些数据,以便后续的代码演示。

import java.util.Hashtable;
import java.util.Map;
public class HashtableTraversalExample {
    public static void main(String[] args) {
        // 1. 创建一个 Hashtable 实例
        // 注意:Hashtable 的构造函数可以指定初始容量和加载因子
        Hashtable<String, Integer> scores = new Hashtable<>();
        // 2. 向 Hashtable 中添加元素
        scores.put("Alice", 95);
        scores.put("Bob", 88);
        scores.put("Charlie", 76);
        scores.put("David", 92);
        System.out.println("原始的 Hashtable: " + scores);
    }
}

使用 entrySet() 和 for-each 循环(推荐)

这是最常用、最推荐的方法,它通过 Map.Entry 对象来同时获取键和值,代码简洁高效。

原理: Map.entrySet() 方法返回一个 Set 集合,该集合包含了 Map 中所有的键值对,每个键值对都被封装在一个 Map.Entry 对象中,我们可以直接遍历这个 Set

java hashtable 遍历-图2
(图片来源网络,侵删)

代码示例:

System.out.println("\n--- 方法一:使用 entrySet() 和 for-each 循环 ---");
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
    // entry.getKey() 获取键
    // entry.getValue() 获取值
    String name = entry.getKey();
    int score = entry.getValue();
    System.out.println("姓名: " + name + ", 分数: " + score);
}

优点:

  • 代码简洁:使用 for-each 循环,代码可读性高。
  • 性能高:这是遍历 Map 最高效的方式之一,因为它直接操作内部的 Entry 对象,避免了多次查找。

使用 keySet() 和 for-each 循环

如果你只需要遍历所有的键,或者需要先获取键再通过键去获取值,可以使用 keySet()

原理: Map.keySet() 方法返回一个包含 Map 中所有键的 Set 集合,遍历这个键集合,然后通过 Map.get(key) 方法来获取对应的值。

java hashtable 遍历-图3
(图片来源网络,侵删)

代码示例:

System.out.println("\n--- 方法二:使用 keySet() 和 for-each 循环 ---");
for (String name : scores.keySet()) {
    // scores.get(name) 通过键获取值
    int score = scores.get(name);
    System.out.println("姓名: " + name + ", 分数: " + score);
}

优点:

  • 当你只需要键时,非常直接。
  • 代码同样简洁。

缺点:

  • 性能稍差:对于 Map 中的每一个键,scores.get(name) 方法都需要执行一次查找操作。Map 很大,这会比 entrySet() 方法慢。

使用 values() 和 for-each 循环

如果你只关心值,而不关心键,可以使用 values() 方法。

原理: Map.values() 方法返回一个包含 Map 中所有值的 Collection 集合,你可以直接遍历这个值的集合。

代码示例:

System.out.println("\n--- 方法三:使用 values() 和 for-each 循环 ---");
for (Integer score : scores.values()) {
    System.out.println("分数: " + score);
}

优点:

  • 当你只需要值时,非常方便。

缺点:

  • 无法在遍历过程中直接获取到对应的键。

使用迭代器(Iterator)

虽然 for-each 循环是主流,但在某些情况下(例如需要在遍历时删除元素),使用传统的 Iterator 是更安全的选择。Hashtable 的所有集合视图(entrySet(), keySet(), values())都返回的集合都是“快速失败”(fail-fast)的,这意味着如果在迭代过程中,除了 iterator.remove() 之外的任何方式修改了 Map,都会抛出 ConcurrentModificationException 异常。

代码示例:

System.out.println("\n--- 方法四:使用 Iterator ---");
// 1. 使用 entrySet() 获取迭代器
System.out.println("--- 遍历 entrySet ---");
Iterator<Map.Entry<String, Integer>> entryIterator = scores.entrySet().iterator();
while (entryIterator.hasNext()) {
    Map.Entry<String, Integer> entry = entryIterator.next();
    System.out.println("姓名: " + entry.getKey() + ", 分数: " + entry.getValue());
}
// 2. 使用 keySet() 获取迭代器
System.out.println("\n--- 遍历 keySet ---");
Iterator<String> keyIterator = scores.keySet().iterator();
while (keyIterator.hasNext()) {
    String name = keyIterator.next();
    System.out.println("姓名: " + name + ", 分数: " + scores.get(name));
}

关于在遍历时删除元素: 如果你想删除一个元素,必须使用迭代器的 remove() 方法。

System.out.println("\n--- 使用 Iterator 安全删除元素 ---");
Iterator<Map.Entry<String, Integer> > iterator = scores.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry<String, Integer> entry = iterator.next();
    // 假设我们要删除分数低于 80 的学生
    if (entry.getValue() < 80) {
        iterator.remove(); // 正确的删除方式
    }
}
System.out.println("删除后的 Hashtable: " + scores);

使用 Java 8 的 forEach 和 Lambda 表达式

如果你使用的是 Java 8 或更高版本,可以利用 Lambda 表达式和 Map 接口的 forEach 方法,以函数式的方式遍历 Map,代码非常优雅。

代码示例:

System.out.println("\n--- 方法五:使用 Java 8 forEach ---");
scores.forEach((name, score) -> {
    System.out.println("姓名: " + name + ", 分数: " + score);
});

优点:

  • 极其简洁:一行代码即可完成遍历。
  • 函数式编程风格:代码更具表现力。

总结与对比

方法 适用场景 优点 缺点
entrySet() + for-each 需要同时访问键和值 性能最高,代码简洁 -
keySet() + for-each 只需要键,或者需要根据键获取值 代码简洁 性能稍差(多次查找)
values() + for-each 只需要值 代码简洁 无法获取键
Iterator 需要在遍历过程中安全地删除元素 安全,支持删除操作 代码比 for-each 稍显冗长
forEach (Java 8+) 现代 Java 开发,追求简洁优雅 代码最简洁,函数式风格 需要 Java 8+ 环境

最佳实践建议:

  1. 如果你需要同时访问键和值强烈推荐使用 entrySet() 和 for-each 循环,这是性能和可读性之间的最佳平衡点。
  2. 如果你使用的是 Java 8 或更高版本,并且喜欢函数式编程风格,map.forEach() 是一个非常棒的选择。
  3. 如果你需要在遍历过程中删除元素,请务必使用 Iteratorremove() 方法。
分享:
扫描分享到社交APP
上一篇
下一篇