Java Hashtable Class

In Java, a Hashtable is a data structure where each key is unique and is utilized for storing key-value pairs. It is part of the Java.util package and implements the Map interface to manage its contained elements. A key feature of a Hashtable is its efficiency in enabling quick retrieval and addition operations.

Within a Hash Table, a hash function is employed to find an index within an array of buckets or slots. Each bucket represents a possible place to store a key-value pair. Upon adding an entry to the Hashtable, the key's hash code is computed, and the specific bucket for storing the entry is determined using this hash code. If the bucket is already occupied, a collision resolution process takes place, resulting in the new entry being added to the existing bucket or placed in a different location.

Hashtable functions similarly to HashMap in terms of usage, with the key distinction being that it is synchronized, ensuring thread safety. This means multiple threads can access a Hashtable simultaneously without risking data corruption. However, this synchronization can impact performance, making HashMap a preferable choice when synchronization is unnecessary.

Points to Remember

  • A Hashtable is an array of a list. Each list is known as a bucket. The position of the bucket is identified by calling the hashcode method. A Hashtable contains values based on the key.
  • Java Hashtable class contains unique elements.
  • Java Hashtable class doesn't allow null key or value.
  • Java Hashtable class is synchronized.
  • The initial default capacity of Hashtable class is 11 whereas loadFactor is 0.75.
  • Hashtable Class Declaration

Let's examine the declaration of the java.util.Hashtable class.

Example

public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable

Hashtable Class Parameters

Explore the Specifications for the java.util.Hashtable class:

-

  • K: Denotes the category of keys managed by this map.

-

  • V: Represents the variety of values mapped.
  • Features of Hashtable

Mapping Key-Value Pairs: In contrast to alternative Map structures, Hashtable is designed to store key-value pairs. This characteristic enables efficient direct access to a specific value using its corresponding key.

Synchronization is a feature of Hashtables that ensures thread safety, allowing multiple threads to access and modify it concurrently without causing data corruption. However, excessive synchronization can adversely impact performance, especially in highly concurrent applications.

Avoiding Null Keys or Values: Hashtable does not support null keys or values. Attempting to insert a null key or value will result in a NullPointerException.

When iterating through a Hashtable, there are multiple methods available for traversing its items. You can utilize keySet, values, and entrySet to obtain collections that enable you to iterate through keys, values, or key-value pairs by applying different methods accordingly.

Performance: A hashtable typically exhibits constant time performance for fundamental operations such as get and put in usual scenarios. However, its performance may degrade under substantial concurrent usage as a replacement for unsynchronized collections like HashMap.

Dynamic resizing: The HashTable is equipped with an automatic resizing feature that triggers when additional elements must be accommodated. Once the number of elements exceeds a specified threshold (known as the load factor), the HashTable increases its capacity by a factor and proceeds to rehash all elements internally.

The Hashtable class includes support for the Enumeration interface to iterate over its elements. Although considered outdated and less efficient compared to iterators or enhanced for loop functionalities, it remains present for backward compatibility with legacy Java code.

Hashtable: A legacy class in Java that has been present since the early versions of the language. While it has been largely superseded by the HashMap and ConcurrentHashMap classes, which offer improved performance and additional features, Hashtable is still utilized in legacy projects or scenarios where ensuring thread safety is paramount.

Advantages of Hashtable

Concurrency: Hashtable ensures thread safety, making it suitable for concurrent environments. It allows multiple threads to interact with it concurrently for reading and writing operations without requiring external synchronization, thereby streamlining concurrent programming tasks.

Reliable Performance: A Hashtable achieves constant-time performance for fundamental operations like get and put under normal circumstances, making it suitable for tasks that require consistent performance.

Dynamic Resizing: The hash table has the ability to automatically adjust its size as more elements are added. Once the number of elements reaches a certain point relative to the load factor, the Hashtable internally increases its capacity and rehashes the elements. This feature ensures that the Hashtable can effectively manage a large volume of data without requiring manual intervention.

Storing and retrieving key-value pairs efficiently is facilitated by a hashtable, making it an excellent data structure. This allows for quick retrieval of values based on their corresponding keys, which is beneficial for tasks such as caching, indexing, and data retrieval.

Historical Compatibility: The hashtable was integrated into Java Collections in the initial releases of Java. It continues to be utilized in outdated codebases to facilitate compatibility with earlier Java applications and libraries.

