Knowledge Guide
HomeDSAHashing

Introduction to Hash Tables

A Hashtable (also known as Hash Map) is a data structure that stores key-value pairs and allows fast lookups, insertions, and deletions. It is an essential tool in programming for efficiently managing and retrieving data.

Imagine a locker system where:

Image
Image

In other words, a Hash Table implements an associative array abstract data type (or Dictionary ADT), mapping keys to values. A Hash Table uses a hash function to compute an index into an array of buckets or slots where the desired value is stored.

Hash Table
Hash Table

There are four main elements to any Hash Table: Keys, Values, the Hash Function, and Buckets.

Here are the three basic operations that are performed on Hash Tables:

A naive Hash Table implementation

Imagine once again a major public library that needs to store basic information, such as Key (ISBN), Title, and Placement Info, for all available books. This system is heavily used, with librarians frequently searching for books. This results in many retrieval requests.

The frequent retrievals require an efficient solution that can quickly perform the search operation (ideally, in constant time). Therefore, the Hash table data structure perfectly suits the scenario.

Let's start by discussing our data model. We will use a dynamic array of the Record type to store the books' information. Here is what our Record class looks like:

java
public class Record {

    public int key;
    public String title;
    public String placementInfo;

    public Record() {
        Key = -1;
    }

    public Record(int key, String title, String placementInfo) {
        key = key;
        title = title;
        placementInfo = placementInfo;
    }
}

ADT class

Now, let's look at the HashTable ADT class definition. The HashTable class has an HT_array pointer to store the address of the dynamically allocated array of records. The max_length property is the maximum number of records the hash table can hold. The length represents the current number of records in the Hash table. It increments and decrements with insertions and deletions, respectively.

java
public class HashTable {

    private Record[] htArray; // Array to store records
    private int maxLength; // To store maximum number of elements a Hash table can store
    private int length; // To keep track of total records present in the hash table

    // The Hash function
    private int hash(int key) {
        // Implement your hash function logic here
        // Return the calculated hash value (index within the range of the hash table's size)
        // Example: return key % max_length;
        return 0; // Placeholder, implement your hash function
    }

    // Constructor to initialize the HashTable
    public HashTable(int size) {
        maxLength = size;
        length = 0;
        htArray = new Record[size];
    }

    // Destructor to release the memory
    public void finalize() {
        htArray = null;
    }

    // Insert a record into the HashTable
    public boolean insert(Record item) {
        // Implement the Insert method logic here
        return false; // Placeholder, implement the insertion logic
    }

    // Search for a record in the HashTable based on the given key
    public boolean search(int key, Record returnedItem) {
        // Implement the Search method logic here
        return false; // Placeholder, implement the search logic
    }

    // Delete a record from the HashTable based on the given key
    public boolean delete(int key) {
        // Implement the Delete method logic here
        return false; // Placeholder, implement the deletion logic
    }
}

Defining the hash method

Let's define our Hash method H() for this naive implementation. We will use the simplest modular Hashing for this scenario:

java
public int hash(int key) {
    return key % max_length;
}

The above Hash function ensures we always get an index value in the range . Let's move on to see how the simplified/ naive Insert() method works.

Naive insertion operation

The Insert() method takes a new record as a parameter and checks if the maximum capacity of the HT_array is not reached. If the table still can have more records, the method calculates a proper index/ hash key for placing this item. After that, it puts the item at the computed index.

java
public boolean insert(Record item) {
    if (length == maxLength) {
        System.err.println("Hash table is full. Cannot insert the key-value pair.");
        return false;
    }

    int index = hash(item.Key);
    htArray[index] = item;
    length++;
    return true;
}

Point to ponder: What happens if two different keys map to the same array index? This implementation overwrites it. Indeed, it is a flaw we will address in the Solving Collisions section.

Naive search operation

Now, let's explore how and why the Search() method will retrieve records in for us. Here is a naive implementation:

java
public boolean search(int key, Record returnedItem) {
    int index = hash(key);

    if (htArray[index].key == -1) {
        return false; // Record not found
    }
    returnedItem.key = htArray[index].key;
    returnedItem.title = htArray[index].title;
    returnedItem.placementInfo = htArray[index].placementInfo;
    return true; // Return true to indicate the record was found
}

