Java Collections synchronizedSortedMap() Method

The synchronizedSortedMap() method in Java is a utility method provided by the java.util.Collections class. It returns a synchronized (thread-safe) sorted map backed by the specified sorted map. This method is particularly useful when you need to ensure that a sorted map is thread-safe in a concurrent environment.

Table of Contents

  1. Introduction
  2. synchronizedSortedMap() Method Syntax
  3. Examples
    • Basic Usage of synchronizedSortedMap()
    • Using synchronizedSortedMap() with Custom Classes
  4. Real-World Use Case
  5. Conclusion

Introduction

The Collections.synchronizedSortedMap() method provides a way to wrap a given sorted map with synchronized access, ensuring that only one thread can access the map at a time. This is crucial in concurrent applications where multiple threads might try to modify the map simultaneously, leading to race conditions or inconsistent data.

The returned sorted map is a synchronized view of the specified map, meaning that all operations on the map are synchronized using the map’s intrinsic lock. This includes operations such as adding, removing, or iterating over the entries, as well as sorted map-specific operations like accessing sub-maps.

synchronizedSortedMap() Method Syntax

The syntax for the synchronizedSortedMap() method is as follows:

public static <K, V> SortedMap<K, V> synchronizedSortedMap(SortedMap<K, V> m)

Parameters:

  • m: The sorted map to be wrapped in a synchronized view.

Returns:

  • A synchronized (thread-safe) sorted map backed by the specified sorted map.

Throws:

  • NullPointerException if the specified sorted map is null.

Examples

Basic Usage of synchronizedSortedMap()

The following example demonstrates how to use the synchronizedSortedMap() method to create a synchronized view of a sorted map.

Example

import java.util.Collections;
import java.util.Iterator;
import java.util.SortedMap;
import java.util.TreeMap;

public class SynchronizedSortedMapExample {
    public static void main(String[] args) {
        // Create a regular TreeMap
        SortedMap<String, String> sortedMap = new TreeMap<>();
        sortedMap.put("Apple", "Fruit");
        sortedMap.put("Carrot", "Vegetable");
        sortedMap.put("Banana", "Fruit");

        // Create a synchronized (thread-safe) sorted map backed by the TreeMap
        SortedMap<String, String> synchronizedSortedMap = Collections.synchronizedSortedMap(sortedMap);

        // Display the synchronized sorted map
        System.out.println("Synchronized Sorted Map: " + synchronizedSortedMap);

        // Use synchronized block for iteration to ensure thread safety
        synchronized (synchronizedSortedMap) {
            Iterator<String> iterator = synchronizedSortedMap.keySet().iterator();
            while (iterator.hasNext()) {
                String key = iterator.next();
                System.out.println("Key: " + key + ", Value: " + synchronizedSortedMap.get(key));
            }
        }

        // Adding and removing entries in a synchronized sorted map
        synchronized (synchronizedSortedMap) {
            synchronizedSortedMap.put("Date", "Fruit");
            synchronizedSortedMap.remove("Carrot");
        }

        // Display the modified synchronized sorted map
        System.out.println("Modified Synchronized Sorted Map: " + synchronizedSortedMap);
    }
}

Output:

Synchronized Sorted Map: {Apple=Fruit, Banana=Fruit, Carrot=Vegetable}
Key: Apple, Value: Fruit
Key: Banana, Value: Fruit
Key: Carrot, Value: Vegetable
Modified Synchronized Sorted Map: {Apple=Fruit, Banana=Fruit, Date=Fruit}

Using synchronizedSortedMap() with Custom Classes

You can also use the synchronizedSortedMap() method with sorted maps containing instances of custom classes.

Example

import java.util.Collections;
import java.util.Iterator;
import java.util.SortedMap;
import java.util.TreeMap;

class Student implements Comparable<Student> {
    String name;
    int id;

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

    @Override
    public int compareTo(Student other) {
        return Integer.compare(this.id, other.id);
    }

    @Override
    public String toString() {
        return name + " (ID: " + id + ")";
    }
}

public class CustomSynchronizedSortedMapExample {
    public static void main(String[] args) {
        // Create a sorted map of students and their scores
        SortedMap<Student, Integer> studentScores = new TreeMap<>();
        studentScores.put(new Student("Amit", 101), 85);
        studentScores.put(new Student("Neha", 102), 90);
        studentScores.put(new Student("Raj", 103), 78);

        // Create a synchronized (thread-safe) sorted map backed by the student map
        SortedMap<Student, Integer> synchronizedStudentScores = Collections.synchronizedSortedMap(studentScores);

        // Display the synchronized student sorted map
        System.out.println("Synchronized Student Sorted Map: " + synchronizedStudentScores);

        // Use synchronized block for iteration to ensure thread safety
        synchronized (synchronizedStudentScores) {
            Iterator<Student> iterator = synchronizedStudentScores.keySet().iterator();
            while (iterator.hasNext()) {
                Student student = iterator.next();
                System.out.println("Student: " + student + ", Score: " + synchronizedStudentScores.get(student));
            }
        }

        // Modifying the synchronized sorted map
        synchronized (synchronizedStudentScores) {
            synchronizedStudentScores.put(new Student("Vikram", 104), 88);
            synchronizedStudentScores.remove(new Student("Neha", 102));
        }

        // Display the modified synchronized student sorted map
        System.out.println("Modified Synchronized Student Sorted Map: " + synchronizedStudentScores);
    }
}

