The LinkedHashMap class in Java is a part of the Java Collections Framework and extends HashMap while maintaining the insertion order of elements. It is useful when you need a key-value mapping with predictable iteration order.
In this tutorial, we will cover:
1. Understanding LinkedHashMap
Key Features:
✔ Maintains insertion order of elements
✔ Allows one null key and multiple null values
✔ Not synchronized (use Collections.synchronizedMap() for thread safety)
✔ Provides constant-time performance for insertions and lookups
Class Declaration:
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
2. Creating and Initializing a LinkedHashMap
You can create a LinkedHashMap using different constructors.
Example: Creating a Simple LinkedHashMap
import java.util.LinkedHashMap; import java.util.Map; public class LinkedHashMapExample { public static void main(String[] args) { // Creating a LinkedHashMap with default capacity LinkedHashMap<Integer, String> map = new LinkedHashMap<>(); // Adding elements map.put(1, "Apple"); map.put(2, "Banana"); map.put(3, "Cherry"); System.out.println("LinkedHashMap: " + map); } }
Output:
LinkedHashMap: {1=Apple, 2=Banana, 3=Cherry}
Example: Creating a LinkedHashMap with Initial Capacity
LinkedHashMap<Integer, String> map = new LinkedHashMap<>(16, 0.75f);
- 16: Initial capacity
- 0.75f: Load factor (default: 0.75)
3. Accessing and Modifying Elements
You can access, update, and modify elements using standard Map methods.
Example: Get, Replace, and Modify Elements
import java.util.LinkedHashMap; public class LinkedHashMapDemo { public static void main(String[] args) { LinkedHashMap<String, Integer> scores = new LinkedHashMap<>(); // Adding elements scores.put("Alice", 85); scores.put("Bob", 92); scores.put("Charlie", 78); // Accessing a value System.out.println("Bob's Score: " + scores.get("Bob")); // Updating a value scores.put("Alice", 90); System.out.println("Updated Scores: " + scores); } }
Output:
Bob's Score: 92 Updated Scores: {Alice=90, Bob=92, Charlie=78}
4. Iterating Over a LinkedHashMap
You can iterate over keys, values, or entries using different approaches.
Example: Iterating Using a forEach Loop
import java.util.LinkedHashMap; import java.util.Map; public class IterateLinkedHashMap { public static void main(String[] args) { LinkedHashMap<Integer, String> map = new LinkedHashMap<>(); map.put(101, "Java"); map.put(102, "Python"); map.put(103, "JavaScript"); // Iterating using forEach for (Map.Entry<Integer, String> entry : map.entrySet()) { System.out.println(entry.getKey() + " -> " + entry.getValue()); } } }
Output:
101 -> Java 102 -> Python 103 -> JavaScript
Example: Iterating Using Java 8 forEach
map.forEach((key, value) -> System.out.println(key + " -> " + value));
5. Maintaining Access Order for Caching
By default, LinkedHashMap maintains insertion order. However, you can configure it to maintain access order by setting the accessOrder flag to true.
Example: Creating an LRU Cache Using LinkedHashMap
import java.util.LinkedHashMap; import java.util.Map; public class LRUCache<K, V> extends LinkedHashMap<K, V> { private final int maxSize; public LRUCache(int maxSize) { super(maxSize, 0.75f, true); // Access-order enabled this.maxSize = maxSize; } @Override protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { return size() > maxSize; // Remove oldest entry when size exceeds maxSize } public static void main(String[] args) { LRUCache<Integer, String> cache = new LRUCache<>(3); cache.put(1, "A"); cache.put(2, "B"); cache.put(3, "C"); // Access key 1 (moves it to the end) cache.get(1); // Insert a new element (removes least recently used entry, which is key 2) cache.put(4, "D"); System.out.println("LRU Cache: " + cache); } }
Output:
LRU Cache: {3=C, 1=A, 4=D}
In this example, the least recently used element is automatically removed when a new entry is added beyond capacity.
6. Removing Elements
Example: Removing Entries
map.remove(102); // Removes entry with key 102 map.clear(); // Removes all entries
7. Checking for Keys and Values
Example: Check Existence of Keys and Values
System.out.println(map.containsKey(101)); // true System.out.println(map.containsValue("Python")); // false
8. Using LinkedHashMap with Generics
You can use LinkedHashMap with custom objects as keys and values.
Example: Using Custom Class as Key
import java.util.LinkedHashMap; import java.util.Objects; class Student { String name; int id; public Student(int id, String name) { this.id = id; this.name = name; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Student)) return false; Student student = (Student) o; return id == student.id && Objects.equals(name, student.name); } @Override public int hashCode() { return Objects.hash(id, name); } } public class CustomLinkedHashMap { public static void main(String[] args) { LinkedHashMap<Student, Integer> studentScores = new LinkedHashMap<>(); studentScores.put(new Student(1, "Alice"), 85); studentScores.put(new Student(2, "Bob"), 90); studentScores.forEach((student, score) -> System.out.println(student.name + "'s Score: " + score)); } }
9. Comparing LinkedHashMap vs HashMap vs TreeMap
Feature | HashMap | LinkedHashMap | TreeMap |
---|---|---|---|
Ordering | Unordered | Insertion Order | Sorted Order |
Performance | Fastest | Slightly Slower | Slower (Sorted) |
Use Case | General Purpose | Ordered Data | Sorted Data |
Conclusion
- LinkedHashMap is useful when ordering of keys matters.
- It provides O(1) time complexity for get() and put() operations.
- It can be used for caching (LRU implementations).
- It maintains either insertion order or access order (if configured).
By leveraging LinkedHashMap, you can efficiently manage ordered key-value mappings while ensuring predictable iteration order.