HashMap 与 HashTable 的区别

HashMap 与 HashTable 的区别

1. 数据结构方面

HashTable 使用的是数组 + 链表

HashMap 1.7 之前与HashTable 一致, 1.7 之后引入红黑树

2. 初始容量和扩容

HashTable 初始容量是11 扩容 2n+1

HashMap 初始容量16 扩容2n

3. 是否允许null作为key

HashMap 允许, HashTable 不允许

4. 线程安全

HashTable 为线程安全,因为HashTable 在put (大多数)方法前加入了synchronized

    public synchronized V put(K key, V value) {
        // Make sure the value is not null
        if (value == null) {
            throw new NullPointerException();
        }

        // Makes sure the key is not already in the hashtable.
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        @SuppressWarnings("unchecked")
        Entry<K,V> entry = (Entry<K,V>)tab[index];
        for(; entry != null ; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }

        addEntry(hash, key, value, index);
        return null;
    }

为什么HashTable 不允许null值作为key

HashMap 源码

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

HashTable 源码

    public synchronized V put(K key, V value) {
        // Make sure the value is not null
        if (value == null) {
            throw new NullPointerException();
        }

        // Makes sure the key is not already in the hashtable.
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();

作者思考

This class implements a hash table, which maps keys to values. Any
* non-null object can be used as a key or as a value.


*
* To successfully store and retrieve objects from a hashtable, the
* objects used as keys must implement the hashCode
* method and the equals method.

Hashtable 设计较早,不允许 null

  • HashtableJDK 1.0 时代的类,最早的设计时考虑的是严格的安全性,因此 put(key, value)keyvalue 都不允许为 null,以防止 NullPointerException
  • 代码中,它的 put 方法直接调用 Objects.requireNonNull(key),不允许 null

HashMap 设计更灵活,允许 null

  • HashMapJDK 1.2 才引入的,设计上更灵活,允许 null 作为 key 和 value。
  • HashMap 允许 null key,是因为 null key 在很多场景下是有意义的,比如:
    • map.get(null) 可以作为一种默认值的查找机制。
    • 在 JSON、数据库等数据格式中,null 也是合法的 key。
  • HashMap 内部对 null key 进行特殊处理:
    • null key 总是存储在数组的 第一个 bucket 里,而非通过 hashCode() 计算索引

2. 为什么 HashMapHashtable 的设计不同?

(1) 线程安全性

  • Hashtable 是同步的(synchronized),防止 null 作为 key 或 value 能减少 NullPointerException,避免不必要的 synchronized 代码块出现问题。
  • HashMap 不是线程安全的,所以允许 null 更符合非同步环境的需求。

(2) 设计原则

  • HashMap 设计时追求 性能和灵活性,避免 null 反而会降低使用的灵活性。
  • Hashtable 作为老 API,设计上偏向 严格的约束,更符合早期 Java 的安全性要求。
posted @ 2025-04-01 21:02  aidan_8  阅读(35)  评论(0)    收藏  举报