HashMap vs. Hashtable

A hash table is a data structure used to implement an associative array, a structure that can map keys to values. A hash table uses a hash function to compute an index into an array of buckets or slots, from which the correct value can be found.

A hash table is made up of two parts

  • an array (the actual table where the data to be searched is stored)
  • a mapping function, known as a hash function

The hash function is a mapping from the input space to the integer space that defines the indices of the array.
The Primary idea behind a hash table is to establish a mapping between the set of all possible keys and positions in the array using a hash function. A hash function accepts a key and returns its hash value, Key vary in type but hash codings are always integer.

When a hash function can guarantee that no 2 keys will generate the same hash value, the resulting hash table is called directly addressed. Thus is ideal, but direct addressing is rarely possible in practice.
Typically, the number of entries in a hash table is small relative to the universe of possible keys. Consequently, most hash functions map some keys to the same position in the table. When two keys map to the same position, they collide. A good hash function minimizes collisions, but we must still be prepared to deal with them.

There are many algorithms for dealing with collisions, such as linear probing and separate chaining. While each of the methods has its advantages, we will only discuss separate chaining here.
Separate chaining requires a slight modification to the data structure. Instead of storing the data elements right into the array, they are stored in linked lists. Each slot in the array then points to one of these linked lists. When an element hashes to a value, it is added to the linked list at that index in the array. Because a linked list has no limit on length, collisions are no longer a problem. If more than one element hashes to the same value, then both are stored in that linked list.

ITCuties - Java HashMap HashTable - linear probing and separate chaining

ITCuties – Java HashMap HashTable – linear probing and separate chaining

HashTable

Class Hashtable<K,V>
K – the type of keys maintained by this map
V – the type of mapped values

  • Just as Vector is a synchronized counterpart to the sleeker, more modern ArrayList, Hashtable is the synchronized counterpart to HashMap.
  • Remember that you don’t synchronize a class, so when we say that Vector and Hashtable are synchronized, we just mean that the key methods of the class are synchronized
  • HashTable doesn’t let you have anything that’s null
  • Enumerator in HashTable is not fail fast

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.

To successfully store and retrieve objects from a hashtable, the objects used as keys must implement the hashCode method and the equals method.
An instance of Hashtable has two parameters that affect its performance:

  1. initial capacity,
  2. 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. The initial capacity and load factor parameters are merely hints to the implementation. The exact details as to when and whether the rehash method is invoked are implementation-dependent.


Check out our other tutorial hashCode and equals – why implementing them is important?.


Generally, the default load factor (.75) offers a good tradeoff between time and space costs. Higher values decrease the space overhead but increase the time cost to look up an entry.
The initial capacity controls a tradeoff between wasted space and the need for rehash operations, which are time-consuming. No rehash operations will ever occur if the initial capacity is greater than the maximum number of entries the Hashtable will contain divided by its load factor. However, setting the initial capacity too high can waste space.

The iterators returned by the iterator method of the collections returned by all of this class’s “collection view methods” are fail-fast: if the Hashtable 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. The Enumerations returned by Hashtable‘s keys and elements methods are not fail-fast.

Hashtable is not part of the Java Collections Framework – it just provides a similar API.

HashTableDemo.java : Demonstrate how to use Hashtable, and its methods.

package com.javalatte.itcuties.hashtable;

import java.util.Collection;
import java.util.Hashtable;
import java.util.Set;

public class HashTableDemo {

    public static void main(String[] JavaLatte) {
        //Constructs a new, empty hashtable with a default initial capacity (11)
        //and load factor (0.75).
        Hashtable<String, Integer> numberList = new Hashtable<String, Integer>();
        numberList.put("one", 1);
        numberList.put("two", 2);
        numberList.put("three", 3);
        numberList.put("four", 4);
        numberList.put("five", 5);
        numberList.put("six", 6);
        System.out.println(numberList);

        //HashTable doesn't let you have anything that's null
        //it give you java.lang.NullPointerException, uncomment the following two lines
        //to check NullPointerException
        /*
         numberList.put("seven", null); 
         numberList.put(null, 7);
         */
        //HashTable methods usage
        if (numberList.contains("seven")) {
            System.out.println("seven is present in hashtable");
        } else {
            System.out.println("seven is not present in hashtable");
        }

        //Retrive keys in a set
        Set<String> keySet = numberList.keySet();
        System.out.println(keySet);

        System.out.println("size : " + numberList.size());

        //Returns a Collection view of the values contained in this map.
        Collection<Integer> collection = numberList.values();
        System.out.println(collection);

        //clear(): Clears this hashtable so that it contains no keys.
        numberList.clear();
        System.out.println("size after clear: " + numberList.size());
    }
}

HashTableIteratorDemo.java : Demonstrate the use of Iterator in Hashtable.

package com.javalatte.itcuties.hashtable;

import java.util.Enumeration;
import java.util.Hashtable;

public class HashTableIteratorDemo {

