DEV Community

Mohammed mhanna
Mohammed mhanna

Posted on

🔥 Mastering Data Structures in Java - Part 7: HashMap

If you’ve ever needed to store key–value pairs (like usernames and passwords, or IDs and names) — you’ve already been thinking about a HashMap.
It’s one of the most powerful and widely used data structures in Java.

Let’s break it down completely 👇


🧠 What Is a HashMap?

A HashMap in Java is a part of the Collections Framework that stores data as key-value pairs.
It allows fast access, insertion, and deletion based on keys.

✅ Keys are unique
✅ One null key is allowed
✅ Multiple null values are allowed
✅ Not thread-safe by default

import java.util.HashMap;

public class HashMapDemo {
    public static void main(String[] args) {
        HashMap<Integer, String> users = new HashMap<>();

        users.put(101, "Mohammed");
        users.put(102, "Ali");
        users.put(103, "Omar");

        System.out.println(users.get(102)); // Output: Ali
    }
}

⚙️ How HashMap Works Internally

At its core, a HashMap uses an array of buckets.
Each bucket holds a linked list (or a tree since Java 8) of entries that share the same hash.

When you put(key, value):

  • Java calculates the hash code of the key.
  • It finds the correct bucket index in the array.
  • It stores the key–value pair there.
  • If another entry has the same hash, it’s linked in the same bucket (collision).

When you get(key):

  • Java finds the hash bucket for the key.
  • Then checks for equality using equals() to find the correct value.
HashMap<String, Integer> scores = new HashMap<>();
scores.put("Alice", 90);
scores.put("Bob", 85);

System.out.println(scores.get("Alice")); // 90

💡 Tip: Always override both equals() and hashCode() when using custom objects as keys!


🧩 Example: Custom Key

class Employee {
    int id;
    String name;

    Employee(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public int hashCode() {
        return id;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof Employee)) return false;
        Employee e = (Employee) obj;
        return this.id == e.id;
    }
}

public class Main {
    public static void main(String[] args) {
        HashMap<Employee, Double> salaries = new HashMap<>();
        salaries.put(new Employee(1, "Ali"), 3000.0);
        salaries.put(new Employee(2, "Sara"), 3500.0);

        System.out.println(salaries.get(new Employee(1, "Ali"))); // 3000.0
    }
}

✅ Even though we created a new Employee object, it works because of correctly overridden equals() and hashCode().


⚡ Performance

Average complexity for put(), get(), remove()O(1)

Worst case (lots of hash collisions) → O(n)

Java 8 improved this by converting long linked lists into balanced trees when collisions become too large.


🧱 When to Use HashMap

Use Case HashMap?
Need to map keys to values ✅ Yes
Need fast lookup by key ✅ Yes
Need order preserved ❌ No
Need thread-safety ❌ No (Use ConcurrentHashMap)
Need sorting by key ❌ No (Use TreeMap)

🌍 Where HashMap Is Used in Real-World Projects

Caching Systems
Store recently used data for quick access.

HashMap<String, String> cache = new HashMap<>();
cache.put("user:101", "Ali");

Database Result Mapping
When reading from a database, mapping IDs to entities.

Configurations & Settings
Store app settings as key-value pairs.

Counting Frequency of Words or Items

HashMap<String, Integer> wordCount = new HashMap<>();
for (String word : sentence.split(" ")) {
    wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);
}

Session Management in Web Apps
Track active user sessions using userId as a key.


🧰 Common Methods

put(K key, V value)
get(Object key)
remove(Object key)
containsKey(Object key)
containsValue(Object value)
keySet()
values()
entrySet()
clear()
size()

Example:

for (Map.Entry<Integer, String> entry : users.entrySet()) {
    System.out.println(entry.getKey() + " -> " + entry.getValue());
}

🧩 Pro Tips

Use LinkedHashMap if you need predictable iteration order.

Use ConcurrentHashMap for thread-safe operations.

Avoid mutable keys — changing them breaks the map’s structure.

Load Factor (default 0.75) controls when to resize the hash table.


💡 Summary

HashMap is the backbone of many Java systems — caches, databases, configurations, and beyond.
It’s fast, flexible, and incredibly powerful — but only when you understand how hashing really works.

Top comments (0)