The LinkedHashMap class in Java is an implementation of the Map interface that stores key-value pairs in a doubly-linked list, thus preserving the insertion order of the map entries. It’s part of the Java Collections Framework and can be found in the java.util package.

Key Points

Below are some important points about Java LinkedHashMap:

Ordering: Unlike HashMap, LinkedHashMap maintains the order in which keys were inserted into the map (insertion order).

Null Keys and Values: Similar to HashMap, LinkedHashMap allows one null key and multiple null values.

Not Synchronized: LinkedHashMap is not synchronized, which means it’s not thread-safe. If multiple threads access a linked hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally.

Performance: The performance of LinkedHashMap can be slightly lower than HashMap due to the overhead of maintaining the linked list. But the difference is usually negligible unless you’re dealing with very large numbers of entries.

Usage: LinkedHashMap is useful in situations where you need a Map that also maintains its elements in order. This is particularly useful when you want to iterate over the keys or values of the map in a specific order that matches the order you added the elements.

1. Create a LinkedHashMap and Add New Elements

import java.util.LinkedHashMap;
import java.util.Map;

public class LinkedHashMapExample {

    public static void main(String[] args) {
        // Step 1: Create and initialize a LinkedHashMap with Fruit Name (String) and Description (String)
        Map<String, String> fruits = new LinkedHashMap<>();

        // Step 2: Add entries to the LinkedHashMap
        fruits.put("Apple", "A sweet red or green fruit.");
        fruits.put("Banana", "A long yellow fruit.");
        fruits.put("Cherry", "A small round red fruit.");

        // Step 3: Display the entries in the LinkedHashMap
        for (Map.Entry<String, String> entry : fruits.entrySet()) {
            System.out.println("Fruit Name: " + entry.getKey() + " - Description: " + entry.getValue());
        }
    }
}

Output:

Fruit Name: Apple - Description: A sweet red or green fruit.
Fruit Name: Banana - Description: A long yellow fruit.
Fruit Name: Cherry - Description: A small round red fruit.

Explanation:

1. The LinkedHashMap is an ordered version of HashMap that maintains the insertion order, useful for situations where order matters.

2. In this example, the LinkedHashMap has been set up to store fruit names (String) as keys and their descriptions (String) as values.

3. We use the put method to add details about various fruits into the map.

4. Finally, we iterate over the LinkedHashMap and display each fruit's name and its description. As can be seen from the output, the items are displayed in the order they were added.

2. Access Entries of a LinkedHashMap

import java.util.LinkedHashMap;
import java.util.Map;

public class LinkedHashMapAccess {

    public static void main(String[] args) {
        // Step 1: Create and initialize a LinkedHashMap with fruit names and their colors
        Map<String, String> fruitColors = new LinkedHashMap<>();
        fruitColors.put("Apple", "Red");
        fruitColors.put("Banana", "Yellow");
        fruitColors.put("Cherry", "Red");

        // Step 2: Check if a key exists
        String fruitToCheck = "Apple";
        if (fruitColors.containsKey(fruitToCheck)) {
            System.out.println(fruitToCheck + " exists in the LinkedHashMap.");
        } else {
            System.out.println(fruitToCheck + " does not exist in the LinkedHashMap.");
        }

        // Step 3: Check if a value exists
        String colorToCheck = "Green";
        if (fruitColors.containsValue(colorToCheck)) {
            System.out.println(colorToCheck + " color exists in the LinkedHashMap.");
        } else {
            System.out.println(colorToCheck + " color does not exist in the LinkedHashMap.");
        }

        // Step 4: Modify the value associated with a given key
        fruitColors.put("Apple", "Green");
        System.out.println("Modified color of Apple: " + fruitColors.get("Apple"));
    }
}

Output:

Apple exists in the LinkedHashMap.
Green color does not exist in the LinkedHashMap.
Modified color of Apple: Green

Explanation:

1. A LinkedHashMap named fruitColors is initialized with fruit names as keys and their colors as values.

2. The method containsKey() is used to check if a given key (fruit name) exists in the LinkedHashMap. In this example, we checked for the key "Apple".

3. The method containsValue() is used to check if a given value (fruit color) exists in the LinkedHashMap. Here, we checked for the color "Green".

4. The put() method is utilized to modify the value associated with a specific key. For this demonstration, the color of "Apple" is changed to "Green".

3. Remove Entries from a LinkedHashMap

import java.util.LinkedHashMap;
import java.util.Map;

public class LinkedHashMapRemoval {

    public static void main(String[] args) {
        // Step 1: Create and initialize a LinkedHashMap with fruit names and their colors
        Map<String, String> fruitColors = new LinkedHashMap<>();
        fruitColors.put("Apple", "Red");
        fruitColors.put("Banana", "Yellow");
        fruitColors.put("Cherry", "Red");

        // Step 2: Remove a key from the LinkedHashMap
        fruitColors.remove("Apple");
        System.out.println("After removing Apple: " + fruitColors);

        // Step 3: Remove a key only if associated with a particular value
        fruitColors.remove("Cherry", "Green");
        System.out.println("After trying to remove Cherry with color Green: " + fruitColors);

        fruitColors.remove("Cherry", "Red");
        System.out.println("After removing Cherry with color Red: " + fruitColors);
    }
}