    public static void main(String[] JavaLatte) {
        //Constructs a new, empty hashtable with the specified initial capacity
        //and default load factor (0.75).
        Hashtable<String, Integer> numberList = new Hashtable<String, Integer>(10);
        numberList.put("one", 1);
        numberList.put("two", 2);
        numberList.put("three", 3);
        numberList.put("four", 4);
        numberList.put("five", 5);
        numberList.put("six", 6);
        System.out.println(numberList);

        //elements() : Returns an enumeration of the values in this hashtable
        Enumeration<Integer> valueEnumeation = numberList.elements();

        //This show Enumeration is not fail-fast as it allow to remove
        //elements after enumeration is created
        numberList.remove("six");
        while (valueEnumeation.hasMoreElements()) {
            System.out.println("value : " + valueEnumeation.nextElement());
        }

    }
}

HashMap

Class HashMap<K,V>
K – the type of keys maintained by this map
V – the type of mapped values

HashMap based implementation of the Map interface. This implementation provides all of the optional map operations, and permits null values and the null key. This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.

  • The HashMap gives you an unsorted, unordered Map, it does not guarantee that the order will remain constant over time.
  • HashMap allows one null key and multiple null values in a collection.
  • When you need a Map and you don’t care about the order (when you iterate through it), then HashMap is the way to go; the other maps add a little more overhead.
  • The more efficient your hashCode() implementation, the better access performance you’ll get.
  • This implementation provides constant-time performance for the basic operations (get and put), assuming the hash function disperses the elements properly among the buckets.

An instance of HashMap has two parameters that affect its performance:

  • initial capacity
  • 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.
The load factor is a measure of how full the hash table is allowed to get before its capacity is automatically increased.
When the number of entries in the hash table exceeds the product of the load factor and the current capacity, the hash table is rehashed (that is, internal data structures are rebuilt) so that the hash table has approximately twice the number of buckets.

As a general rule, the default load factor (.75) offers a good tradeoff between time and space costs. Higher values decrease the space overhead but increase the lookup cost (reflected in most of the operations of the HashMap class, including get and put). The expected number of entries in the map and its load factor should be taken into account when setting its initial capacity, so as to minimize the number of rehash operations. If the initial capacity is greater than the maximum number of entries divided by the load factor, no rehash operations will ever occur.

Note that this implementation is not synchronized. If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally.

The iterators returned by all of this class’s “collection view methods” 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.

HashMapDemo.java : Demonstrate how to use HashMap, and its methods.

package com.javalatte.itcuties.hashtable;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class HashMapDemo {

    public static void main(String[] JavaLatte) {
        HashMap<String, Integer> numberList = new HashMap<String, Integer>();
        numberList.put("one", 1);
        numberList.put("two", 2);
        numberList.put("three", 3);
        numberList.put("four", 4);
        numberList.put("five", 5);
        numberList.put("six", 6);
        numberList.put("sixteen", 6);
        System.out.println(numberList);

        //HashMap allows only one null keys and multiple null values
        numberList.put("seven", null);
        numberList.put(null, 8);
        numberList.put(null, 9);// it override the previous null key

        System.out.println("Size : " + numberList.size());
        //Output show that data is unsorted and unordered
        System.out.println(numberList);

        //HashMap method usaga
        if (numberList.containsKey(null)) {
            System.out.println("Contain null key, value=" + numberList.get(null));
        } else {
            System.out.println("Does not contain null key");
        }

        if (numberList.containsValue(11)) {
            System.out.println("11 is present");
        } else {
            System.out.println("11 is not present");
        }
        System.out.println();

        //Returns a Set view of the keys contained in this map.
        Set<String> keySet = numberList.keySet();
        System.out.println(keySet);

        //How to Iterate Over a Map in Java
        for (Map.Entry<String, Integer> entry : numberList.entrySet()) {
            System.out.println("key : " + entry.getKey() + "       value : " + entry.getValue());
        }

        System.out.println("Size of HashMap : " + numberList.size());
    }
}

HashMapIteratorDemo.java : Demonstrate the use of Iterator in HashMap.

package com.javalatte.itcuties.hashtable;

import java.util.HashMap;
import java.util.Iterator;

public class HashMapIteratorDemo {

    public static void main(String[] JavaLatte) {
        HashMap<String, Integer> numberList = new HashMap<String, Integer>();
        numberList.put("one", 1);
        numberList.put("two", 2);
        numberList.put("three", 3);
        numberList.put("four", 4);
        numberList.put("five", 5);
        numberList.put("six", 6);
        numberList.put("sixteen", 6);
        System.out.println(numberList);
        System.out.println();

        //entrySet : Returns a Set view of the mappings contained in this map.
        Iterator it = numberList.entrySet().iterator();

        //Following line will give java.util.ConcurrentModificationException
        //because iterator is fail-fast
        numberList.remove("four");

        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

Hashtable vs. HashMap – comparison

Hashtable HashMap
It is synchronized. It is not synchronized.
Hashtable does not allow null keys or values HashMap allows one null key and any number of null values.
Enumerator for the Hashtable is not fail-safe Iterator in the HashMap is fail-safe
Hashtable extends the Dictionary class HashMap extends the AbstractMap class
HashTable is thread safe and can be shared between multiple thread HashMap cannot be shared with multiple thread without proper synchronization

Download this sample code here.

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>