The Search() method applies the hash function H() on the passed key and checks if the hash table slot is empty or not. If this slot has a valid record, the Search() method assigns the record at this slot to the reference parameter. Also, it returns a true flag to indicate the operation's success.

The above implementation of Search() clearly takes constant time (i.e., ) time to retrieve/ search any record regardless of the size our table may grow. This is evident by the fact that you only have to apply the hash function only constant number of times to calculate the position of the searched item.

Note: This naive implementation for the search doesn't cover all aspects. We will discuss a more sophisticated method in the next lesson.

Naive delete operation

Like the search operation, this deletion operation first locates the item requiring a delete. Afterward, the deletion operation simply places a null or default object at the table slot.

Here is what the naive implementation looks like:

java
public boolean delete(int key) {
    int index = hash(key);

    if (htArray[index].key == key) {
        htArray[index].key = -1; // Mark the slot as empty
        length--;
        return true;
    }
    return false; // The slot is already empty or there is a different item at the slot
}

Again, like the search operation, deletion also takes a constant time to locate and delete an item from the table. But, it is important to note that this naive implementation is just to get an overall idea of how the hash table works. However, it doesn't cater to many exceptional cases; we will discuss those in the subsequent sections.

Here is the complete code for the naive hash table implementation with a sample driver code:

java
import java.util.Arrays;

class Record {
    public int key;
    public String title;
    public String placementInfo;

    public Record() {
        key = -1;
    }

    public Record(int key, String title, String placementInfo) {
        this.key = key;
        this.title = title;
        this.placementInfo = placementInfo;
    }
}

class HashTable {
    private Record[] htArray;
    private int maxLength;
    private int length;

    public HashTable(int size) {
        maxLength = size;
        length = 0;
        htArray = new Record[size];
        Arrays.fill(htArray, new Record());
    }

    private int hash(int key) {
        return key % maxLength;
    }

    public boolean Insert(Record item) {
        if (length == maxLength) {
            System.err.println("Hash table is full. Cannot insert the key-value pair.");
            return false;
        }

        int index = hash(item.key);
        htArray[index] = item;
        length++;
        return true;
    }

    public boolean search(int key, Record returnedItem) {
        int index = hash(key);

        if (htArray[index].key == -1) {
            return false; // Record not found
        }
        returnedItem.key = htArray[index].key;
        returnedItem.title = htArray[index].title;
        returnedItem.placementInfo = htArray[index].placementInfo;
        return true; // Return true to indicate the record was found
    }

    public boolean delete(int key) {
        int index = hash(key);

        if (htArray[index].key == key) {
            htArray[index].key = -1; // Mark the slot as empty
            length--;
            return true;
        }
        return false; // The slot is already empty or there is a different item at the slot
    }
}

class Solution {
    public static void main(String[] args) {
        HashTable hashTable = new HashTable(10);

        // Insert book information
        hashTable.Insert(new Record(1001, "Introduction to Programming", "A2 Shelf"));
        hashTable.Insert(new Record(1002, "Data Structures and Algorithms", "B1 Shelf"));
        hashTable.Insert(new Record(1003, "Database Management Systems", "C3 Shelf"));

        // Retrieve book information
        Record book = new Record();
        if (hashTable.search(1001, book)) {
            System.out.println("Book Information for Key " + book.key + ":");
            System.out.println("Title: " + book.title);
            System.out.println("Placement Info: " + book.placementInfo);
        } else {
            System.out.println("No book information found for Key 1001");
        }

        // Delete a book information
        hashTable.delete(1001);

        // Retrieve the book status after deletion
        if (hashTable.search(1001, book)) {
            System.out.println("Book Information for Key " + book.key + ":");
            System.out.println("Title: " + book.title);
            System.out.println("Placement Info: " + book.placementInfo);
        } else {
            System.out.println("No book information found for Key 1001");
        }
    }
}

Implementation

Here is how different languages have implemented Hash Tables:

LanguageAPI
Javajava.util.Map Or java.util.HashMap
Pythondict
C++std::unordered_map
JavaScriptObject or Map

When to Use a Hashtable?

🤖 Don't fully get this? Learn it with Claude

Stuck on Introduction to Hash Tables? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Introduction to Hash Tables** (DSA) and want to truly understand it. Explain Introduction to Hash Tables from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Introduction to Hash Tables** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Introduction to Hash Tables** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Introduction to Hash Tables** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes