Table of Contents
Overview
Hashtable and HashMap are common data structures to store key-value data in your Java application. While having similarities, there are some crucial differences you need to know as a Java developer. Let’s discuss the differences between these two data structures in this post.
Hashtable is thread-safe, HashMap is not
Consider the following code using HashMap:
public static void main(String[] args) { //demonstrate the differences between HashMap and HashTable regarding synchronization var myMap = new HashMap<String, Integer>(); myMap.put("key1", 1); //spawn 10 threads to modify the value of "key1" for (int i = 0; i < 10; i++) { new Thread(() -> { myMap.put("key1", myMap.get("key1") + 1); }).start(); } //wait for all threads to finish try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(myMap.get("key1")); }
What would this code print? The answer is no one knows for sure. Since HashMap is not thread-safe, some updates could be lost in the code above.
In fact, running the code multiple times would produce different result. This is one example:
On the other hand, using HashTable would solve the issue:
var myTable = new Hashtable<String, Integer>(); myTable.put("key1", 1); //spawn 100 threads to modify the value of "key1" for (int i = 0; i < 100; i++) { new Thread(() -> { myTable.put("key1", myTable.get("key1") + 1); }).start(); } //wait for all threads to finish try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Result using HashTable: " + myTable.get("key1"));
The result is consistent, for the above code, I always get 101 returned.
But why HashTable is thread-safe and HashMap is not? It’s because if you look into the implementation of HashTable, all methods are synchronized while that’s not the case with HashMap.
For example, this is the method put of HashTable:
public synchronized V put(K key, V value) { //... }
And this is the put method of HashMap
public V put(K key, V value) { //... }
HashMap allows null key & value, HashTable doesn’t
The following code would throw NullPointerException (on line 2, if you comment line 2, the exception is still thrown by line 3)
var myTable = new Hashtable<String, Integer>(); myTable.put(null, 100); mytable.put("Key2", null);
However, if I use HashMap, there is not exception thrown at run time:
var myMap= new HashMap<String, Integer>(); myMap.put("key1", null); myMap.put(null, 100);
Performance
In single-thread applications, HashMap tends to perform better due to the lack of synchronization. However, in multiple thread applications, you need to use synchronization on operations involving HashMap to maintain data integrity, which would put a cost on performance too.
Let’s consider the operation of creating a HashTable and a HashMap with 1_000_000 entries
public static void main(String[] args) { var myMap= new HashMap<String, Integer>(); var myTable = new Hashtable<String, Integer>(); var beforeAddingToHashTable = System.currentTimeMillis(); //add 1000000 entries to HashTable for (int i = 0; i < 1_000_000; i++) { myTable.put("key" + i, i); } var afterAddingToHashTable = System.currentTimeMillis(); var beforeAddingToHashMap = System.currentTimeMillis(); //add 1000000 entries to HashMap for (int i = 0; i < 1_000_000; i++) { myMap.put("key" + i, i); } var afterAddingToHashMap = System.currentTimeMillis(); //compare the result System.out.println("Time to add 1000000 entries to HashTable: " + (afterAddingToHashTable - beforeAddingToHashTable)); System.out.println("Time to add 1000000 entries to HashMap: " + (afterAddingToHashMap - beforeAddingToHashMap)); }
Generally, the time taken to complete the operations on a HashMap is less than that of a HashTable. However, it depends on the condition of your machine and how large is the set.
Iterating over Entries
HashMap: HashMap allows you to iterate over its entries using an enhanced for loop or iterators. It provides methods like keySet(), values(), and entrySet() for this purpose.
Hashtable: Hashtable also offers methods for iteration, similar to HashMap. You can use keys(), values(), and entrySet().
var myMap= new HashMap<String, Integer>(); var myTable = new Hashtable<String, Integer>(); myMap.put("Key1", 100); myMap.put("Key2", 200); myTable.put("Key1", 100); myTable.put("Key2", 200); //Iterate over the map for (var entry : myMap.entrySet()) { System.out.println(entry.getKey() + " " + entry.getValue()); } myMap.values(); //myMap.keys(); //this will not compile //Iterate over the table for (var entry : myTable.entrySet()) { System.out.println(entry.getKey() + " " + entry.getValue()); } myTable.keys(); myTable.values();
Conclusion
There you have it, the core differences between HashTable and HashMap in Java:
- HashTable is thread-safe (by marking methods with synchronized) while HashMap is not
- HashMap is generally faster on single-threaded applications due to the lack of synchronization
- HashTable offers keys() to iterate over keys
- HashMap allows null key and value while HashTable doesn’t
I build softwares that solve problems. I also love writing/documenting things I learn/want to learn.