Enumeration Feature: In HashTable, enumeration support allows for iterating through its elements using the Enumeration interface. Enumerations are not as suitable for repetitive tasks as iterators or enhanced for loops, but they are included for compatibility with legacy Java code.

Avoiding Null Keys or Values: Hashtable in Java doesn't allow null keys or values to be inserted. This restriction helps prevent bugs and NullPointerExceptions in the code.

Consistent Performance During High Load: The synchronized feature of Hashtable demonstrates reliable performance even under heavy concurrent access. Nevertheless, the synchronization overhead can impact performance more significantly compared to unsynchronized collections. In scenarios where Hashtable is unsynchronized, its performance remains steady and suitable for various purposes.

Disadvantages of Hashtable

Synchronization Impact: The Hashtable is synchronized, allowing only one thread to access it at a time. This introduces extra overhead, potentially impacting performance, especially in scenarios where extensive concurrency is unnecessary.

Impact on Performance: Consequently, Hashtable functions exhibit slower performance compared to unsynchronized HashMap operations. This performance gap is further accentuated in highly concurrent environments.

Restricted Flexibility: HashTable does not support null keys or values. This limitation can pose challenges in scenarios where null values are permissible or suitable.

Memory Inefficiency: When a Hashtable is created, memory slots are allocated based on its initial capacity and load factor. If the capacity is set too high, it can lead to wastage of memory space, especially when the table is not fully filled.

Outdated Functionalities: The Hashtable class in Java is considered antiquated. While it can still be useful in certain scenarios, modern alternatives such as HashMap and ConcurrentHashMap offer improved efficiency, a wider range of features, and decreased memory usage.

When iterating through elements in the Hashtable class, developers have the option of using either Enumeration or Iterator. Even though Enumeration is simpler to use, it is considered less sophisticated and flexible compared to iterators or enhanced loops found in modern collections.

Constructors of Java Hashtable Class

The Hashtable class offers multiple constructors for creating hashtable instances. Each constructor enables the initialization of the hashtable in various manners, offering versatility according to specific needs.

Constructor Description
Hashtable() It creates an empty hashtable having the initial default capacity and load factor.
Hashtable(int capacity) It accepts an integer parameter and creates a hash table that contains a specified initial capacity.
Hashtable(int capacity, float loadFactor) It is used to create a hash table having the specified initial capacity and loadFactor.
Hashtable(Map<? extends K,? extends V> t) It creates a new hash table with the same mappings as the given Map.

Methods of Java Hashtable Class

Method Description
void clear() It is used to reset the hash table.
Object clone() It returns a shallow copy of the Hashtable.
V compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) It is used to compute a mapping for the specified key and its current mapped value (or null if there is no current mapping).
V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction) It is used to compute its value using the given mapping function, if the specified key is not already associated with a value (or is mapped to null), and enters it into this map unless null.
V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) It is used to compute a new mapping given the key and its current mapped value if the value for the specified key is present and non-null.
Enumerationelements() It returns an enumeration of the values in the hash table.
Set<Map.Entry<K,V>> entrySet() It returns a set view of the mappings contained in the map.
boolean equals(Object o) It is used to compare the specified Object with the Map.
void forEach(BiConsumer<? super K,? super V> action) It performs the given action for each entry in the map until all entries have been processed or the action throws an exception.
V getOrDefault(Object key, V defaultValue) It returns the value to which the specified key is mapped, or defaultValue if the map contains no mapping for the key.
int hashCode() It returns the hash code value for the Map
Enumeration<K> keys() It returns an enumeration of the keys in the hashtable.
Set<K> keySet() It returns a Set view of the keys contained in the map.
V merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction) If the specified key is not already associated with a value or is associated with null, associates it with the given non-null value.
V put(K key, V value) It inserts the specified value with the specified key in the hash table.
void putAll(Map<? extends K,? extends V> t)) It is used to copy all the key-value pair from map to hashtable.
V putIfAbsent(K key, V value) If the specified key is not already associated with a value (or is mapped to null) associates it with the given value and returns null, else returns the current value.
boolean remove(Object key, Object value) It removes the specified values with the associated specified keys from the hashtable.
V replace(K key, V value) It replaces the specified value for a specified key.
boolean replace(K key, V oldValue, V newValue) It replaces the old value with the new value for a specified key.
void replaceAll(BiFunction<? super K,? super V,? extends V> function) It replaces each entry's value with the result of invoking the given function on that entry until all entries have been processed or the function throws an exception.
String toString() It returns a string representation of the Hashtable object.
Collectionvalues() It returns a collection view of the values contained in the map.
boolean contains(Object value) This method returns true if some value equal to the value exists within the hash table, else return false.
boolean containsValue(Object value) This method returns true if some value equal to the value exists within the hash table, else return false.
boolean containsKey(Object key) This method return true if some key equal to the key exists within the hash table, else return false.
boolean isEmpty() This method returns true if the hash table is empty; returns false if it contains at least one key.
protected void rehash() It is used to increase the size of the hash table and rehashes all of its keys.
V get(Object key) This method returns the object that contains the value associated with the key.
V remove(Object key) It is used to remove the key and its value. This method returns the value associated with the key.
int size() This method returns the number of entries in the hash table.

