DevNotes
Support
Collection Framework · Chapter 14

Map Interface

Key-value storage — unique keys, core and Java 8 methods (computeIfAbsent, merge), views, and choosing the right Map.

◷ 15 min read§ 15 sections? 23 interview questions{ } 50 code examples

#Introduction

We are now entering the most important part of the Collections Framework for interviews. Map is fundamentally different from List, Set, Queue and Deque. The key idea is:

A Map stores data as key-value pairs. Keys are unique; values don't have to be.

#What is Map?

Package:

Java
java.util.Map

A Map represents Key → Value associations:

KeyValue
101"Thimmaraju"
102"Rahul"
103"Priya"

Here the keys are 101, 102, 103 and the values are Thimmaraju, Rahul, Priya.

#Map Is NOT a Collection

This is a common interview question.

  • Iterable
    • Collection
      • List
      • Set
      • Queue
  • Map
    • HashMap
      • LinkedHashMap
    • TreeMap
    • …
Map is a separate hierarchy

Map does not extend Collection. Why? Because a Collection represents individual elements (A, B, C), while a Map represents associations (A → 100, B → 200, C → 300).

However, a Map provides Collection views:

Java
map.keySet();
map.values();
map.entrySet();

#Map Basics

Basic Example

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

employees.put(101, "John");
employees.put(102, "David");
employees.put(103, "Sarah");
101
John
102
David
103
Sarah

Keys Must Be Unique

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

map.put(101, "John");
map.put(102, "David");
map.put(101, "Mike");

Final result: 101 → Mike, 102 → David. The second put(101, …) replaces the previous value; it does not create another entry.

Values Can Be Duplicated

Java
map.put(101, "John");
map.put(102, "John");
map.put(103, "John");

Valid. So remember: Key → unique, Value → can repeat.

#Core Map Methods

The most important methods: put(), get(), remove(), containsKey(), containsValue(), size(), isEmpty(), clear() — and the views keySet(), values(), entrySet().

put()

Adds or updates a mapping.

Java
map.put("A", 100);   // A → 100 (new)
map.put("A", 200);   // A → 200 (updated)

Return Value of put()

Important interview detail.

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

System.out.println(map.put("A", 100));
System.out.println(map.put("A", 200));
Output
null
100

Why? The first insertion has no previous value → null. The second returns the previous value → 100.

get()

Java
Integer value = map.get("A");   // 200
map.get("X");                   // null — key not present

The get() + null Problem

Java
map.put("A", null);

map.get("A");   // null
map.get("X");   // also null

So you cannot always distinguish "key exists with a null value" from "key doesn't exist" using get() alone. Use:

Java
map.containsKey("A");

containsKey()

Checks whether a key exists. This is generally the correct operation when your question is "Does this key exist?"

Java
if (map.containsKey("A")) {
    // ...
}

containsValue()

Checks whether a value exists:

Java
map.containsValue("John");

Unlike key lookup, value searching generally requires examining entries — typically O(n). containsKey() is designed around key lookup; containsValue() typically scans values.

remove()

Java
map.remove(101);

The entire mapping (101 → John) disappears. remove(key) returns the previous value, or null if there was no mapping.

remove(key, value)

A conditional version:

Java
map.remove(101, "John");

It removes the mapping only if both key and value match. Useful for conditional updates and concurrent-style logic.

replace()

Java
map.replace(101, "Mike");

Unlike put(), replace() only operates when the key already exists. There is also:

Java
map.replace(101, "John", "Mike");

which replaces only when the current value matches "John".

#Modern Map Methods (Java 8+)

putIfAbsent()

Very important modern Map method.

Java
map.putIfAbsent(101, "John");

It inserts only if the key doesn't already have a mapping.

putIfAbsent(key, value)
Key exists?
do nothing
insert
This is particularly useful when you don't want to overwrite an existing value

computeIfAbsent()

One of the most useful Map methods. Suppose:

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

You want a list for a key, creating it only when necessary. Instead of verbose code:

Java
if (!map.containsKey("Java")) {
    map.put("Java", new ArrayList<>());
}
map.get("Java").add(10);

use:

Java
map.computeIfAbsent("Java", k -> new ArrayList<>()).add(10);

