Reputation: 2568
As specified in JDK documentation, Hashtable does not allow null keys or values. HashMap allows one null key and any number of null values. Why is this?
Upvotes: 46
Views: 86512
Reputation: 43
Hashtable is a class which came with the first version of java. When it was released Java engineers tried to discourage the use of null keys or maybe did not realize its usefulness. So, they did not allow it in the Hashtable.
The put method to insert key value pair in Hashtable throws NullPointerException if value is null. Since Hashtable is based on hashing mechanism, hash is calculated for keys, which throws NullPointerException if key is null.
Later Java engineers must have realized that having a null key and values has its uses like using them for default cases. So, they provided HashMap class with collection framework in Java 5 with capability of storing null key and values.
The put method to insert key value pair in HashMap checks for null key and stores it at the first location of the internal table array. It isn’t afraid of the null values and does not throw NullPointerException like Hashtable does.
Now, there can be only one null key as keys have to be unique although we can have multiple null values associated with different keys.
Upvotes: 1
Reputation: 1044
Hashtable does not allow null keys but HashMap allows one null key and any number of null values. There is a simple explanation behind that.
put()
method in hashmap does not call hashcode() when null is passed as key and null Key is handled as a special case. HashMap puts null key in bucket 0 and maps null as key to passed value.
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;
}
As seen in the algorithm the put()
method checks if the key is null and call putForNullKey(value) and return. This putForNullKey will create a entry in bucket at 0 index. Index zero is always reserved for null key in the bucket.
On the other hand, in case of hashtable objects used as keys must implement the hashCode method and the equals method. Since null is not an object, it can’t implement these methods.
Upvotes: 0
Reputation: 554
The main reason why Hashtable and ConcurrentHashMap do not allow null keys or values is because of the expectation that they are going to be used in a multi-threaded environment. For a minute, let's assume that null values are allowed. In this case the hashtable's "get" method has ambiguous behavior. It can return null if the key is not found in the map or it can return null if the key is found and its value is null. When a code expects null values, it usually checks if the key is present in the map so that it can know whether the key is not present or the key is present but value is null. Now this code breaks in a multi-threaded environment. Let's take a look at below code:
if (map.contains(key)) {
return map.get(key);
} else {
throw new KeyNotFoundException;
}
In the above code, let's say thread t1 calls the contains method and finds the key and it assumes that key is present and is ready for returning the value whether it is null or not. Now before it calls map.get, another thread t2 removes that key from the map. Now t1 resumes and returns null. However as per the code, the correct answer for t1 is KeyNotFoundException because the key has been removed. But still it returns the null and thus the expected behavior is broken.
Now, for a regular HashMap, it is assumed, that it is going to get called by a single thread, hence there is no possibility of key getting removed in the middle of "contains" check and "get". So HashMap can tolerate null values. However for Hashtable and ConcurrentHashMap, the expectations are clear that multiple threads are going to act on the data. Hence they cannot afford to allow null values and give out incorrect answer. Same logic goes for keys. Now the counter argument can be - the contains and get steps could fail for non null values for Hashtables and ConcurrentHashMaps, because another thread can modify the map/table before the second step gets executed. That is correct, it can happen. But since Hashtables and ConcurrentHashMaps do not allow null keys and values, it is not necessary for them to implement contains and get check in the first place. They can directly get the value because they know that if the get method returns null, the only reason for that is the key is not present and not because the value could be null. The contains and get check is necessary only for HashMaps because they allow the null values and thus need to resolve the ambiguity about whether the key is not found or the value is null.
Upvotes: 21
Reputation: 81
Default Hashtable implementation has null check which thorws null pointer exception. Later on java developers might have realized the importance of null keys(for some default value etc) and values and that why HashMap got introduced.
For HashMap, null check is there for keys if the key is null then that element will be stored in a location where hashcode is not required.
Upvotes: 2
Reputation: 2743
Just as @Jainendra said, HashTable doesn't allow null key for call key.hashCode() in put()
.
But it seems that no one clearly answer why null value isn't allowed.
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;
}
The null check in put doesn't explain why null value is illegal, it just ensure non-null invariant.
The concrete answer for not allow null value is HashTable will call value.equals
when call contains/remove
.
Upvotes: 0
Reputation: 25143
Hashtable is the older class, and its use is generally discouraged. Perhaps they saw the need for a null key, and more importantly - null values, and added it in the HashMap implementation.
HashMap is newer, and has more advanced capabilities, which are basically just an improvement on the Hashtable functionality. When HashMap was created, it was specifically designed to handle null values as keys and handles them as a special case.
Edit
From Hashtable
JavaDoc:
To successfully store and retrieve objects from a Hashtable, the objects used as keys must implement the hashCode method and the equals method.
Since null
isn't an object, you can't call .equals()
or .hashCode()
on it, so the Hashtable
can't compute a hash to use it as a key.
Upvotes: 58
Reputation: 3124
Hash table is very old class , from JDK 1.0
To understand this, first of all we need to understand comments written on this class by author. “This class implements a hashtable, 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 class is implemented on hashing mechanism, that’s mean to store any key-value pair, its required hash code of key object. If key would be null, it will not able to given hash ,it will through null pointer exception and similar case for value it is throwing null if the value is null.
But later on it was realized that null key and value has its own importance that is why one null key and multiple null values are allowed in later implemented classes like HashMap class.
For hash map null keys will allow and there is a null check is there for keys if the key is null then that element will be stored in a zero location in Entry array. null key we can use for some default value..
=> Hashtable methods are synchronised it neveruses object based locking.
HashMap implements by considering it special
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
Java 8 you cannot infer types for hash table.
private Map<String,String> hashtable = new Hashtable<>(); // Not Allowed
private Map<String,String> hashtable = new HashMap<>(); // Allowed
Upvotes: 0
Reputation: 21
so to conclude
Because in HashTable when you put an element it will take into account key and value hash. Basically you will have something like :
public Object put(Object key, Object value){
key.hashCode();
//some code
value.hashCode();
}
HashTable - Does not allow null keys This is because, in put(K key, V value) method, we have key.hashcode() which throws null pointer exception. HashTable - Does not allow null value This is because, in put(K key, V value) method we have if(value==null){throw new NullPointerException
HashMap allows null values as it doesn't have any checks like HashTable, while it allows only one null key. This is done with the help of putForNullKey method, which add the value to the 0th index of the internal Array every time the key is provided as null
Upvotes: 2
Reputation: 8484
The reason is the reason on the accepted answer: Hashtable is old.
However, the use of Hashtable IS NOT discouraged in favor of HashMap in every scenario.
Neither Hashtable nor ConcurrentHashMap support null keys or values. HashMap does.
If you want a drop-in replacement that doesn't require anything else than changing the class and works in every scenario, there is none. The most similar option would be ConcurrentHashMap (which is thread safe but doesn't support locking the whole table):
This class is fully interoperable with Hashtable in programs that rely on its thread safety but not on its synchronization details.
HashMap is a better replacement for single threaded applications or any time synchronization is not a requirement, because of the performance impact synchronization introduces.
Sources:
Upvotes: 2
Reputation: 325
HashTable - Does not allow null keys
This is because, in put(K key, V value) method, we have key.hashcode()
which throws null pointer exception.
HashTable - Does not allow null value
This is because, in put(K key, V value) method we have if(value==null){throw new NullPointerException
HashMap allows null values as it doesn't have any checks like HashTable, while it allows only one null key. This is done with the help of putForNullKey method, which add the value to the 0th index of the internal Array every time the key is provided as null
Upvotes: -3