授课语音

Java 中的 HashMapHashtable 的区别

在 Java 中,HashMapHashtable 都是实现了 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 键和值
性能 较高(适用于单线程或外部同步的场景) 较低(同步带来性能开销)
适用场景 单线程或外部同步的场景 多线程环境下,但性能较差

总结来说,HashMapHashtable 的主要区别在于线程安全性和性能。HashMap 适用于单线程或需要自己控制同步的场景,而 Hashtable 则适用于需要内建线程安全的多线程环境,但由于同步机制,它的性能通常低于 HashMap

去1:1私密咨询

系列课程: