← Back to Home

LinkedHashMap

LinkedHashMap is an implementation of the Map interface that maintains a predictable iteration order while still offering fast key-based access. It combines the performance of HashMap with order preservation using a linked list. This is a high-frequency interview topic, especially compared with HashMap and TreeMap.

What Is LinkedHashMap?

  • Implementation of Map
  • Stores key-value pairs
  • Maintains order (insertion or access order)
  • Allows one null key and multiple null values
  • Part of java.util package
Map<Integer, String> map = new LinkedHashMap<>();
          

Position in Map Hierarchy

Map
 └── HashMap
      └── LinkedHashMap
          

✔ LinkedHashMap extends HashMap

Key Characteristics of LinkedHashMap

  • Predictable iteration order
  • Slightly slower than HashMap
  • Faster than TreeMap
  • Not synchronized (not thread-safe)
  • Uses hashing + linked list

How LinkedHashMap Works Internally (Interview Favorite)

  • Backed by a HashMap
  • Maintains a doubly linked list of entries
  • Each entry has:
    • before reference
    • after reference

HashMap + Doubly Linked List = LinkedHashMap

✔ HashMap → fast lookup
✔ Linked list → order preservation

Order Types in LinkedHashMap

1️⃣ Insertion Order (Default)

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

map.put(1, "Java");
map.put(2, "Python");
map.put(3, "C++");
System.out.println(map);
          

Output:

{1=Java, 2=Python, 3=C++}
          

✔ Order of insertion preserved

2️⃣ Access Order (Very Important)

LinkedHashMap<Integer, String> map =
    new LinkedHashMap<>(16, 0.75f, true);

map.get(1);
          

✔ Recently accessed entries move to the end

✔ Used in LRU Cache

Commonly Used LinkedHashMap Methods

map.put(1, "Java");
map.get(1);
map.remove(2);
map.containsKey(1);
map.size();
          

✔ Same methods as HashMap

LRU Cache Using LinkedHashMap (Interview Favorite)

class LRUCache<K, V> extends LinkedHashMap<K, V> {
    private final int capacity;
    LRUCache(int capacity) {
        super(capacity, 0.75f, true);
        this.capacity = capacity;
    }
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return size() > capacity;
    }
}
          

✔ Real-world use case

✔ Frequently asked in interviews

Null Handling

map.put(null, "Java");   // allowed
map.put(1, null);       // allowed
          

✔ Same behavior as HashMap

Performance Complexity

Operation Time Complexity
put O(1) average
get O(1)
remove O(1)
iteration O(n)

⚠ Slight overhead due to linked list maintenance

LinkedHashMap vs HashMap vs TreeMap

Feature HashMap LinkedHashMap TreeMap
Order ❌ No ✔ Insertion / Access ✔ Sorted
Performance Fastest Slightly slower Slower
Null key ✔ One ✔ One ❌ No
Internal DS Hash table Hash table + list Red-Black Tree

When to Use LinkedHashMap

  • Order of insertion matters
  • Predictable iteration required
  • Implementing LRU cache
  • Fast lookup with ordering

When NOT to Use LinkedHashMap

  • Sorting is required (use TreeMap)
  • Order does not matter (use HashMap)
  • Memory usage must be minimal

Common Beginner Mistakes

  • Assuming sorted order
  • Ignoring access-order constructor
  • Using LinkedHashMap unnecessarily
  • Forgetting it is not thread-safe

Interview-Ready Answers

Short Answer

LinkedHashMap is a HashMap implementation that maintains insertion or access order.

Detailed Answer

In Java, LinkedHashMap extends HashMap and maintains a doubly linked list of entries, allowing predictable iteration order. It supports insertion-order and access-order modes and is commonly used to implement LRU caches while still providing constant-time performance.

Key Takeaway

LinkedHashMap = HashMap with order guarantee. Use it when you need fast lookups plus predictable iteration order.

LinkedHashMap Examples

1. Creating a LinkedHashMap

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
        map.put(1, "Java");
        map.put(2, "API");
        System.out.println(map);
    }
}
          

Output

{1=Java, 2=API}
          

2. Maintains Insertion Order

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
        map.put(3, "C");
        map.put(1, "A");
        map.put(2, "B");
        System.out.println(map);
    }
}
          

Output

{3=C, 1=A, 2=B}
          

3. Duplicate Key Overwrites Value (Order Preserved)

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
        map.put(1, "Java");
        map.put(1, "Selenium");
        System.out.println(map);
    }
}
          

Output

{1=Selenium}
          

4. Allows One null Key and Multiple null Values

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedHashMap<String, String> map = new LinkedHashMap<>();
        map.put(null, "A");
        map.put("X", null);
        map.put("Y", null);
        System.out.println(map);
    }
}
          

Output

{null=A, X=null, Y=null}
          

5. Iterating Using entrySet()

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
        map.put(1, "A");
        map.put(2, "B");

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

6. Iterating Using keySet()

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
        map.put(10, "X");
        map.put(20, "Y");

        for (Integer k : map.keySet()) {
            System.out.println(k);
        }
    }
}
          

7. Iterating Using values()

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
        map.put(1, "Java");
        map.put(2, "API");

        for (String v : map.values()) {
            System.out.println(v);
        }
    }
}
          

8. Difference Between HashMap and LinkedHashMap

import java.util.*;

class Demo {
    public static void main(String[] args) {
        Map<Integer, String> h = new HashMap<>();
        h.put(2, "B");
        h.put(1, "A");

        Map<Integer, String> l = new LinkedHashMap<>();
        l.put(2, "B");
        l.put(1, "A");

        System.out.println(h);
        System.out.println(l);
    }
}
          

Output

{1=A, 2=B}
{2=B, 1=A}
          

9. Access-Order LinkedHashMap

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedHashMap<Integer, String> map =
            new LinkedHashMap<>(16, 0.75f, true);

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

        map.get(1);
        map.get(2);

        System.out.println(map);
    }
}
          

Output

{3=C, 1=A, 2=B}
          

Explanation

Order changes based on access.

10. LinkedHashMap as LRU Cache (Very Important)

import java.util.*;

class LRUCache extends LinkedHashMap<Integer, String> {
    private final int capacity;

    LRUCache(int capacity) {
        super(capacity, 0.75f, true);
        this.capacity = capacity;
    }

    protected boolean removeEldestEntry(Map.Entry<Integer, String> eldest) {
        return size() > capacity;
    }

    public static void main(String[] args) {
        LRUCache cache = new LRUCache(2);
        cache.put(1, "A");
        cache.put(2, "B");
        cache.get(1);
        cache.put(3, "C");
        System.out.println(cache);
    }
}
          

Output

{1=A, 3=C}
          

11. putIfAbsent() with LinkedHashMap

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
        map.put(1, "Java");
        map.putIfAbsent(1, "API");
        map.putIfAbsent(2, "API");
        System.out.println(map);
    }
}
          

Output

{1=Java, 2=API}
          

12. replace() Method

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
        map.put(1, "Java");
        map.replace(1, "Selenium");
        System.out.println(map);
    }
}
          

13. Conditional remove()

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
        map.put(1, "Java");
        map.remove(1, "API");   // no effect
        map.remove(1, "Java");  // removed
        System.out.println(map);
    }
}
          

14. Custom Object as Key (equals & hashCode Required)

class User {
    int id;
    User(int id) { this.id = id; }

    public boolean equals(Object o) {
        return this.id == ((User)o).id;
    }

    public int hashCode() {
        return id;
    }
}

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedHashMap<User, String> map = new LinkedHashMap<>();
        map.put(new User(1), "Admin");
        map.put(new User(1), "Admin");
        System.out.println(map.size());
    }
}
          

Output

1
          

15. LinkedHashMap Is Not Thread-Safe

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedHashMap<String, String> map = new LinkedHashMap<>();
        map.put("A", "Not Thread Safe");
        System.out.println(map);
    }
}
          

16. Thread-Safe LinkedHashMap

import java.util.*;

class Demo {
    public static void main(String[] args) {
        Map<String, String> map =
            Collections.synchronizedMap(new LinkedHashMap<>());
        map.put("A", "Safe");
        System.out.println(map);
    }
}
          

17. Converting HashMap to LinkedHashMap

import java.util.*;

class Demo {
    public static void main(String[] args) {
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(2, "B");
        hashMap.put(1, "A");

        LinkedHashMap<Integer, String> linked =
            new LinkedHashMap<>(hashMap);

        System.out.println(linked);
    }
}
          

18. LinkedHashMap Size & Empty Check

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
        System.out.println(map.isEmpty());
        map.put(1, "Java");
        System.out.println(map.size());
    }
}
          

Output

true
1
          

19. Performance Note (Concept)

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

Explanation

  • Slightly slower than HashMap
  • Extra memory for doubly-linked list
  • Predictable iteration order

20. Interview Summary – LinkedHashMap

import java.util.*;

class Demo {
    public static void main(String[] args) {
        LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
        map.put(1, "Ordered");
        map.put(2, "KeyValue");
        System.out.println(map);
    }
}
          

Key Points

  • Maintains insertion or access order
  • Allows one null key
  • Backed by HashMap + Linked List
  • Used for LRU cache
  • Not thread-safe by default