Skip to main content
Tech blog

What is the difference between HashMap, Hashtable and ConcurrentHashMap?

By Markian MumbaSeptember 21, 2025
TechData structuresHashmapHashtableconcurrenthashmap
entrance to a quarry

Entrance to a Quarry, Vincent van Gogh (1853 - 1890)

As I was scrolling through my usual YouTube feed and watching developer talks, a video was suggested on my homepage. The title was something like "JP Morgan interview questions for Java developers." I was intrigued and opened it. The video didn't have many views, which gave it more credibility in my eyes. The guy listed questions that ranged from Java to Spring to Hibernate to Spring Boot. I saved the video and decided to go through all those questions. Then a better idea came about: what if I just do one question at a time, but instead of just answering it, do a deeper dive on the topic of that question? This would give me more insight into the workings of Java and Spring Boot.

This will be a series of me answering these questions and sharing articles about the findings I've made while doing the research. So, as the title suggests, this will be our first question from the video:

What is the difference between the 3 different data structures?

All of these are data structures that solve the same core problem: they need to store key-value pairs and retrieve values quickly using their keys. This is accomplished through a process called hashing, where a function converts the keys into an array of indexes.

Building Blocks

When starting out, it will be an array of, say, 16 slots. These slots are known as buckets. Each bucket can hold one or more entries—these being our key-value pairs. The bucket that a key goes into is determined by the hashing function we have in place.

bucketIndex = hash(key) % numberOfBuckets Key: "lion" Value: "an animal of kingdom Panthera" Let's say the hash of "lion" is 12345. If we have 16 buckets: 12345 % 16 = 9 So this would go to bucket 9

In Java, a bucket could be a linked list, but in newer versions of Java, when too many entries collide into the same bucket, the list may turn into a balanced tree for efficiency.

bucket[9] → [("lion", "Panthera"), ("tiger", "Panthera"), ("leopard", "Panthera")]

HashMap

HashMap prioritizes speed above all else. It makes no guarantee about thread safety, which means if multiple threads try to modify it simultaneously, you could end up with corrupted data or infinite loops. The lack of synchronization overhead makes it extremely fast for single-threaded operations.

Hashtable

This one takes a different approach. Every single method in a Hashtable is synchronized, meaning only one thread can access it at any given moment. This makes Hashtable thread-safe by default, but that comes with a significant performance cost. Also, a Hashtable does not allow null keys or null values, which are allowed in HashMap.

ConcurrentHashMap

Here we're using a more sophisticated approach to tackle thread safety. Instead of blocking the entire structure like Hashtable, we do segment-based locking or bucket-level locking. This design allows multiple threads to read concurrently and even allows some concurrent modifications, as long as they're not affecting the same buckets. The result is much better performance than Hashtable while maintaining thread safety.

Locking Strategies Explained

  • Hashtable:

    • Puts a lock on the whole table.

    • Imagine putting a giant wall around the whole array of buckets.

    • If thread A is updating "lion" in bucket 9, thread B cannot even read "zebra" in bucket 3 until A finishes.

  • HashMap:

    • No locking at all

    • Multiple threads can walk in and start changing buckets.

    • But if two threads change bucket 9 at the same time, one can overwrite or corrupt the other (race condition).

  • ConcurrentHashMap:

    • Uses

      fine-grained locking

    • Instead of locking the whole table, it locks

      only the bucket (or segment) being modified

    • So if thread A is writing "lion" in bucket 9, thread B is free to write "zebra" in bucket 3.

Can HashMap Work Like ConcurrentHashMap?

From my understanding, we can say that HashMap can work like a ConcurrentHashMap to some degree:

  • A plain HashMap has no locks at all

  • If multiple threads happen to always touch different buckets, then in practice, it can behave like a ConcurrentHashMap.

  • Example:

    • Thread A always updates "lion" → bucket 9

    • Thread B always updates "zebra" → bucket 3

    • Since they never step on each other's toes, both can run in parallel without corruption.

But the moment two threads hit the same bucket, chaos ensues:

  • One reads "lion"'s value while another is halfway through writing it → inconsistent value.

  • Worse: if the internal structure (like the linked list/tree in the bucket) is being resized/rehashed at the same time → the whole HashMap can get corrupted (endless loops, missing entries, etc.).

That's why we say HashMap is not thread-safe, even if sometimes it looks okay when threads are operating on different keys.

Real-World Analogy

Here's a practical way to think about when to use each: HashMap is like cooking alone in your kitchen—you can move fast because you don't have to coordinate with anyone. Hashtable is like a kitchen where only one person can be present at any time, even if one person just wants to grab a snack while another is cooking. ConcurrentHashMap is like a well-designed commercial kitchen where multiple chefs can work simultaneously as long as they're not trying to use the exact same burner at the same time.

Practical Example: Bank Balance Race Condition

To see how the different structures work, imagine we have a program that uses two threads to increase the bank balance for Alice. Each thread has a for loop that goes from 1 to 1,000, adding each number to the bank balance. So the correct outcome should be 2,000.

  • For HashMap: The result might be less than 2,000. This is because at one point or another, the two threads updated the amount simultaneously, thus overwriting each other's changes. This brings about the concept of a race condition.

  • For Hashtable: The result will be correct and will add up to 2,000. This is because it is synchronised—when thread one is doing a put operation, thread two must wait to do its put operation, so there is no race condition.

When to Use Which as a Web Developer?

The bigger question becomes: as a web developer building with React/Angular and Spring Boot, when will I know that I'm in a single-threaded or multi-threaded environment, so I know when to use which data structure?

In Spring Boot applications, you're typically dealing with a multi-threaded environment where each HTTP request is handled by a separate thread. If you're sharing data structures between these threads (like caching data in a service), you'll want to use ConcurrentHashMap. For local operations within a single request handler, HashMap is usually fine.

💎 Random Nugget

"You must be imaginative, strong-hearted. You must try things that may not work, and you must not let anyone define your limits because of where you come from. Your only limit is your soul."
Chef Gusteau, Ratatouille