Constructors

Hashtable

Upon instantiation, the Hashtable constructor creates a fresh hashtable devoid of any elements. It establishes the initial capacity at a standard value (typically 11) and the load factor at the customary value of 0.75. These internal parameters play a crucial role in governing the performance and resizing actions of the hashtable when new elements are introduced.

HashTableExample1.java

Example

import java.util.Hashtable;

public class HashTableExample1 {

    public static void main(String[] args) {

        // Creating an empty hashtable with default initial capacity and load factor

        Hashtable<String, Integer> hashtable = new Hashtable<>();        

        // Print the hashtable

        System.out.println("Hashtable: " + hashtable);

    }

}

Output:

Output

Hashtable: {}

Hashtable(int initialCapacity)

The constructor Hashtable(int initialCapacity) creates a fresh hashtable that is empty and has a designated initial capacity. This initial capacity represents the quantity of buckets employed to hold key-value pairs, impacting the hashtable's efficiency and memory consumption. The hashtable's resizing to accommodate additional elements is triggered by the load factor of 0.75 by default.

HashTableExample2.java

Example

import java.util.Hashtable;

public class HashTableExample2 {

    public static void main(String[] args) {

        // Creating an empty hashtable with a specified initial capacity

        int initialCapacity = 20;

        Hashtable<String, Integer> hashtable = new Hashtable<>(initialCapacity);        

        // Print the hashtable

        System.out.println("Hashtable: " + hashtable);

    }

}

Output:

Output

Hashtable: {}

Hashtable(int initialCapacity, float loadFactor)

The constructor Hashtable(int initialCapacity, float loadFactor) creates a fresh hashtable that is empty, setting the initial capacity and load factor as specified. The initial capacity defines the quantity of buckets, and the load factor dictates when resizing should occur. Setting a specific load factor can impact how the hashtable adjusts its size according to the estimated element count and memory limitations.

HashTableExample3.java

Example

import java.util.Hashtable;

public class HashTableExample3 {

    public static void main(String[] args) {

        // Creating an empty hashtable with specified initial capacity and load factor

        int initialCapacity = 20;

        float loadFactor = 0.5f; // Custom load factor

        Hashtable<String, Integer> hashtable = new Hashtable<>(initialCapacity, loadFactor);        

        // Print the hashtable

        System.out.println("Hashtable: " + hashtable);

    }

}

Output:

Output

Hashtable: {}

Hashtable(Map<Map<K, V>> t)

The constructor Hashtable(Map<? extends K, ? extends V> t) is used to create a new hashtable that contains the exact mappings present in the specified map. It duplicates all the key-value pairs from the specified map to the new hashtable, essentially replicating its data. This constructor offers a simple method to generate a hashtable with pre-existing mappings sourced from a given map.

HashTableExample4.java

Example

import java.util.Hashtable;

import java.util.HashMap;

import java.util.Map;

public class HashTableExample4 {

    public static void main(String[] args) {

        // Creating a Map

        Map<String, Integer> map = new HashMap<>();

        map.put("One", 1);

        map.put("Two", 2);

        map.put("Three", 3);        

        // Creating a hashtable from the map

        Hashtable<String, Integer> hashtable = new Hashtable<>(map);        

        // Print the hashtable

        System.out.println("Hashtable: " + hashtable);

    }

}

Output:

Output

Hashtable: {One=1, Three=3, Two=2}

Java Hashtable Example

Hashtable1.java

Example

import java.util.*;

class Hashtable1{