Output:

After removing Apple: {Banana=Yellow, Cherry=Red}
After trying to remove Cherry with color Green: {Banana=Yellow, Cherry=Red}
After removing Cherry with color Red: {Banana=Yellow}

Explanation:

1. A LinkedHashMap named fruitColors is initialized with fruit names as keys and their colors as values.

2. The remove(Object key) method is used to remove the specified key (in this case, "Apple") and its associated value from the LinkedHashMap.

3. The remove(Object key, Object value) method is used to remove the specified key only if it is associated with the specified value. Here, an attempt is made to remove the key "Cherry" with the color "Green" (which does not match), so no removal occurs. Later, "Cherry" with the color "Red" is successfully removed.

4. Iterate Over a LinkedHashMap – Different Ways

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

public class LinkedHashMapIteration {

    public static void main(String[] args) {
        // Step 1: Create and initialize a LinkedHashMap with fruit names and their colors
        Map<String, String> fruitColors = new LinkedHashMap<>();
        fruitColors.put("Apple", "Red");
        fruitColors.put("Banana", "Yellow");
        fruitColors.put("Cherry", "Red");

        // Step 2: Iterate using Java 8 forEach and lambda expression
        System.out.println("Using Java 8 forEach and lambda:");
        fruitColors.forEach((fruit, color) -> System.out.println(fruit + " = " + color));

        // Step 3: Iterate over entrySet using Java 8 forEach and lambda expression
        System.out.println("\nUsing entrySet with Java 8 forEach and lambda:");
        fruitColors.entrySet().forEach(entry -> System.out.println(entry.getKey() + " = " + entry.getValue()));

        // Step 4: Iterate over entrySet using iterator
        System.out.println("\nUsing iterator over entrySet:");
        Iterator<Entry<String, String>> iterator = fruitColors.entrySet().iterator();
        while(iterator.hasNext()) {
            Entry<String, String> entry = iterator.next();
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }

        // Step 5: Iterate using iterator() and Java 8 forEachRemaining() method
        System.out.println("\nUsing iterator and Java 8 forEachRemaining():");
        iterator = fruitColors.entrySet().iterator();
        iterator.forEachRemaining(entry -> System.out.println(entry.getKey() + " = " + entry.getValue()));
    }
}

Output:

Using Java 8 forEach and lambda:
Apple = Red
Banana = Yellow
Cherry = Red

Using entrySet with Java 8 forEach and lambda:
Apple = Red
Banana = Yellow
Cherry = Red

Using iterator over entrySet:
Apple = Red
Banana = Yellow
Cherry = Red

Using iterator and Java 8 forEachRemaining():
Apple = Red
Banana = Yellow
Cherry = Red

Explanation:

1. A LinkedHashMap named fruitColors is initialized with fruit names as keys and their colors as values.

2. The first approach makes use of Java 8's forEach method directly on the LinkedHashMap using a lambda expression to print each key-value pair.

3. The second approach iterates over the entrySet of the LinkedHashMap using Java 8's forEach method and a lambda expression to print each entry.

4. In the third approach, an Iterator is used to manually loop through the entrySet and print each key-value pair.

5. The fourth approach uses the iterator() method to get an iterator and then utilizes the Java 8's forEachRemaining method to print each entry.

5. Student Management System Using LinkedHashMap

import java.util.LinkedHashMap;
import java.util.Map;

public class StudentManagement {

    // Define a Student class with name and grade properties
    static class Student {
        private final String name;
        private final int grade;

        public Student(String name, int grade) {
            this.name = name;
            this.grade = grade;
        }

        @Override
        public String toString() {
            return name + " (" + grade + ")";
        }
    }

    public static void main(String[] args) {
        // Create a LinkedHashMap to represent a student management system
        // where student ID numbers are keys and Students are values
        Map<Integer, Student> studentMap = new LinkedHashMap<>();

        // Add some students to the student map
        studentMap.put(1001, new Student("Alice", 85));
        studentMap.put(1002, new Student("Bob", 90));
        studentMap.put(1003, new Student("Charlie", 88));

        // Display the student management system
        System.out.println("Student Management System:");
        studentMap.forEach((id, student) -> System.out.println("ID: " + id + " - " + student));
    }
}

Output:

Student Management System:
ID: 1001 - Alice (85)
ID: 1002 - Bob (90)
ID: 1003 - Charlie (88)

Explanation:

1. A Student class is defined with properties name and grade. The class has a toString method to represent the student in a readable format.

2. A LinkedHashMap named studentMap is created where student ID numbers are used as the keys, and the Student object is the value.

3. Three students are added to the studentMap using their ID numbers as keys.

4. The student management system is displayed by iterating over the LinkedHashMap and printing the student ID and its associated Student object.

Conclusion

In this tutorial, you learned what is a LinkedHashMap, key points about LinkedHashMap, how to create a LinkedHashMap, how to add new key-value pairs to a LinkedHashMap, how to remove entries from a LinkedHashMap, and how to iterate over a LinkedHashMap.