What are the differences between a HashMap and a Hashtable in Java?
Which is more efficient for non-threaded applications?
Hashtable
is synchronized, whereas HashMap
isn't. That makes Hashtable
slower than Hashmap
.
For single thread applications, use HashMap
since they are otherwise the same in terms of functionality.
HashTable is synchronized, if you are using it in a single thread you can use HashMap, which is an unsynchronized version. Unsynchronized objects are often a little more performant. By the way if multiple threads access a HashMap concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. Youn can wrap a unsynchronized map in a synchronized one using :
Map m = Collections.synchronizedMap(new HashMap(...));
HashTable can only contain non-null object as a key or as a value. HashMap can contain one null key and null values.
The iterators returned by Map are fail-fast, if the map is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException
. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future. Whereas the Enumerations returned by Hashtable's keys and elements methods are not fail-fast.
HashTable and HashMap are member of the Java Collections Framework (since Java 2 platform v1.2, HashTable was retrofitted to implement the Map interface).
HashTable is considered legacy code, the documentation advise to use ConcurrentHashMap in place of Hashtable if a thread-safe highly-concurrent implementation is desired.
HashMap doesn't guarantee the order in which elements are returned. For HashTable I guess it's the same but I'm not entirely sure, I don't find ressource that clearly state that.
HashMap and HashTable
1) Hashtable and Hashmap implement the java.util.Map interface 2) Both Hashmap and Hashtable is the hash based collection. and working on hashing. so these are similarity of HashMap and HashTable.
1) First difference is HashMap is not thread safe While HashTable is ThreadSafe
2) HashMap is performance wise better because it is not thread safe. while Hashtable performance wise is not better because it is thread safe. so multiple thread can not access Hashtable at the same time.
Old and classic topic, just want to add this helpful blog that explains this:
http://blog.manishchhabra.com/2012/08/the-5-main-differences-betwen-hashmap-and-hashtable/
Blog by Manish Chhabra
The 5 main differences betwen HashMap and Hashtable
HashMap and Hashtable both implement java.util.Map interface but there are some differences that Java developers must understand to write more efficient code. As of the Java 2 platform v1.2, Hashtable class was retrofitted to implement the Map interface, making it a member of the Java Collections Framework.
One of the major differences between HashMap and Hashtable is that HashMap is non-synchronized whereas Hashtable is synchronized, which means Hashtable is thread-safe and can be shared between multiple threads but HashMap cannot be shared between multiple threads without proper synchronization. Java 5 introduced ConcurrentHashMap which is an alternative of Hashtable and provides better scalability than Hashtable in Java.Synchronized means only one thread can modify a hash table at one point of time. Basically, it means that any thread before performing an update on a hashtable will have to acquire a lock on the object while others will wait for lock to be released.
The HashMap class is roughly equivalent to Hashtable, except that it permits nulls. (HashMap allows null values as key and value whereas Hashtable doesn’t allow nulls).
The third significant difference between HashMap vs Hashtable is that Iterator in the HashMap is a fail-fast iterator while the enumerator for the Hashtable is not and throw ConcurrentModificationException if any other Thread modifies the map structurally by adding or removing any element except Iterator’s own remove() method. But this is not a guaranteed behavior and will be done by JVM on best effort. This is also an important difference between Enumeration and Iterator in Java.
One more notable difference between Hashtable and HashMap is that because of thread-safety and synchronization Hashtable is much slower than HashMap if used in Single threaded environment. So if you don’t need synchronization and HashMap is only used by one thread, it out perform Hashtable in Java.
HashMap does not guarantee that the order of the map will remain constant over time.
Note that HashMap can be synchronized by
Map m = Collections.synchronizedMap(hashMap);
In Summary there are significant differences between Hashtable and HashMap in Java e.g. thread-safety and speed and based upon that only use Hashtable if you absolutely need thread-safety, if you are running Java 5 consider using ConcurrentHashMap in Java.
Note, that a lot of the answers state that Hashtable is synchronised. In practice this buys you very little. The synchronization is on the accessor / mutator methods will stop two threads adding or removing from the map concurrently, but in the real world you will often need additional synchronisation.
A very common idiom is to "check then put" — i.e. look for an entry in the Map
, and add it if it does not already exist. This is not in any way an atomic operation whether you use Hashtable
or HashMap
.
An equivalently synchronised HashMap
can be obtained by:
Collections.synchronizedMap(myMap);
But to correctly implement this logic you need additional synchronisation of the form:
synchronized(myMap) {
if (!myMap.containsKey("tomato"))
myMap.put("tomato", "red");
}
Even iterating over a Hashtable
's entries (or a HashMap
obtained by Collections.synchronizedMap
) is not thread safe unless you also guard the Map
from being modified through additional synchronization.
Implementations of the ConcurrentMap interface (for example ConcurrentHashMap) solve some of this by including thread safe check-then-act semantics such as:
ConcurrentMap.putIfAbsent(key, value);
A Collection — sometimes called a container — is simply an object that groups multiple elements into a single unit. Collection
s are used to store, retrieve, manipulate, and communicate aggregate data. A collections framework W is a unified architecture for representing and manipulating collections.
The HashMap
JDK1.2 and Hashtable JDK1.0, both are used to represent a group of objects that are represented in <Key, Value>
pair. Each <Key, Value>
pair is called Entry
object. The collection of Entries is referred by the object of HashMap
and Hashtable
. Keys in a collection must be unique or distinctive. [as they are used to retrieve a mapped value a particular key. values in a collection can be duplicated.]
« Superclass, Legacy and Collection Framework member
Hashtable is a legacy class introduced in JDK1.0
, which is a subclass of Dictionary class. From JDK1.2
Hashtable is re-engineered to implement the Map interface to make a member of collection framework. HashMap is a member of Java Collection Framework right from the beginning of its introduction in JDK1.2
. HashMap is the subclass of the AbstractMap class.
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable { ... }
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { ... }
« Initial capacity and Load factor
The capacity is the number of buckets in the hash table, and the initial capacity is simply the capacity at the time the hash table is created. Note that the hash table is open: in the case of a "hash
collision", a single bucket stores multiple entries, which must be searched sequentially. The load factor is a measure of how full the hash table is allowed to get before its capacity is automatically increased.
HashMap constructs an empty hash table with the default initial capacity (16) and the default load factor (0.75). Where as Hashtable constructs empty hashtable with a default initial capacity (11) and load factor/fill ratio (0.75).
« Structural modification in case of hash collision
HashMap
, Hashtable
in case of hash collisions they store the map entries in linked lists. From Java8 for HashMap
if hash bucket grows beyond a certain threshold, that bucket will switch from linked list of entries to a balanced tree. which improve worst-case performance from O(n) to O(log n). While converting the list to binary tree, hashcode is used as a branching variable. If there are two different hashcodes in the same bucket, one is considered bigger and goes to the right of the tree and other one to the left. But when both the hashcodes are equal, HashMap
assumes that the keys are comparable, and compares the key to determine the direction so that some order can be maintained. It is a good practice to make the keys of HashMap
comparable. On adding entries if bucket size reaches TREEIFY_THRESHOLD = 8
convert linked list of entries to a balanced tree, on removing entries less than TREEIFY_THRESHOLD
and at most UNTREEIFY_THRESHOLD = 6
will reconvert balanced tree to linked list of entries. Java 8 SRC, stackpost
« Collection-view iteration, Fail-Fast and Fail-Safe
+--------------------+-----------+-------------+
| | Iterator | Enumeration |
+--------------------+-----------+-------------+
| Hashtable | fail-fast | safe |
+--------------------+-----------+-------------+
| HashMap | fail-fast | fail-fast |
+--------------------+-----------+-------------+
| ConcurrentHashMap | safe | safe |
+--------------------+-----------+-------------+
Iterator is a fail-fast in nature. i.e it throws ConcurrentModificationException if a collection is modified while iterating other than it’s own remove() method. Where as Enumeration is fail-safe in nature. It doesn’t throw any exceptions if a collection is modified while iterating.
According to Java API Docs, Iterator is always preferred over the Enumeration.
NOTE: The functionality of Enumeration interface is duplicated by the Iterator interface. In addition, Iterator adds an optional remove operation, and has shorter method names. New implementations should consider using Iterator in preference to Enumeration.
In Java 5 introduced ConcurrentMap Interface: ConcurrentHashMap
- a highly concurrent, high-performance ConcurrentMap
implementation backed by a hash table. This implementation never blocks when performing retrievals and allows the client to select the concurrency level for updates. It is intended as a drop-in replacement for Hashtable
: in addition to implementing ConcurrentMap
, it supports all of the "legacy" methods peculiar to Hashtable
.
Each HashMapEntry
s value is volatile thereby ensuring fine grain consistency for contended modifications and subsequent reads; each read reflects the most recently completed update
Iterators and Enumerations are Fail Safe - reflecting the state at some point since the creation of iterator/enumeration; this allows for simultaneous reads and modifications at the cost of reduced consistency. They do not throw ConcurrentModificationException. However, iterators are designed to be used by only one thread at a time.
Like Hashtable
but unlike HashMap
, this class does not allow null to be used as a key or value.
public static void main(String[] args) {
//HashMap<String, Integer> hash = new HashMap<String, Integer>();
Hashtable<String, Integer> hash = new Hashtable<String, Integer>();
//ConcurrentHashMap<String, Integer> hash = new ConcurrentHashMap<>();
new Thread() {
@Override public void run() {
try {
for (int i = 10; i < 20; i++) {
sleepThread(1);
System.out.println("T1 :- Key"+i);
hash.put("Key"+i, i);
}
System.out.println( System.identityHashCode( hash ) );
} catch ( Exception e ) {
e.printStackTrace();
}
}
}.start();
new Thread() {
@Override public void run() {
try {
sleepThread(5);
// ConcurrentHashMap traverse using Iterator, Enumeration is Fail-Safe.
// Hashtable traverse using Enumeration is Fail-Safe, Iterator is Fail-Fast.
for (Enumeration<String> e = hash.keys(); e.hasMoreElements(); ) {
sleepThread(1);
System.out.println("T2 : "+ e.nextElement());
}
// HashMap traverse using Iterator, Enumeration is Fail-Fast.
/*
for (Iterator< Entry<String, Integer> > it = hash.entrySet().iterator(); it.hasNext(); ) {
sleepThread(1);
System.out.println("T2 : "+ it.next());
// ConcurrentModificationException at java.util.Hashtable$Enumerator.next
}
*/
/*
Set< Entry<String, Integer> > entrySet = hash.entrySet();
Iterator< Entry<String, Integer> > it = entrySet.iterator();
Enumeration<Entry<String, Integer>> entryEnumeration = Collections.enumeration( entrySet );
while( entryEnumeration.hasMoreElements() ) {
sleepThread(1);
Entry<String, Integer> nextElement = entryEnumeration.nextElement();
System.out.println("T2 : "+ nextElement.getKey() +" : "+ nextElement.getValue() );
//java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode
// at java.util.HashMap$EntryIterator.next
// at java.util.Collections$3.nextElement
}
*/
} catch ( Exception e ) {
e.printStackTrace();
}
}
}.start();
Map<String, String> unmodifiableMap = Collections.unmodifiableMap( map );
try {
unmodifiableMap.put("key4", "unmodifiableMap");
} catch (java.lang.UnsupportedOperationException e) {
System.err.println("UnsupportedOperationException : "+ e.getMessage() );
}
}
static void sleepThread( int sec ) {
try {
Thread.sleep( 1000 * sec );
} catch (InterruptedException e) {
e.printStackTrace();
}
}
« Null Keys And Null Values
HashMap
allows maximum one null key and any number of null values. Where as Hashtable
doesn’t allow even a single null key and null value, if the key or value null is then it throws NullPointerException. Example
« Synchronized, Thread Safe
Hashtable
is internally synchronized. Therefore, it is very much safe to use Hashtable
in multi threaded applications. Where as HashMap
is not internally synchronized. Therefore, it is not safe to use HashMap
in multi threaded applications without external synchronization. You can externally synchronize HashMap
using Collections.synchronizedMap()
method.
« Performance
As Hashtable
is internally synchronized, this makes Hashtable
slightly slower than the HashMap
.
@See