Output:

Synchronized Student Sorted Map: {Amit (ID: 101)=85, Neha (ID: 102)=90, Raj (ID: 103)=78}
Student: Amit (ID: 101), Score: 85
Student: Neha (ID: 102), Score: 90
Student: Raj (ID: 103), Score: 78
Modified Synchronized Student Sorted Map: {Amit (ID: 101)=85, Raj (ID: 103)=78, Vikram (ID: 104)=88}

Explanation:

  1. Synchronized View: The synchronizedSortedMap() method returns a synchronized view of the specified sorted map, ensuring thread-safe access.

  2. Synchronized Block: When iterating over the synchronized sorted map, a synchronized block is used to avoid concurrent modification exceptions and ensure thread safety.

  3. Custom Class: The method works with custom class instances, allowing you to create synchronized sorted maps with user-defined objects.

Real-World Use Case

Thread-Safe Access to a Shared Resource

In real-world applications, the synchronizedSortedMap() method can be used to manage thread-safe access to shared resources, such as a map of sorted tasks in a multi-threaded environment.

Example

Imagine a scenario where you need to manage a shared map of sorted tasks in a concurrent application.

import java.util.Collections;
import java.util.Iterator;
import java.util.SortedMap;
import java.util.TreeMap;

class Task implements Comparable<Task> {
    String description;
    int priority;

    Task(String description, int priority) {
        this.description = description;
        this.priority = priority;
    }

    @Override
    public int compareTo(Task other) {
        return Integer.compare(this.priority, other.priority);
    }

    @Override
    public String toString() {
        return description + " (Priority: " + priority + ")";
    }
}

public class TaskManager {
    private final SortedMap<Task, String> tasks;

    public TaskManager() {
        // Initialize the task map and wrap it in a synchronized view
        this.tasks = Collections.synchronizedSortedMap(new TreeMap<>());
    }

    public void addTask(Task task, String assignee) {
        synchronized (tasks) {
            tasks.put(task, assignee);
        }
    }

    public void removeTask(Task task) {
        synchronized (tasks) {
            tasks.remove(task);
        }
    }

    public void displayTasks() {
        // Use synchronized block for iteration to ensure thread safety
        synchronized (tasks) {
            Iterator<Task> iterator = tasks.keySet().iterator();
            while (iterator.hasNext()) {
                Task task = iterator.next();
                System.out.println("Task: " + task + ", Assignee: " + tasks.get(task));
            }
        }
    }

    public static void main(String[] args) {
        TaskManager taskManager = new TaskManager();

        // Add tasks to the manager
        taskManager.addTask(new Task("Review code", 2), "Alice");
        taskManager.addTask(new Task("Write tests", 1), "Bob");
        taskManager.addTask(new Task("Deploy application", 3), "Charlie");

        // Display all tasks
        System.out.println("Task List:");
        taskManager.displayTasks();

        // Remove a task
        taskManager.removeTask(new Task("Write tests", 1));

        // Display remaining tasks
        System.out.println("\nUpdated Task List:");
        taskManager.displayTasks();
    }
}

Output:

Task List:
Task: Write tests (Priority: 1), Assignee: Bob
Task: Review code (Priority: 2), Assignee: Alice
Task: Deploy application (Priority: 3), Assignee: Charlie

Updated Task List:
Task: Review code (Priority: 2), Assignee: Alice
Task: Deploy application (Priority: 3), Assignee: Charlie

Explanation:

  1. Task Manager: The TaskManager class manages a sorted map of tasks, ensuring thread-safe access by wrapping the map in a synchronized view.

  2. Concurrent Environment: The synchronizedSortedMap() method is used to synchronize access to the shared map, preventing race conditions and ensuring data consistency.

  3. Task Management: The example demonstrates the use of a sorted map to manage tasks based on their priority.

Conclusion

The Collections.synchronizedSortedMap() method is a powerful utility for creating synchronized (thread-safe) sorted maps in Java. By providing a simple way to wrap sorted maps with synchronized access, it enhances the flexibility and safety of your code in concurrent environments. This method is particularly valuable in scenarios where you need to manage shared resources or ensure thread-safe access to sorted data, improving the robustness and maintainability of your Java applications.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top