Learnitweb

Why HashMap Allows One Null Key While Hashtable Doesn’t?

1. Background

Hashtable

  • Introduced in Java 1.0 (before collections framework).
  • It’s synchronized, which means it’s thread-safe.
  • Designed at a time when nulls were considered programming errors (especially in multithreaded contexts).
  • Therefore, it doesn’t allow null keys or values.

HashMap

  • Introduced later in Java 1.2 as part of the Collections Framework.
  • It’s not synchronized (faster, but not thread-safe).
  • Designed to be more flexible, including allowing one null key and multiple null values.

2. Internal Working Difference

Let’s look at how key lookup works in both:

In HashMap

  1. When you insert a key-value pair, HashMap calls: int hash = (key == null) ? 0 : key.hashCode(); So, if the key is null, it assigns a default hash value (0).
  2. This means all null keys go into bucket index 0.
  3. When retrieving a null key, HashMap simply checks: if (key == null) return getForNullKey(); and fetches the value stored in bucket 0.

In Hashtable

  1. It directly calls key.hashCode() without a null check. int hash = key.hashCode(); // Throws NullPointerException if key is null
  2. So, inserting a null key will immediately throw NullPointerException.
  3. This behavior is intentional to prevent confusion or concurrency bugs in older thread-safe code.

3. Design Rationale

AspectHashMapHashtable
Introduced inJava 1.2 (Collections Framework)Java 1.0 (Legacy class)
SynchronizationNon-synchronizedSynchronized
Null keysAllowed (one null key)Not allowed
Null valuesAllowedNot allowed
PerformanceFaster (no synchronization overhead)Slower (synchronized methods)
Thread safetyNot thread-safeThread-safe (synchronized)

Why HashMap allows one null key:

  • Flexibility: Collections Framework promotes ease of use.
  • Consistency: Many data structures (like lists, sets) allow null elements.
  • Utility: Useful for representing a “default” or “missing” key explicitly.
  • Controlled behavior: Internally handled via bucket index 0.

Why Hashtable disallows null keys:

  • Historical reason: Designed before Java Collections existed.
  • Thread-safety concern: In synchronized code, a null check might race with another thread inserting/removing entries, leading to subtle bugs.
  • Error prevention: Null keys often indicate logic errors in legacy systems.

4. Code Example

HashMap Example (allows null)

import java.util.HashMap;

public class HashMapNullExample {
    public static void main(String[] args) {
        HashMap<String, String> map = new HashMap<>();
        map.put(null, "First Null Key");
        map.put("A", "Value A");
        map.put(null, "Replaced Null Key"); // Replaces previous null key

        System.out.println(map.get(null)); // Output: Replaced Null Key
    }
}

Hashtable Example (throws exception)

import java.util.Hashtable;

public class HashtableNullExample {
    public static void main(String[] args) {
        Hashtable<String, String> table = new Hashtable<>();
        table.put(null, "First Null Key"); // Throws NullPointerException
    }
}

5. Summary

FeatureHashMapHashtable
Null KeyOne allowed (stored in bucket 0)Not allowed
Null ValueAllowedNot allowed
Thread-safeNoYes
Introduced InJava 1.2Java 1.0
Internal CheckHandles null safelyCalls key.hashCode() directly

6. Key Takeaways

  1. HashMap handles null keys by assigning them a fixed hash (0) and placing them in a special bucket.
  2. Hashtable was designed for early multi-threaded use, where null could cause unpredictable synchronization issues.
  3. Modern Java prefers ConcurrentHashMap instead of Hashtable for thread-safe operations.
  4. ConcurrentHashMap also disallows null keys and values to avoid ambiguity in concurrent lookups.