What is Hashtable in Java? Explained with Examples
Updated on May 28, 2025 | 18 min read | 7.93K+ views
Share:
For working professionals
For fresh graduates
More
Updated on May 28, 2025 | 18 min read | 7.93K+ views
Share:
Table of Contents
Did you know that Java is ranked second among the top programming languages in 2025? As Java continues to dominate in enterprise environments, understanding data structures like what is a Hashtable becomes essential for developing high-performance applications in multi-threaded contexts. |
A Hashtable in Java is a synchronized data structure that stores key-value pairs using a hashing technique. It ensures thread safety in concurrent environments by determining the index for storing values, making it efficient for lookups.
Unlike HashMap, it doesn’t allow null keys or values, and its iteration order is not guaranteed. Understanding what is a Hashtable is crucial for implementing thread-safe data structures in Java applications, particularly for legacy systems or simple multi-threaded use cases.
In this blog, we will explore what is a hashtable in Java, along with examples that are relevant within enterprises.
Master Java and more with upGrad’s Software Development course featuring an updated Generative AI curriculum and specializations in Cyber Security, Full Stack Development, Game Development, and more. Build a strong foundation with hands-on projects, expert mentorship, and training on the latest tools and languages!
A Hashtable is a synchronized, legacy Java collection that stores key-value pairs using hashing, unlike JavaScript’s Map or unsynchronized HashMap. It forbids null keys and values, ensuring thread safety but causing performance issues in high-concurrency applications. For scalable, modern Java or JavaScript environments, ConcurrentHashMap or asynchronous collections offer better alternatives than Hashtable.
If you want to learn Java and other programming languages for modern enterprise operations, the following courses from upGrad can help you succeed.
Both Hashtable and HashMap rely on hashing code in Java to store key-value pairs efficiently, but their concurrency handling and usage contexts differ significantly. While ReactJS developers might often interact with Java backends, understanding these distinctions is critical when dealing with data caching or session management in full-stack applications.
Although both classes use a hash table to store key-value pairs, they differ in some crucial aspects:
Feature | Hashtable | HashMap |
---|---|---|
Thread Safety |
|
|
Null Support |
|
|
Iteration Behavior |
|
|
Performance |
|
|
Legacy vs Modern Use |
|
|
Use Case Scenarios |
|
|
Example Scenario:
You maintain a legacy financial system that relies on Hashtable for thread-safe caching without refactoring. Migrating to HashMap requires extensive code changes and synchronization adjustments. Continuing with Hashtable ensures stability and backward compatibility while new systems adopt modern concurrent collections.
Now that you know what is a hashtable and how it compares with HashMap, let’s understand how it works internally and what makes it efficient.
Understanding what is a hashtable Java involves knowing its internal workings. A Hashtable stores key-value pairs in an array called buckets, where each key’s hashcode determines the bucket index. When multiple keys share the same index, collisions occur, resolved by chaining, storing entries as linked lists within buckets.
Here are some of the key considerations:
This balance of hashing, collision handling, and resizing ensures Hashtable performs efficiently in typical use cases, though modern alternatives may suit evolving needs better.
This approach makes lookups very fast on average, typically O(1) time complexity.
Code Example:
import java.util.Hashtable;
public class HashtableExample {
public static void main(String[] args) {
Hashtable<String, Integer> ht = new Hashtable<>();
ht.put("Apple", 1);
ht.put("Banana", 2);
ht.put("Cherry", 3);
System.out.println("Value for key 'Apple': " + ht.get("Apple"));
System.out.println("Value for key 'Banana': " + ht.get("Banana"));
System.out.println("Value for key 'Cherry': " + ht.get("Cherry"));
}
}
Output:
Value for key 'Apple': 1
Value for key 'Banana': 2
Value for key 'Cherry': 3
Output Explanation:
The keys "Apple," "Banana," and "Cherry" are hashed to compute their index, efficiently storing corresponding values. If two keys hash to the same index, they are handled by a linked bucket list to avoid collisions.
Let’s explore how to create a hash table Java with examples and constructors to address what is a hashtable in detail.
If you’re wondering what is a hashtable and how to create one, Java provides several constructors to initialize a hashtable based on your specific needs. Using the right constructor helps optimize both performance and memory usage by setting appropriate initial capacity and load factor.
Here’s a step-by-step guide to create a hashtable in Java:
Step 1: Choose the Default Constructor
Step 2: Use Constructor with Initial Capacity
Step 3: Use Constructor with Initial Capacity and Load Factor
Step 4: Use Constructor from an Existing Map
Code Example:
import java.util.Hashtable;
import java.util.HashMap;
import java.util.Map;
public class HashtableConstructorsExample {
public static void main(String[] args) {
// Default constructor
Hashtable<String, Integer> ht1 = new Hashtable<>();
System.out.println("Default constructor size: " + ht1.size());
// Constructor with initial capacity
Hashtable<String, Integer> ht2 = new Hashtable<>(20);
System.out.println("Initial capacity 20, size: " + ht2.size());
// Constructor with initial capacity and load factor
Hashtable<String, Integer> ht3 = new Hashtable<>(20, 0.5f);
System.out.println("Capacity 20, load factor 0.5, size: " + ht3.size());
// Constructor from another Map
Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
Hashtable<String, Integer> ht4 = new Hashtable<>(map);
System.out.println("Hashtable from Map, size: " + ht4.size());
}
}
Output:
Default constructor size: 0
Initial capacity 20, size: 0
Capacity 20, load factor 0.5, size: 0
Hashtable from Map, size: 2
Output Explanation:
Each Hashtable is initially empty except for the one created from an existing Map, which contains two entries. The initial capacity and load factor settings affect internal resizing and performance but not the immediate size. The size() method reflects the actual number of stored entries at creation time.
Important Consideration: Choosing a huge initial capacity or a very low load factor can cause unnecessary memory use without a significant performance gain. It’s best to balance these values based on your application’s expected data size and concurrency needs.
These constructors give you flexibility in how to make a hash table in Java, balancing between performance and memory use.
When creating a Hashtable Java, selecting the right constructor is crucial for balancing memory usage and performance. Different constructors offer flexibility depending on your expected data volume and access patterns.
Quick Tips for Choosing Parameters:
Each constructor serves different scenarios, and choosing the right one ensures efficient use of hashtable in Java for your specific requirements.
If you want to gain expertise in industry-relevant programming skills like Java. Check out upGrad’s AI-Powered Full Stack Development Course by IIITB. The program will allow you to gain hands-on experience with Java, JavaScript, ReactJS, and more for practical applications.
Now that we’ve covered how to create hashtables, let’s look at the common operations you can perform on a hash table Java, including examples.
Understanding what a hashtable is also involves knowing its core and advanced methods. These methods help you manipulate and interact with the data stored efficiently. Below is a comprehensive overview of key Hashtable in Java methods, with simple descriptions and practical use cases.
Hashtable provides a rich set of methods that let you perform various operations, from basic insertion and retrieval to more advanced concurrent programming patterns. Understanding these methods will help you manage data efficiently and avoid common pitfalls.
Below is a table summarizing the key Hashtable methods, their purposes, and when to use them:
Method |
Description |
put(K key, V value) | Inserts or updates the key-value pair in the hashtable. |
get(Object key) | Retrieves the value associated with the specified key, or null if none exists. |
remove(Object key) | Removes the key and its corresponding value from the hashtable. |
containsKey(Object key) | Checks if a given key exists in the hashtable. |
containsValue(Object value) | Checks if a specified value is present in the hashtable. |
size() | Returns the number of key-value pairs currently in the hashtable. |
clear() | Removes all key-value pairs from the hashtable. |
clone() | Creates a shallow copy of the hashtable. |
compute(K key, BiFunction remappingFunction) | Attempts to compute a new mapping for the specified key and its current value. Useful for atomic updates. |
computeIfAbsent(K key, Function mappingFunction) | Computes and inserts a value if the specified key is not already associated with a value. Ideal for lazy initialization. |
computeIfPresent(K key, BiFunction remappingFunction) | Computes a new value for a key only if it is already present. Useful for conditional updates. |
putIfAbsent(K key, V value) | Inserts the key-value pair only if the key is not already associated with a value. Helps avoid overwriting existing entries. |
replace(K key, V value) | Replaces the value for the specified key only if it currently maps to some value. |
replace(K key, V oldValue, V newValue) | Replaces the value for the specified key only if currently mapped to the specified old value. |
contains(Object value) | Tests if some key maps to the specified value in the hashtable. |
elements() | Returns an enumeration of all the values in the hashtable. |
entrySet() | Returns a Set view of the mappings contained in this hashtable. |
isEmpty() | Checks if the hashtable contains no key-value pairs. |
keys() | Returns an enumeration of all the keys in the hashtable. |
keySet() | Returns a Set view of the keys contained in this hashtable. |
putAll(Map<? extends K, ? extends V> t) | Copies all mappings from the specified map into the hashtable. |
rehash() | Increases the capacity and reorganizes the hashtable internally to maintain efficient access. This can be costly in time and should be minimized. Poorly implemented hash functions may lead to excessive rehashing or even infinite loops, so designing good hashCode() methods is critical. |
toString() | Returns a string representation of the hashtable’s contents. |
values() | Returns a Collection view of the values contained in the hashtable. |
Key Method Usage Insights
Now, let’s understand how you can iterate over a hashtable.
Understanding what is a Hashtable Java is essential for managing key-value data efficiently, especially in legacy or multi-threaded applications. Hashtables use a synchronized hashing mechanism to store data, unlike modern concurrent maps, making traversal techniques critical for thread safety. Integrating Hashtable operations with backend systems like SQL or MySQL and frontend frameworks like Bootstrap in full-stack Java applications requires efficient, safe iteration.
Use Cases:
In Java applications integrating SQL/MySQL for data persistence or Bootstrap for frontend UI, synchronized and predictable data retrieval from Hashtables is vital to maintain state consistency and responsiveness.
Code Example:
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.Collections;
public class HashtableIterationExample {
public static void main(String[] args) {
Hashtable<String, Integer> ht = new Hashtable<>();
ht.put("Apple", 50);
ht.put("Banana", 30);
ht.put("Cherry", 20);
// Using Enumeration to iterate keys
System.out.println("Using Enumeration:");
Enumeration<String> keysEnum = ht.keys();
while (keysEnum.hasMoreElements()) {
String key = keysEnum.nextElement();
System.out.println(key + " => " + ht.get(key));
}
// Creating synchronized map for thread-safe iteration with Iterator
Map<String, Integer> syncMap = Collections.synchronizedMap(ht);
// Using Iterator over synchronized map's entrySet
System.out.println("\nUsing Iterator with synchronizedMap:");
synchronized (syncMap) {
Iterator<Map.Entry<String, Integer>> iterator = syncMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
System.out.println(entry.getKey() + " => " + entry.getValue());
}
}
}
}
Output:
Using Enumeration:
Apple => 50
Banana => 30
Cherry => 20
Using Iterator with synchronizedMap:
Apple => 50
Banana => 30
Cherry => 20
Output Explanation:
This example shows iteration using Enumeration, which is not fail-fast, and an Iterator wrapped inside a synchronized map to ensure thread safety. The synchronized block around the Iterator prevents concurrent modifications, which is essential in multi-threaded environments.
If you want to learn advanced SQL functions for industry-relevant Java applications, check out upGrad’s Advanced SQL: Functions and Formulas. The 11-hour free program will help you understand query optimization, programming structures, and more.
Let’s explore some of the advantages and disadvantages of Hashtable Java to explain what is a hashtable and its efficacy in computational operations.
The Hashtable class in Java provides synchronized key-value storage, making it thread-safe for basic concurrent access. However, its legacy design and coarse-grained locking lead to performance bottlenecks in modern containerized environments using Docker and orchestration platforms like Kubernetes.. For scalable microservices deployed in Kubernetes clusters, finer concurrency controls provided by ConcurrentHashMap are preferred.
Here’s a tabular format to address the advantages and disadvantages of a Hashtable.
Aspects | Advantages | Disadvantages |
Thread Safety | Built-in synchronization ensures safe concurrent access. | Coarse-grained locking causes contention and slows performance on multi-core systems. |
Usage Simplicity | Simple API for key-value storage, easy for legacy use. | Lacks flexibility for advanced concurrency control. |
Legacy Compatibility | Compatible with older Java codebases. | Outdated compared to modern collections like HashMap and ConcurrentHashMap. |
Null Handling | Disallows null keys and values, avoiding null errors. | Restricts use cases needing null support; HashMap allows null keys and values. |
Performance | Works well in low-concurrency or single-threaded apps. | Synchronization overhead reduces throughput in high-concurrency, containerized environments. |
Concurrency & Scalability | Suitable for basic multithreading. | Poor scalability on multi-core and high-concurrency workloads versus ConcurrentHashMap. |
Iterator Behavior | Supports legacy Enumeration without fail-fast checks. | Iterators are not fail-fast, risking inconsistent data during concurrent modifications. |
Let’s explore some examples and best practices for Hashable in Java with code.
The Hashtable class in Java is part of the legacy collections framework and is commonly used for thread-safe key-value data storage. While it offers simple synchronization, it can impact performance in high-concurrency situations compared to more modern alternatives like ConcurrentHashMap. Understanding a Hashtable's thread-safety guarantees, iteration mechanics, and memory considerations is critical to legacy and current applications.
Below is a Hashtable example demonstrating basic operations like insertion, retrieval, iteration, and size checking.
Code Example:
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Map;
public class HashtableDemo {
public static void main(String[] args) {
// Initialize Hashtable
Hashtable<String, Integer> hashtable = new Hashtable<>();
// Insert key-value pairs
hashtable.put("Employee1", 50000);
hashtable.put("Employee2", 60000);
hashtable.put("Employee3", 55000);
// Retrieve value for a specific key
int employee1Salary = hashtable.get("Employee1");
System.out.println("Salary of Employee1: " + employee1Salary);
// Iterate over Hashtable using Enumeration
Enumeration<String> keys = hashtable.keys();
System.out.println("Hashtable Contents:");
while (keys.hasMoreElements()) {
String key = keys.nextElement();
System.out.println(key + " = " + hashtable.get(key));
}
// Check size of the Hashtable
System.out.println("Total employees in hashtable: " + hashtable.size());
}
}
Output:
Salary of Employee1: 50000
Hashtable Contents:
Employee3 = 55000
Employee2 = 60000
Employee1 = 50000
Total employees in hashtable: 3
Output Explanation:
The program first retrieves and prints Employee1's salary, which is ₹50,000. Then, it iterates over all the key-value pairs using an Enumeration of keys and prints each pair.
The order of the entries may vary because a Hashtable does not guarantee the order of elements based on insertion. Lastly, it prints the total number of entries in the Hashtable, which is 3, reflecting the three key-value pairs inserted.
Also Read: Top 12 Java Open Source Projects on GitHub You Should Explore in 2025
Let’s explore some of the best practices for the Hashtable in Java applications to comprehensively understand what is a hashtable.
When choosing a Hashtable in Java, it’s crucial to understand its strengths and limitations, especially in multi-threaded applications. While Hashtable provides thread safety through synchronized methods, it may introduce performance bottlenecks in high-concurrency scenarios compared to alternatives like ConcurrentHashMap. Using a Hashtable effectively requires careful handling of null values, iteration behavior, and awareness of its legacy status in modern Java development
Also Read: Top 22 Open Source Java Projects to Enhance Your Development Skills
Learning key data structures and understanding what is a Hashtable and hashing code in Java is essential for building efficient and thread-safe applications. Understanding concepts such as synchronization, hashing mechanics, and performance optimization ensures you write reliable, scalable code across real-world projects.
To deepen your knowledge and practical skills, upGrad offers specialized Java and data structures programs that cover essential concepts and advanced techniques. These additional courses prepare you to tackle complex coding challenges and optimize application data management.
Curious which course can help you in upskilling in Java proficiency? Contact upGrad for personalized counseling and expert guidance. For hands-on learning, you can also visit your nearest upGrad offline center.
Boost your career with our popular Software Engineering courses, offering hands-on training and expert guidance to turn you into a skilled software developer.
Master in-demand Software Development skills like coding, system design, DevOps, and agile methodologies to excel in today’s competitive tech industry.
Stay informed with our widely-read Software Development articles, covering everything from coding techniques to the latest advancements in software engineering.
900 articles published
Director of Engineering @ upGrad. Motivated to leverage technology to solve problems. Seasoned leader for startups and fast moving orgs. Working on solving problems of scale and long term technology s...
Get Free Consultation
By submitting, I accept the T&C and
Privacy Policy
India’s #1 Tech University
Executive PG Certification in AI-Powered Full Stack Development
77%
seats filled
Top Resources