This pattern is extremely common in real Java code.

computeIfPresent()

Runs a computation only when the key is already mapped:

Java
map.computeIfPresent("A", (key, value) -> value + 10);

If A → 100, it becomes A → 110.

compute()

Runs the remapping function regardless of whether the key currently exists:

Java
map.compute("A", (key, value) -> value == null ? 1 : value + 1);

Useful for counters and state updates.

merge()

Very useful for counting.

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

Instead of:

Java
if (counts.containsKey(word)) {
    counts.put(word, counts.get(word) + 1);
} else {
    counts.put(word, 1);
}

use:

Java
counts.merge(word, 1, Integer::sum);

For Java Java Python the result is Java → 2, Python → 1.

getOrDefault()

Java
int count = map.getOrDefault("Java", 0);

If Java → 5, returns 5; if absent, returns 0. Useful for counters and lookup logic.

forEach()

Java
map.forEach((key, value) -> System.out.println(key + " = " + value));

Concise and readable.

replaceAll()

Transforms all values:

Java
map.replaceAll((key, value) -> value + 10);

A → 100, B → 200 becomes A → 110, B → 210.

clear(), size() and isEmpty()

  • map.clear(); → removes all mappings → {}
  • map.size(); → number of key-value mappings. For A → 10, B → 20, C → 30, size() is 3, not 6 — a mapping consists of one key and one value.
  • map.isEmpty(); → true if there are no mappings.

#Map Views

keySet()

Returns a Set view of the keys.

Java
Set<Integer> keys = map.keySet();   // 101, 102, 103

Because keys are unique, a Set is appropriate.

values()

Returns a Collection view of values.

Java
Collection<String> values = map.values();   // John, David, Sarah

Why Collection instead of Set? Because values can be duplicated.

entrySet()

Returns a Set of key-value entries. Each entry contains a key and a value.

Java
Set<Map.Entry<Integer, String>> entries = map.entrySet();

Best Way to Iterate a Map

Prefer:

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

Why? Because you get both key and value directly.

Why Not keySet() + get()?

Java
for (Integer key : map.keySet()) {
    System.out.println(key + " = " + map.get(key));
}

This performs a separate lookup for every key. With entrySet() you access the mapping directly.

Map Views Are Backed by the Map

This is an important concept.

Java
Set<Integer> keys = map.keySet();

This isn't necessarily an independent copy — it is a view. Modifications through supported view operations can affect the original Map.

  • Map
    • keySet()
    • values()
    • entrySet()
These are different views of the same underlying mappings

#Map Implementations

The major implementations you need to know: HashMap, LinkedHashMap, TreeMap, Hashtable, ConcurrentHashMap, WeakHashMap, IdentityHashMap, EnumMap. Their selection depends on requirements.

HashMap

The most commonly used Map: key-value storage + fast average lookup + no ordering guarantee.

OperationComplexity
put()O(1) average
get()O(1) average
remove()O(1) average

Internally: HashMap → hash table → buckets. We'll dedicate a separate chapter to HashMap internals.

LinkedHashMap

Adds predictable iteration order: HashMap + linked ordering structure. By default, it maintains insertion order.

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

map.put(3, "C");
map.put(1, "A");
map.put(2, "B");
Output
3 → C
1 → A
2 → B

TreeMap

Provides sorted keys. Internally: TreeMap → Red-Black Tree.

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

map.put(30, "C");
map.put(10, "A");
map.put(20, "B");
Output
10 → A
20 → B
30 → C

Typical operations: O(log n).

Hashtable

Legacy synchronized Map implementation.

Java
Hashtable<Integer, String> map = new Hashtable<>();
  • Thread-safe through synchronization
  • Does not allow null keys
  • Does not allow null values
  • Legacy API

For new concurrent code, prefer appropriate classes from java.util.concurrent, especially ConcurrentHashMap for general concurrent hash-map use.

ConcurrentHashMap

Designed for concurrent access.

Java
Map<Integer, String> map = new ConcurrentHashMap<>();
  • Thread-safe
  • High concurrency
  • Does not allow null keys
  • Does not allow null values
  • Better suited to modern concurrent applications than Hashtable

We'll study its internals separately.

WeakHashMap

Uses weak references for keys. This allows entries to become eligible for garbage collection when their keys are no longer strongly referenced elsewhere.

Normal HashMap
Map → Key
Key stays reachable
WeakHashMap
Map → weak reference → Key
Key can be collected

Useful for certain cache/metadata scenarios. It is not a general-purpose replacement for a normal cache.

IdentityHashMap

A particularly interesting Map. A normal HashMap compares keys using equals(); IdentityHashMap uses ==.

Java
String a = new String("Java");
String b = new String("Java");

a.equals(b) is true, but a == b is false. HashMap considers them equal keys; IdentityHashMap treats them as different keys.

EnumMap

A specialized Map for enum keys.

Java
enum Day {
    MONDAY, TUESDAY, WEDNESDAY
}

EnumMap<Day, String> map = new EnumMap<>(Day.class);

Advantages:

  • Very efficient
  • Compact
  • Designed specifically for enum keys
  • Maintains enum declaration order when iterated

If your keys are enums, EnumMap is often an excellent choice.

#Map Selection Guide

This table is worth memorizing:

RequirementChoose
General-purpose fast lookupHashMap
Fast lookup + insertion orderLinkedHashMap
Sorted keysTreeMap
Concurrent hash mapConcurrentHashMap
Legacy synchronized mapHashtable
Keys should be weakly referencedWeakHashMap
Identity (==) key comparisonIdentityHashMap
Enum keysEnumMap

HashMap vs LinkedHashMap vs TreeMap

FeatureHashMapLinkedHashMapTreeMap
OrderingNone guaranteedInsertion/access orderSorted keys
Typical getO(1) avgO(1) avgO(log n)
Typical putO(1) avgO(1) avgO(log n)
StructureHash tableHash table + linksRed-Black Tree
Null keyOne allowedOne allowedGenerally no
Duplicate keysNoNoNo

#Multiple Values per Key

Map Does Not Mean Duplicate Keys

Java
map.put("A", 10);
map.put("A", 20);

This doesn't produce A → 10 and A → 20. It produces A → 20. If you need multiple values per key, Map<String, List<Integer>> is a common design — e.g. Java → [10, 20, 30], Python → [40, 50].

Map of Lists Pattern

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

map.computeIfAbsent("Java", k -> new ArrayList<>()).add(10);
map.computeIfAbsent("Java", k -> new ArrayList<>()).add(20);

Result: Java → [10, 20]. This pattern appears frequently in real projects and coding interviews.

#Keys, Equality and Null

Map and equals() / hashCode()

For hash-based Maps such as HashMap, key lookup depends on hashing and equality:

hashCode()
bucket
equals()
matching key
This is why mutable keys can be dangerous

Mutable Key Problem

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

If Employee.hashCode() depends on employee.id and you change the ID after insertion (employee.id = 999;), the key's hash can change. Now the Map may be unable to find the entry using the mutated key.

Map and Null

Null behaviour differs by implementation:

MapNull keyNull value
HashMap✅ One✅ Yes
LinkedHashMap✅ One✅ Yes
TreeMap❌ Generally no (natural ordering)✅ Yes
Hashtable❌ No❌ No
ConcurrentHashMap❌ No❌ No
WeakHashMap✅ One✅ Yes
IdentityHashMap✅ One✅ Yes
EnumMap❌ No✅ Yes

The exact behaviour should always be considered implementation-specific.

#Interview Scenarios

Q1Fastest average lookup, no ordering
Java
Map<Integer, Employee> employees = new HashMap<>();
Q2Insertion order preserved
Java
Map<Integer, Employee> employees = new LinkedHashMap<>();
Q3Keys automatically sorted
Java
Map<Integer, Employee> employees = new TreeMap<>();
Q4Multiple threads access and update a Map
Java
Map<Integer, Employee> employees = new ConcurrentHashMap<>();

Don't simply use HashMap without external synchronization.

Q5Keys are enum values

Use EnumMap<MyEnum, String> rather than automatically defaulting to HashMap.

#Frequently Asked Interview Questions

Q1Is Map a Collection?

No. Map is a separate hierarchy.

Q2Can Map contain duplicate keys?

No. A key maps to at most one value at a time.

Q3Can Map contain duplicate values?

Yes.

Q4What happens when you put the same key twice?

The new value replaces the previous value.

Q5Difference between keySet() and entrySet()?
  • keySet() → keys only
  • entrySet() → key + value
Q6Why does values() return Collection rather than Set?

Because duplicate values are allowed.

Q7Why is entrySet() preferred when iterating keys and values?

It provides each key-value mapping directly without performing a separate lookup.

Q8Why is HashMap generally O(1)?

Hashing allows the implementation to locate the appropriate bucket directly on average.

Q9Why is TreeMap O(log n)?

It uses a balanced Red-Black Tree.

Q10HashMap vs LinkedHashMap?

HashMap has no ordering guarantee; LinkedHashMap maintains predictable iteration order.

Q11HashMap vs TreeMap?

HashMap uses hashing and provides O(1) average basic operations. TreeMap uses a balanced tree and provides sorted keys with O(log n) operations.

Q12HashMap vs ConcurrentHashMap?

HashMap is not thread-safe. ConcurrentHashMap is designed for concurrent access.

Q13Why can't ConcurrentHashMap store null?

Because null would create ambiguity between key absent and key mapped to null, and its concurrent APIs rely on this distinction.

Q14What is WeakHashMap?

A Map whose keys are weakly referenced, allowing entries to become eligible for garbage collection when keys are no longer strongly reachable elsewhere.

Q15What is IdentityHashMap?

A Map that uses reference identity (==) rather than normal object equality (equals()) for key comparison.

Q16Tricky: size and value after a duplicate key
Java
Map<String, Integer> map = new HashMap<>();

map.put("A", 10);
map.put("B", 20);
map.put("A", 30);

System.out.println(map.size());
System.out.println(map.get("A"));
Output
2
30

Because "A" is a duplicate key.

Q17Tricky: get() returns null twice
Java
Map<String, Integer> map = new HashMap<>();

map.put("A", null);

System.out.println(map.get("A"));
System.out.println(map.get("B"));

Both print null. To distinguish them: map.containsKey("A") returns true, while map.containsKey("B") returns false.

Q18Tricky: duplicate values
Java
Map<Integer, String> map = new HashMap<>();

map.put(1, "A");
map.put(2, "A");
map.put(3, "B");

map.size();   // 3

Duplicate values don't matter. Only duplicate keys are replaced.

#The Map Decision Framework

  • Map
    • Need fast lookup?HashMap
    • Need insertion order?LinkedHashMap
    • Need sorted keys?TreeMap
Common choices
Special requirementChoose
Concurrent accessConcurrentHashMap
Enum keysEnumMap
Weakly referenced keysWeakHashMap
Reference identity comparisonIdentityHashMap

Final Mental Model

  • MapKey → Value association
    • Keyunique
    • Valueduplicates OK
ViewGives
keySet()Keys
values()Values
entrySet()Key + Value

#Chapter Summary

ConceptKey Point
MapKey-value association
Extends Collection?❌ No
Duplicate keys❌ No
Duplicate values✅ Yes
put()Add/update mapping
get()Retrieve value
remove()Remove mapping
containsKey()Check key
containsValue()Check value
keySet()Key view
values()Value view
entrySet()Entry view
HashMapFast average lookup
LinkedHashMapPredictable order
TreeMapSorted keys
ConcurrentHashMapConcurrent access
WeakHashMapWeakly referenced keys
IdentityHashMap== key comparison
EnumMapEnum keys

Interview Readiness Checklist

  • Why Map is not a Collection
  • Why keys must be unique
  • Whether values can be duplicated
  • What happens when the same key is inserted twice
  • put() return value
  • get() vs containsKey()
  • keySet() vs values() vs entrySet()
  • Why entrySet() is preferred for key-value iteration
  • putIfAbsent(), computeIfAbsent(), compute(), merge()
  • HashMap vs LinkedHashMap vs TreeMap
  • HashMap vs ConcurrentHashMap
  • WeakHashMap, IdentityHashMap, EnumMap
  • Why mutable Map keys are dangerous
  • Null behaviour across Map implementations