Java Map Interface
A complete guide to the Java Map interface β key-value pair storage, HashMap, LinkedHashMap, TreeMap, all Map methods, 5 iteration techniques, sorting by key and value, Java 8+ Map APIs, nested maps, and best practices with real-world examples.
Last Updated
March 2026
Read Time
19 min
Level
Beginner to Intermediate
What is the Java Map Interface?
The Map interface in Java (java.util.Map<K, V>) represents a collection of key-value pairs where every key is unique and maps to exactly one value. It is one of the most important and widely used data structures in Java β the foundation of lookup tables, caches, configuration stores, and frequency counters across virtually every Java application.
Unlike List and Set, Map does NOT extend the Collection interface. It exists as a separate hierarchy because it does not hold individual elements β it holds associations (pairs). Think of a Map as a real-world dictionary: each word (key) maps to its definition (value). You look up a word instantly β you do not scan from page 1 every time.
Java provides several Map implementations, each with different ordering and performance characteristics: HashMap (fastest, no order), LinkedHashMap (insertion order), TreeMap (sorted by key), and Hashtable (legacy, thread-safe). Choosing the right implementation depends on whether you need ordering and whether thread safety is required.
Map Syntax and Implementations
Always declare a Map variable using the Map<K, V> interface type (program to interface), and choose the appropriate implementation on the right side.
import java.util.*;
// HashMap β fastest, no guaranteed order
Map<String, Integer> hashMap = new HashMap<>();
// LinkedHashMap β maintains insertion order
Map<String, Integer> linkedHashMap = new LinkedHashMap<>();
// TreeMap β sorted by key (natural order or custom Comparator)
Map<String, Integer> treeMap = new TreeMap<>();
// Hashtable β legacy, thread-safe (avoid in new code)
Map<String, Integer> hashtable = new Hashtable<>();
// Java 9+ β immutable Map of up to 10 entries
Map<String, Integer> immutable = Map.of("Java", 1, "Python", 2, "Kotlin", 3);
// Java 9+ β immutable Map via Map.ofEntries (for more entries)
Map<String, Integer> large = Map.ofEntries(
Map.entry("One", 1),
Map.entry("Two", 2),
Map.entry("Three", 3)
);import java.util.*;
public class MapIntro {
public static void main(String[] args) {
Map<String, Integer> scores = new HashMap<>();
// Put key-value pairs
scores.put("Arjun", 88);
scores.put("Priya", 95);
scores.put("Rohan", 72);
scores.put("Sneha", 89);
scores.put("Arjun", 91); // duplicate key β overwrites 88
System.out.println("Map : " + scores);
System.out.println("Size : " + scores.size());
System.out.println("Arjun : " + scores.get("Arjun"));
System.out.println("Has Priya? " + scores.containsKey("Priya"));
System.out.println("Has 72? " + scores.containsValue(72));
System.out.println("Keys : " + scores.keySet());
System.out.println("Values : " + scores.values());
}
}Output
Map : {Rohan=72, Priya=95, Sneha=89, Arjun=91} Size : 4 Arjun : 91 Has Priya? true Has 72? true Keys : [Rohan, Priya, Sneha, Arjun] Values : [72, 95, 89, 91]Why Use the Map Interface?
Map is the right data structure whenever you need to associate one piece of data with another and retrieve it instantly. Here is why Map is indispensable in Java development:
- βΆ
β‘ O(1) Average Lookup β HashMap's get(key) and put(key, value) operate in O(1) average time via hashing. This makes Maps the fastest possible structure for key-based retrieval β essential for caches, lookup tables, and configuration stores.
- βΆ
π Unique Key Guarantee β Maps enforce key uniqueness automatically. Adding a duplicate key silently replaces the existing value. This makes Maps ideal for frequency counting, deduplication, and ID-to-object indexing without extra uniqueness checks.
- βΆ
πΊοΈ Natural Modeling of Real-World Relationships β Phone books (name β number), dictionaries (word β definition), database rows (id β record), HTTP headers (header-name β header-value) β all are naturally key-value relationships that Map models directly.
- βΆ
π Flexible Iteration β Maps offer keySet(), values(), and entrySet() views, enabling you to iterate just keys, just values, or both simultaneously β covering all traversal patterns.
- βΆ
𧬠Type-Safe via Generics β Map<String, Integer> guarantees both keys and values are type-checked at compile time. No ClassCastException surprises at runtime.
- βΆ
ποΈ Rich Java 8+ Functional API β getOrDefault(), putIfAbsent(), computeIfAbsent(), merge(), forEach(), and replaceAll() transform Map from a simple lookup table into a powerful functional data container that eliminates boilerplate null-checking and conditional update logic.
HashMap vs LinkedHashMap vs TreeMap vs Hashtable
Choosing the right Map implementation is critical for correctness and performance. Here is the definitive comparison of all four major Map implementations:
Decision guide: Use HashMap by default. Use LinkedHashMap when insertion or access order matters (e.g., LRU cache). Use TreeMap when keys must be sorted or you need range operations (firstKey, lastKey, subMap, headMap, tailMap). Never use Hashtable in new code β use ConcurrentHashMap for thread safety instead.
Map in the Java Collections Hierarchy
The Map interface is a separate hierarchy from Collection. Understanding this hierarchy clarifies which methods each implementation provides and why.
Key insight: TreeMap implements NavigableMap which gives it powerful range-query methods like floorKey(), ceilingKey(), subMap(), headMap(), and tailMap() β unique capabilities that HashMap and LinkedHashMap do not have.
Important Map Methods
The Map interface defines a rich set of methods. Java 8 added powerful functional methods that eliminate most manual null-checking and conditional put patterns.
CRUD Operations on Map
Let's walk through every essential Map operation β Create, Read, Update, and Delete β with a comprehensive demonstration covering edge cases like missing keys, overwriting, and bulk operations.
import java.util.*;
public class MapCRUD {
public static void main(String[] args) {
Map<String, Integer> population = new HashMap<>();
// ---- CREATE ----
population.put("Mumbai", 20_667_656);
population.put("Delhi", 32_941_308);
population.put("Bengaluru", 8_443_675);
population.put("Chennai", 7_088_000);
population.put("Hyderabad", 6_809_970);
population.putIfAbsent("Delhi", 999); // ignored β key exists
population.putIfAbsent("Kolkata", 4_631_392); // added
System.out.println("After CREATE: " + population.size() + " cities");
// ---- READ ----
System.out.println("Delhi pop : " + population.get("Delhi"));
System.out.println("Pune pop : " + population.get("Pune")); // null
System.out.println("Pune (def) : " + population.getOrDefault("Pune", 0));
System.out.println("Has Mumbai?: " + population.containsKey("Mumbai"));
System.out.println("All keys : " + population.keySet());
// ---- UPDATE ----
population.put("Chennai", 7_200_000); // overwrite
population.replace("Hyderabad", 7_100_000); // replace only if exists
System.out.println("Updated Chennai: " + population.get("Chennai"));
// ---- DELETE ----
population.remove("Bengaluru");
population.remove("Kolkata", 999); // not removed β value mismatch
System.out.println("After DELETE: " + population.size() + " cities");
System.out.println("Kolkata still exists: " + population.containsKey("Kolkata"));
System.out.println("Final map: " + population);
}
}Output
After CREATE: 6 cities Delhi pop : 32941308 Pune pop : null Pune (def) : 0 Has Mumbai?: true All keys : [Hyderabad, Kolkata, Chennai, Delhi, Mumbai, Bengaluru] Updated Chennai: 7200000 After DELETE: 5 cities Kolkata still exists: true Final map: {Hyderabad=7100000, Kolkata=4631392, Chennai=7200000, Delhi=32941308, Mumbai=20667656}Iterating a Map β 5 Ways
Unlike List, you cannot iterate a Map directly in a single for-each. You iterate over one of its three views β keySet(), values(), or entrySet() β or use Java 8+ functional methods.
import java.util.*;
public class MapIteration {
public static void main(String[] args) {
Map<String, Integer> marks = new LinkedHashMap<>();
marks.put("Maths", 92);
marks.put("Science", 88);
marks.put("English", 79);
marks.put("History", 84);
// 1. keySet() β iterate over keys only
System.out.println("1. keySet():");
for (String subject : marks.keySet()) {
System.out.println(" " + subject + " -> " + marks.get(subject));
}
// 2. values() β iterate over values only
System.out.println("2. values():");
int total = 0;
for (int score : marks.values()) {
total += score;
}
System.out.println(" Total marks: " + total);
// 3. entrySet() β most efficient: both key and value together
System.out.println("3. entrySet() (recommended):");
for (Map.Entry<String, Integer> entry : marks.entrySet()) {
System.out.println(" " + entry.getKey() + " = " + entry.getValue());
}
// 4. Iterator on entrySet β for safe removal during traversal
System.out.println("4. Iterator (removes History):");
Iterator<Map.Entry<String, Integer>> it = marks.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, Integer> e = it.next();
if (e.getKey().equals("History")) it.remove();
else System.out.println(" " + e.getKey() + " = " + e.getValue());
}
// 5. forEach lambda (Java 8+) β cleanest syntax
System.out.println("5. forEach lambda:");
marks.forEach((subject, score) ->
System.out.println(" " + subject + ": " + score + "%"));
}
}Output
1. keySet(): Maths -> 92 Science -> 88 English -> 79 History -> 84 2. values(): Total marks: 343 3. entrySet() (recommended): Maths = 92 Science = 88 English = 79 History = 84 4. Iterator (removes History): Maths = 92 Science = 88 English = 79 5. forEach lambda: Maths: 92% Science: 88% English: 79%Sorting a Map by Key and Value
HashMap does not maintain any order. To sort a Map, either use TreeMap (sorts by key automatically) or sort the entrySet() using Java 8 Stream API for custom sort orders.
import java.util.*;
import java.util.stream.*;
public class MapSorting {
public static void main(String[] args) {
Map<String, Integer> wordCount = new HashMap<>();
wordCount.put("java", 45);
wordCount.put("python", 30);
wordCount.put("kotlin", 20);
wordCount.put("scala", 15);
wordCount.put("groovy", 8);
// --- Sort by KEY ascending (TreeMap) ---
Map<String, Integer> sortedByKey = new TreeMap<>(wordCount);
System.out.println("Sorted by Key (asc): " + sortedByKey);
// --- Sort by KEY descending ---
Map<String, Integer> keyDesc = new TreeMap<>(Comparator.reverseOrder());
keyDesc.putAll(wordCount);
System.out.println("Sorted by Key (desc): " + keyDesc);
// --- Sort by VALUE ascending (Stream) ---
System.out.println("Sorted by Value (asc):");
wordCount.entrySet().stream()
.sorted(Map.Entry.comparingByValue())
.forEach(e -> System.out.println(" " + e.getKey() + " = " + e.getValue()));
// --- Sort by VALUE descending (Stream) ---
System.out.println("Sorted by Value (desc):");
wordCount.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
.forEach(e -> System.out.println(" " + e.getKey() + " = " + e.getValue()));
// --- Collect sorted result into LinkedHashMap (preserves order) ---
Map<String, Integer> sortedMap = wordCount.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e1,
LinkedHashMap::new
));
System.out.println("Collected sorted map: " + sortedMap);
}
}Output
Sorted by Key (asc): {groovy=8, java=45, kotlin=20, python=30, scala=15} Sorted by Key (desc): {scala=15, python=30, kotlin=20, java=45, groovy=8} Sorted by Value (asc): groovy = 8 scala = 15 kotlin = 20 python = 30 java = 45 Sorted by Value (desc): java = 45 python = 30 kotlin = 20 scala = 15 groovy = 8 Collected sorted map: {java=45, python=30, kotlin=20, scala=15, groovy=8}HashMap Internal Working β How put() Works
Understanding how HashMap.put(key, value) works internally explains why keys must implement hashCode() and equals(), and why HashMap achieves O(1) average performance.
Code Execution Flow β from source to output
Key internals: HashMap uses an array of buckets (default 16). Each bucket holds a linked list. In Java 8+, when a bucket's chain exceeds 8 nodes, it converts to a Red-Black Tree β improving worst-case lookup from O(n) to O(log n). When elements exceed capacity Γ loadFactor (default 0.75), the HashMap rehashes (doubles capacity). This is why hashCode() and equals() must be correctly implemented in any class used as a Map key.
Java 8+ Map Methods β The Powerful Functional API
Java 8 added a suite of functional Map methods that dramatically simplify common patterns β frequency counting, conditional updates, and value merging β replacing verbose if-else blocks with single expressive calls.
import java.util.*;
public class Java8MapMethods {
public static void main(String[] args) {
// --- getOrDefault ---
Map<String, Integer> config = new HashMap<>();
config.put("timeout", 30);
System.out.println(config.getOrDefault("timeout", 60)); // 30
System.out.println(config.getOrDefault("retries", 3)); // 3 (default)
// --- putIfAbsent ---
config.putIfAbsent("timeout", 999); // ignored β already set
config.putIfAbsent("retries", 3); // added
System.out.println("Config: " + config);
// --- computeIfAbsent β frequency counter pattern ---
Map<String, Integer> freq = new HashMap<>();
String[] words = {"java", "python", "java", "kotlin", "java", "python"};
for (String w : words) {
freq.merge(w, 1, Integer::sum); // cleanest frequency counter
}
System.out.println("Word freq: " + freq);
// --- computeIfAbsent β grouping pattern ---
Map<Integer, List<String>> byLength = new HashMap<>();
String[] names = {"Amit", "Priya", "Rohan", "Dev", "Sneha", "Jo"};
for (String name : names) {
byLength.computeIfAbsent(name.length(), k -> new ArrayList<>()).add(name);
}
System.out.println("By length: " + byLength);
// --- replaceAll ---
Map<String, Integer> prices = new HashMap<>();
prices.put("Apple", 100);
prices.put("Banana", 40);
prices.put("Mango", 120);
prices.replaceAll((item, price) -> (int)(price * 1.10)); // 10% price hike
System.out.println("After 10% hike: " + prices);
// --- merge β combine two maps ---
Map<String, Integer> shopA = new HashMap<>(Map.of("Apple", 50, "Banana", 30));
Map<String, Integer> shopB = new HashMap<>(Map.of("Apple", 20, "Mango", 40));
shopB.forEach((k, v) -> shopA.merge(k, v, Integer::sum));
System.out.println("Combined stock: " + shopA);
}
}Output
30 3 Config: {timeout=30, retries=3} Word freq: {java=3, python=2, kotlin=1} By length: {2=[Jo], 3=[Dev], 4=[Amit, Rohan], 5=[Priya, Sneha]} After 10% hike: {Apple=110, Banana=44, Mango=132} Combined stock: {Apple=70, Banana=30, Mango=40}Nested Map β Map of Maps
A nested Map (Map<K, Map<K2, V>>) is used to model multi-dimensional key-value data β such as a student's scores across multiple subjects, a city's statistics across multiple years, or a role-permission matrix.
import java.util.*;
public class NestedMapDemo {
public static void main(String[] args) {
// Map<StudentName, Map<Subject, Score>>
Map<String, Map<String, Integer>> reportCard = new HashMap<>();
// Add Arjun's scores
Map<String, Integer> arjunScores = new LinkedHashMap<>();
arjunScores.put("Maths", 92);
arjunScores.put("Science", 88);
arjunScores.put("English", 76);
reportCard.put("Arjun", arjunScores);
// Add Priya's scores using computeIfAbsent
reportCard.computeIfAbsent("Priya", k -> new LinkedHashMap<>()).put("Maths", 95);
reportCard.computeIfAbsent("Priya", k -> new LinkedHashMap<>()).put("Science", 91);
reportCard.computeIfAbsent("Priya", k -> new LinkedHashMap<>()).put("English", 83);
// Print full report card
System.out.println("=== Report Card ===");
reportCard.forEach((student, subjects) -> {
System.out.println("\n" + student + ":");
subjects.forEach((subject, score) ->
System.out.printf(" %-10s: %d%n", subject, score));
int avg = subjects.values().stream()
.mapToInt(Integer::intValue).sum() / subjects.size();
System.out.println(" Average : " + avg);
});
// Access specific cell
int priyaMaths = reportCard.get("Priya").getOrDefault("Maths", 0);
System.out.println("\nPriya's Maths score: " + priyaMaths);
}
}Output
=== Report Card === Arjun: Maths : 92 Science : 88 English : 76 Average : 85 Priya: Maths : 95 Science : 91 English : 83 Average : 89 Priya's Maths score: 95Best Practices for Using Map
Professional Java developers follow these Map best practices to write correct, efficient, and maintainable code:
- βΆ
β 1. Program to the Map Interface β Always declare as Map<K,V> map = new HashMap<>(), not as HashMap<K,V> map = new HashMap<>(). This decouples your code from the concrete implementation β swap to TreeMap or LinkedHashMap with one-line change.
- βΆ
β 2. Use entrySet() for Iteration β Never keySet() + get() β Iterating with keySet() and calling get(key) inside the loop performs two map lookups per entry. entrySet() iteration retrieves key and value in a single step β it is always faster and cleaner.
- βΆ
β 3. Set Initial Capacity for Large Maps β If you know approximately N entries will be added, construct with new HashMap<>(N * 4 / 3 + 1) to avoid rehashing. Rehashing is O(n) and expensive for large maps.
- βΆ
β 4. Implement hashCode() and equals() Correctly for Custom Keys β HashMap correctness depends entirely on hashCode() and equals() being consistent and correct on key objects. Never use mutable fields in hashCode() of a Map key β if the key's hashCode changes after insertion, the entry becomes permanently unretrievable.
- βΆ
β 5. Use getOrDefault() and computeIfAbsent() β Avoid Manual Null Checks β Replace if (map.get(key) == null) { map.put(key, new ArrayList<>()); } map.get(key).add(item); with the clean one-liner: map.computeIfAbsent(key, k -> new ArrayList<>()).add(item);.
- βΆ
β 6. Use merge() for Frequency Counting and Accumulation β Replace the three-line if-present-else-put pattern with map.merge(key, 1, Integer::sum). This is the idiomatic Java 8+ way to count or accumulate values.
- βΆ
β 7. Use Map.of() for Immutable Constant Maps β For maps of known constants (HTTP status codes, country codes, config defaults), Java 9+ Map.of() creates a compact, immutable, null-hostile map that communicates intent clearly and prevents accidental modification.
- βΆ
β 8. Never Use Hashtable in New Code β Hashtable is fully synchronized (slow), rejects nulls entirely, and is a relic from Java 1.0. Use ConcurrentHashMap for thread-safe maps β it has segment-level locking (far faster than Hashtable's method-level locking) and supports the Java 8+ functional API.
import java.util.*;
public class MapBestPractices {
public static void main(String[] args) {
String[] fruits = {"apple","banana","apple","mango","banana","apple"};
// β Verbose anti-pattern
Map<String, Integer> badCount = new HashMap<>();
for (String f : fruits) {
if (badCount.containsKey(f)) {
badCount.put(f, badCount.get(f) + 1);
} else {
badCount.put(f, 1);
}
}
System.out.println("Verbose : " + badCount);
// β
getOrDefault pattern (Java 8+)
Map<String, Integer> count1 = new HashMap<>();
for (String f : fruits)
count1.put(f, count1.getOrDefault(f, 0) + 1);
System.out.println("getOrDefault: " + count1);
// β
merge β cleanest (Java 8+)
Map<String, Integer> count2 = new HashMap<>();
for (String f : fruits)
count2.merge(f, 1, Integer::sum);
System.out.println("merge : " + count2);
// β
entrySet iteration vs keySet iteration
System.out.println("\nentrySet (efficient):");
for (Map.Entry<String, Integer> e : count2.entrySet())
System.out.println(" " + e.getKey() + " -> " + e.getValue());
}
}Output
Verbose : {apple=3, banana=2, mango=1} getOrDefault: {apple=3, banana=2, mango=1} merge : {apple=3, banana=2, mango=1} entrySet (efficient): apple -> 3 banana -> 2 mango -> 1Real-World Code Examples
Example 1 β Employee Directory with HashMap
import java.util.*;
import java.util.stream.*;
class Employee {
int id;
String name;
String dept;
double salary;
Employee(int id, String name, String dept, double salary) {
this.id = id; this.name = name;
this.dept = dept; this.salary = salary;
}
@Override public String toString() {
return name + "(" + dept + ", βΉ" + salary + ")";
}
}
public class EmployeeDirectory {
public static void main(String[] args) {
Map<Integer, Employee> directory = new HashMap<>();
directory.put(101, new Employee(101, "Arjun", "Engineering", 85000));
directory.put(102, new Employee(102, "Priya", "Marketing", 72000));
directory.put(103, new Employee(103, "Rohan", "Engineering", 91000));
directory.put(104, new Employee(104, "Sneha", "HR", 68000));
directory.put(105, new Employee(105, "Vikram", "Engineering", 78000));
// Lookup by ID β O(1)
System.out.println("Employee 103: " + directory.get(103));
// Group by department
Map<String, List<Employee>> byDept = new HashMap<>();
directory.values().forEach(e ->
byDept.computeIfAbsent(e.dept, k -> new ArrayList<>()).add(e));
System.out.println("\nBy Department:");
byDept.forEach((dept, emps) -> System.out.println(" " + dept + ": " + emps));
// Average salary by department
System.out.println("\nAvg Salary:");
byDept.forEach((dept, emps) -> {
double avg = emps.stream().mapToDouble(e -> e.salary).average().orElse(0);
System.out.printf(" %-15s: βΉ%.0f%n", dept, avg);
});
// Highest paid employee
Employee top = directory.values().stream()
.max(Comparator.comparingDouble(e -> e.salary)).orElseThrow();
System.out.println("\nHighest paid: " + top);
}
}Output
Employee 103: Rohan(Engineering, βΉ91000.0) By Department: Marketing: [Priya(Marketing, βΉ72000.0)] Engineering: [Arjun(Engineering, βΉ85000.0), Rohan(Engineering, βΉ91000.0), Vikram(Engineering, βΉ78000.0)] HR: [Sneha(HR, βΉ68000.0)] Avg Salary: Marketing : βΉ72000 Engineering : βΉ84667 HR : βΉ68000 Highest paid: Rohan(Engineering, βΉ91000.0)Example 2 β TreeMap for Leaderboard (Sorted Scores)
import java.util.*;
public class Leaderboard {
public static void main(String[] args) {
// TreeMap sorted by score descending (reverse order)
TreeMap<Integer, String> board =
new TreeMap<>(Comparator.reverseOrder());
board.put(88, "Arjun");
board.put(95, "Priya");
board.put(72, "Rohan");
board.put(89, "Sneha");
board.put(100, "Vikram");
board.put(65, "Aisha");
System.out.println("=== Leaderboard ===");
int rank = 1;
for (Map.Entry<Integer, String> e : board.entrySet()) {
System.out.printf("#%d %-10s %d pts%n", rank++, e.getValue(), e.getKey());
}
// NavigableMap operations
System.out.println("\nTop scorer : " + board.firstEntry());
System.out.println("Scores > 85: " + board.headMap(85, false));
System.out.println("Floor of 90: " + board.floorKey(90));
System.out.println("Ceiling of 90: " + board.ceilingKey(90));
}
}Output
=== Leaderboard === #1 Vikram 100 pts #2 Priya 95 pts #3 Sneha 89 pts #4 Arjun 88 pts #5 Rohan 72 pts #6 Aisha 65 pts Top scorer : 100=Vikram Scores > 85: {100=Vikram, 95=Priya, 89=Sneha, 88=Arjun} Floor of 90: 89 Ceiling of 90: 95Practice This Code β Live Editor
Advantages and Disadvantages of Map
Map is indispensable for key-value data, but understanding its trade-offs helps you pick the right implementation and use it correctly.
Java Map β Interview Questions
These are the most frequently asked interview questions on the Java Map interface and its implementations for Java developer and backend engineer positions.
Practice Questions β Test Your Knowledge
Test your understanding of the Map interface with these practice questions. Attempt each before revealing the answer.
1. What is the output? Map<String,Integer> m = new HashMap<>(); m.put("A", 1); m.put("B", 2); m.put("A", 3); System.out.println(m.size() + " " + m.get("A"));
Easy2. What is the output? Map<String,Integer> m = new LinkedHashMap<>(); m.put("Banana",2); m.put("Apple",1); m.put("Mango",3); m.forEach((k,v) -> System.out.print(k + " "));
Easy3. You have Map<String,List<String>> groupMap. How do you add "Java" to the list at key "Languages" without checking if the key exists, in one line?
Medium4. What is the time complexity of: (a) HashMap.get(key), (b) TreeMap.get(key), (c) HashMap.containsValue(v), (d) TreeMap.subMap(k1, k2)?
Medium5. Why does this code produce wrong results in a multi-threaded scenario even with synchronized methods? Map<String,Integer> map = new HashMap<>(); // Thread 1 and Thread 2 both running: int v = map.getOrDefault(key, 0); map.put(key, v + 1);
Hard6. What is the output? TreeMap<Integer,String> tm = new TreeMap<>(); tm.put(5,"E"); tm.put(1,"A"); tm.put(3,"C"); tm.put(7,"G"); System.out.println(tm.subMap(2, 6));
Medium7. You need an LRU (Least Recently Used) cache with max capacity 3. How do you implement it using LinkedHashMap?
Hard8. You have a List<String> words. Count the frequency of each word and print the top 3 most frequent words using Map and Stream. Write the code.
HardConclusion β Mastering Java Map
The Map interface is the beating heart of Java data processing. Virtually every non-trivial Java application uses Maps for caching, configuration, frequency analysis, grouping, indexing, or lookup β making Map fluency a core Java developer skill rather than an optional advanced topic.
Mastering Map means knowing when to reach for HashMap (default fast lookup), LinkedHashMap (ordered iteration, LRU caches), TreeMap (sorted keys, range queries), and ConcurrentHashMap (thread-safe concurrent access). It also means internalizing the Java 8+ functional API β getOrDefault, computeIfAbsent, merge, forEach β which transforms verbose, error-prone map manipulation into clean, expressive one-liners.
Your next steps: deep-dive into ConcurrentHashMap internals (bucket-level CAS locking), study Java 21's Sequenced Collections (which adds first/last entry access to LinkedHashMap via the SequencedMap interface), explore Collectors.groupingBy for Stream-based map building, and understand how Spring's @Cacheable and Caffeine/Guava caches build on these Map fundamentals for production-grade caching.
Remember: Declare as Map, iterate with entrySet(), count with merge(), group with computeIfAbsent(), and always implement hashCode() + equals() on custom keys. These five habits will keep your Map code correct, efficient, and production-ready. β