Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the advantage of null keys mechanism change of HashMap in JDK 1.6 or above version?

Tags:

java

hashmap

I found that some code is changed for null keys in class HashMap in JDK 1.6 or above version compared to the previous JDK version, like 1.5.

In JDK1.5, a static final Object named NULL_KEY is defined: static final Object NULL_KEY = new Object();

Methods, including maskNull, unmaskNull, get and put etc, will use this object.

See

static final Object NULL_KEY = new Object();
static <T> T maskNull(T key) {
    return key == null ? (T)NULL_KEY : key;
}
static <T> T unmaskNull(T key) {
    return (key == NULL_KEY ? null : key);
}

public V get(Object key) {
    Object k = maskNull(key);    
    int hash = hash(k);        
    int i = indexFor(hash, table.length); 
    Entry<K,V> e = table[i];             
    while (true) {                        
        if (e == null)
            return null;
        if (e.hash == hash && eq(k, e.key))
            return e.value;
        e = e.next;
    }
}

public V put(K key, V value) {
    K k = maskNull(key);                             
    int hash = hash(k);                             
    int i = indexFor(hash, table.length);             
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        if (e.hash == hash && eq(k, e.key)) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);              
            return oldValue;
        }
    }

    modCount++;                                       
    addEntry(hash, k, value, i);                      
    return null;
}

However, such Object (NULL_KEY) is not used in JDK 1.6 or above version.

Instead, two new methods named getForNullKey() and putForNullKey(value) is added, which are applied in get and put method as well.

See the source code as follows:

 public V get(Object key) {
    if (key == null)
        return getForNullKey();
    Entry<K,V> entry = getEntry(key);

    return null == entry ? null : entry.getValue();
}

 private V getForNullKey() {
    for (Entry<K,V> e = table[0]; e != null; e = e.next) {
        if (e.key == null)
            return e.value;
    }
    return null;
 }

public V put(K key, V value) {
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key);
    int i = indexFor(hash, table.length);
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }

    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

/**
 * Offloaded version of put for null keys
 */
private V putForNullKey(V value) {
    for (Entry<K,V> e = table[0]; e != null; e = e.next) {
        if (e.key == null) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }
    modCount++;
    addEntry(0, null, value, 0);
    return null;
}

Change always has its reason for changing, such as improving the performance etc. Please help me out with the following 2 question

Q#1 ==> Why this change is made, is there some scenario that the null keys of HashMap implemented in JDK 1.5 encouneters issue ?

Q#2 ==> What is the advantage of null keys mechanism change of HashMap in JDK 1.6 or above version?

like image 737
MouseLearnJava Avatar asked Nov 26 '13 13:11

MouseLearnJava


People also ask

Can we have null as key for map in Java?

Indeed, if a Java Map implementation allows for null values, then it is possible for the Map to return its value for the given key, but that value might be a null. Often this doesn't matter, but if it does, one can use Map. containsKey() to determine if the Map entry has a key entry.

What does HashMap get return if key not found?

HashMap. get() method of HashMap class is used to retrieve or fetch the value mapped by a particular key mentioned in the parameter. It returns NULL when the map contains no such mapping for the key.

Can a key be null in a map?

Yes, null is always a valid map key for any type of map key (including primitives, sobjects, and user-defined objects).

Does a HashMap get return a reference?

It returns a reference.


1 Answers

Documentation for private V getForNullKey() says

Offloaded version of get() to look up null keys. Null keys map to index 0. This null case is split out into separate methods for the sake of performance in the two most commonly used operations (get and put), but incorporated with conditionals in others.

like image 148
auselen Avatar answered Oct 30 '22 02:10

auselen