 public static void main(String args[]){

  Hashtable<Integer,String> hm=new Hashtable<Integer,String>();



  hm.put(100,"Amit");

  hm.put(102,"Ravi");

  hm.put(101,"Vijay");

  hm.put(103,"Rahul");



  for(Map.Entry m:hm.entrySet()){

   System.out.println(m.getKey()+" "+m.getValue());

  }

 }

}

Output:

Output

103 Rahul

102 Ravi

101 Vijay

100 Amit

Java Hashtable Example: remove

Hashtable2.java

Example

import java.util.*;

public class Hashtable2 {

   public static void main(String args[]) {

  Hashtable<Integer,String> map=new Hashtable<Integer,String>();  	  

	 map.put(100,"Amit");  

	 map.put(102,"Ravi"); 

	 map.put(101,"Vijay");  

	 map.put(103,"Rahul");  

	 System.out.println("Before remove: "+ map);  

	   // Remove value for key 102

	   map.remove(102);

	   System.out.println("After remove: "+ map);

   }    

}

Output:

Output

Before remove: {103=Rahul, 102=Ravi, 101=Vijay, 100=Amit}

After remove: {103=Rahul, 101=Vijay, 100=Amit}

Java Hashtable Example: getOrDefault

Hashtable3.java

Example

import java.util.*;

class Hashtable3{

 public static void main(String args[]){

 	Hashtable<Integer,String> map=new Hashtable<Integer,String>();  	  

	 map.put(100,"Amit");  

	 map.put(102,"Ravi"); 

	 map.put(101,"Vijay");  

	 map.put(103,"Rahul");  

	 //Here, we specify the if and else statement as arguments of the method

	 System.out.println(map.getOrDefault(101, "Not Found"));

	 System.out.println(map.getOrDefault(105, "Not Found"));

 }

}

Output:

Output

Vijay

Not Found

Java Hashtable Example: putIfAbsent

Hashtable4.java

Example

import java.util.*;

class Hashtable4{

 public static void main(String args[]){

 	Hashtable<Integer,String> map=new Hashtable<Integer,String>();  	  

	 map.put(100,"Amit");  

	 map.put(102,"Ravi"); 

	 map.put(101,"Vijay");  

	 map.put(103,"Rahul");  

	 System.out.println("Initial Map: "+map);

	 //Inserts, as the specified pair is unique

	 map.putIfAbsent(104,"Gaurav");

	 System.out.println("Updated Map: "+map);

	 //Returns the current value, as the specified pair already exist

	 map.putIfAbsent(101,"Vijay");

	 System.out.println("Updated Map: "+map);

 }

}

Output:

Output

Initial Map: {103=Rahul, 102=Ravi, 101=Vijay, 100=Amit}

Updated Map: {104=Gaurav, 103=Rahul, 102=Ravi, 101=Vijay, 100=Amit}

Updated Map: {104=Gaurav, 103=Rahul, 102=Ravi, 101=Vijay, 100=Amit}

Java Hashtable Example: Book

HashtableExample.java

Example

import java.util.*;  

class Book {  

int id;  

String name,author,publisher;  

int quantity;  

public Book(int id, String name, String author, String publisher, int quantity) {  

    this.id = id;  

    this.name = name;  

    this.author = author;  

    this.publisher = publisher;  

    this.quantity = quantity;  

}  

}  

public class HashtableExample {  

public static void main(String[] args) {  

    //Creating map of Books  

    Map<Integer,Book> map=new Hashtable<Integer,Book>();  

    //Creating Books  

    Book b1=new Book(101,"Let us C","Yashwant Kanetkar","BPB",8);  

    Book b2=new Book(102,"Data Communications & Networking","Forouzan","Mc Graw Hill",4);  

    Book b3=new Book(103,"Operating System","Galvin","Wiley",6);  

    //Adding Books to map 

    map.put(1,b1);

    map.put(2,b2);

    map.put(3,b3);    

    //Traversing map

    for(Map.Entry<Integer, Book> entry:map.entrySet()){  

    	int key=entry.getKey();

    	Book b=entry.getValue();

        System.out.println(key+" Details:");

        System.out.println(b.id+" "+b.name+" "+b.author+" "+b.publisher+" "+b.quantity); 

    }  

}  

}

Output:

Output

3 Details:

103 Operating System Galvin Wiley 6

2 Details:

102 Data Communications & Networking Forouzan Mc Graw Hill 4

1 Details:

101 Let us C Yashwant Kanetkar BPB 8

Input Required

This code uses input(). Please provide values below: