1. Overview
In this short tutorial, we are going to focus on the core differences between the Hashtable and the HashMap.
2. Hashtable and HashMap in Java
Hashtable and HashMap are quite similar – both are collections that implement the Map interface.
Also, the put(), get(), remove(), and containsKey() methods provide constant-time performance O(1). Internally, these methods work based on a general concept of hashing using buckets for storing data.
Neither class maintains the insertion order of the elements. In other words, the first item added may not be the first item when we iterate over the values.
But they also have some differences that make one better than another in some situations. Let’s look closer at these differences.
3. Differences Between Hashtable and HashMap
3.1. Synchronization
Firstly, Hashtable is thread-safe and can be shared between multiple threads in the application.
On the other hand, HashMap is not synchronized and can’t be accessed by multiple threads without additional synchronization code. We can use Collections.synchronizedMap() to make a thread-safe version of a HashMap. We can also just create custom lock code or make the code thread-safe by using the synchronized keyword.
HashMap is not synchronized, therefore it’s faster and uses less memory than Hashtable. Generally, unsynchronized objects are faster than synchronized ones in a single threaded application.
3.2. Null Values
Another difference is null handling. HashMap allows adding one Entry with null as key as well as many entries with null as value. In contrast, Hashtable doesn’t allow null at all. Let’s see an example of null and HashMap:
HashMap<String, String> map = new HashMap<String, String>(); map.put(null, "value"); map.put("key1", null); map.put("key2", null);
This will result in:
assertEquals(3, map.size());
Next, let’s see how Hashtable is different:
Hashtable<String, String> table = new Hashtable<String, String>(); table.put("key", null);
This results in a NullPointerException. Adding an object with null as a key also results in a NullPointerException:
table.put(null, "value");
3.3. Iteration Over Elements
HashMap uses Iterator to iterate over values, whereas Hashtable has Enumerator for the same. The Iterator is a successor of Enumerator that eliminates its few drawbacks. For example, Iterator has a remove() method to remove elements from underlying collections.
The Iterator is a fail-fast iterator. In other words, it throws a ConcurrentModificationException when the underlying collection is modified while iterating. Let’s see the example of fail-fast:
HashMap<String, String> map = new HashMap<String, String>(); map.put("key1", "value1"); map.put("key2", "value2"); Iterator<String> iterator = map.keySet().iterator(); while(iterator.hasNext()){ iterator.next(); map.put("key4", "value4"); }
This throws a ConcurrentModificationException exception because we are calling put() while iterating over the collection.
4. When to Choose HashMap Over Hashtable
We should use HashMap for an unsynchronized or single threaded application.
It is worth mentioning that since JDK 1.8, Hashtable has been deprecated. However, ConcurrentHashMap is a great Hashtable replacement. We should consider ConcurrentHashMap to use in applications with multiple threads.
5. Conclusion
In this article, we illustrated differences between HashMap and Hashtable and what to keep in mind when we need to choose one.
As usual, the implementation of all these examples and code snippets are over on Github.