ZetCode

Java Collections.singletonMap Method

Last modified: April 20, 2025

The Collections.singletonMap method is a utility method in Java's Collections framework. It creates an immutable map containing only one key-value pair. This method is part of the java.util.Collections class.

Singleton maps are useful when you need a map with exactly one entry that cannot be modified. They are memory-efficient and thread-safe by design. The method was introduced in Java 1.3 and remains widely used.

Collections.singletonMap Overview

The singletonMap method creates an immutable, serializable map with a single key-value pair. The resulting map implements the Map interface but throws UnsupportedOperationException for modification attempts.

Key characteristics include fixed size, null values support (if allowed by the value type), and optimized memory usage. The map maintains no extra storage beyond its single entry.

Basic singletonMap Usage

This example demonstrates the most basic usage of Collections.singletonMap. We create a map with one key-value pair and demonstrate its immutability by attempting to modify it.

SingletonMapBasic.java
package com.zetcode;

import java.util.Collections;
import java.util.Map;

public class SingletonMapBasic {

    public static void main(String[] args) {
        
        // Create singleton map
        Map<String, Integer> ageMap = Collections.singletonMap("John", 30);
        
        // Access elements
        System.out.println("John's age: " + ageMap.get("John"));
        System.out.println("Map size: " + ageMap.size());
        
        try {
            // Attempt to modify (will throw exception)
            ageMap.put("Alice", 25);
        } catch (UnsupportedOperationException e) {
            System.out.println("Expected exception: " + e.getMessage());
        }
    }
}

This code creates a singleton map with "John" as the key and 30 as the value. We demonstrate accessing the value and checking the map size. The attempt to add another entry throws an exception, proving immutability.

The output shows successful read operations and the expected exception when attempting modification. This behavior is fundamental to singleton collections.

Using singletonMap with Null Values

This example explores how singletonMap handles null values. While the key cannot be null, the value can be null if the value type permits it. We demonstrate both cases.

SingletonMapNulls.java
package com.zetcode;

import java.util.Collections;
import java.util.Map;

public class SingletonMapNulls {

    public static void main(String[] args) {
        
        // Valid: null value
        Map<String, String> validMap = 
            Collections.singletonMap("config", null);
        System.out.println("Config value: " + validMap.get("config"));
        
        try {
            // Invalid: null key
            Map<String, String> invalidMap = 
                Collections.singletonMap(null, "value");
        } catch (NullPointerException e) {
            System.out.println("Expected exception: " + e.getMessage());
        }
    }
}

The example shows that while null values are permitted (when the value type allows), null keys are prohibited. Attempting to use a null key throws a NullPointerException.

This behavior matches the general Map contract in Java, where keys cannot be null but values can be (unless restricted by the implementation). The output demonstrates both scenarios.

singletonMap in Method Parameters

Singleton maps are often used to pass single-entry maps to methods expecting Map parameters. This example shows a practical use case where a method requires a Map but we only have one entry.

SingletonMapParameter.java
package com.zetcode;

import java.util.Collections;
import java.util.Map;

public class SingletonMapParameter {

    public static void printMapDetails(Map<String, Integer> map) {
        System.out.println("Map contents:");
        map.forEach((k, v) -> System.out.println(k + " = " + v));
        System.out.println("Map size: " + map.size());
    }

    public static void main(String[] args) {
        
        // Using singletonMap as parameter
        printMapDetails(Collections.singletonMap("temperature", 23));
        
        // Without singletonMap would require more code:
        // Map<String, Integer> tempMap = new HashMap<>();
        // tempMap.put("temperature", 23);
        // printMapDetails(tempMap);
    }
}

Here we see how singletonMap simplifies passing single-entry maps to methods. The alternative would require creating a mutable map, adding the entry, and then passing it - more verbose and less efficient.

The output shows the method correctly processes the singleton map. This pattern is common in APIs that accept Map parameters but where callers often have just one entry.

Comparing singletonMap with Regular Map

This example compares memory usage and performance characteristics of singletonMap versus regular HashMap. We demonstrate the differences in memory footprint and modification behavior.

SingletonMapComparison.java
package com.zetcode;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class SingletonMapComparison {

    public static void main(String[] args) {
        
        // Singleton map
        Map<String, String> singleton = 
            Collections.singletonMap("id", "A100");
        
        // Regular HashMap
        Map<String, String> hashMap = new HashMap<>();
        hashMap.put("id", "A100");
        
        System.out.println("Singleton map class: " + singleton.getClass());
        System.out.println("HashMap class: " + hashMap.getClass());
        
        // Memory comparison
        System.out.println("\nSingleton map overhead: minimal");
        System.out.println("HashMap overhead: includes hash table structure");
        
        // Modification comparison
        try {
            singleton.put("newKey", "value");
        } catch (UnsupportedOperationException e) {
            System.out.println("\nCannot modify singleton map");
        }
        
        hashMap.put("newKey", "value");
        System.out.println("HashMap modified successfully");
    }
}

The example highlights key differences between singleton maps and regular HashMaps. Singleton maps have minimal memory overhead as they don't need hash table structures. They're immutable, while HashMaps are mutable by default.

The output shows the different behaviors and reminds us to choose the appropriate map type based on requirements. Singleton maps are perfect for immutable single-entry cases.

singletonMap with Custom Objects

This example demonstrates using singletonMap with custom objects as both keys and values. We'll use a simple Person class to show how object references work in singleton maps.

SingletonMapCustomObjects.java
package com.zetcode;

import java.util.Collections;
import java.util.Map;

class Person {
    private String name;
    
    public Person(String name) {
        this.name = name;
    }
    
    public String getName() {
        return name;
    }
    
    @Override
    public String toString() {
        return "Person{" + "name=" + name + '}';
    }
}

public class SingletonMapCustomObjects {

    public static void main(String[] args) {
        
        Person john = new Person("John Doe");
        Person jane = new Person("Jane Smith");
        
        Map<Person, Person> marriage = 
            Collections.singletonMap(john, jane);
        
        System.out.println("Marriage mapping:");
        marriage.forEach((k, v) -> 
            System.out.println(k.getName() + " is married to " + v.getName()));
        
        // The actual objects are stored by reference
        john = new Person("Johnny Doe"); // Doesn't affect the map
        System.out.println("\nAfter modifying original reference:");
        marriage.forEach((k, v) -> 
            System.out.println(k.getName() + " is married to " + v.getName()));
    }
}

The example shows that singleton maps store object references, not copies. When we create a new Person object and assign it to the john variable, the map still references the original object.

This behavior is consistent with all Java collections. The output demonstrates that modifying references doesn't affect collections that already contain those objects.

singletonMap in Collections Framework

This example shows how singletonMap fits within the broader Collections framework. We'll use it alongside other collections and demonstrate interoperability.

SingletonMapInFramework.java
package com.zetcode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

public class SingletonMapInFramework {

    public static void main(String[] args) {
        
        // Create a list of singleton maps
        List<Map<String, Integer>> mapList = new ArrayList<>();
        
        mapList.add(Collections.singletonMap("Alice", 25));
        mapList.add(Collections.singletonMap("Bob", 30));
        mapList.add(Collections.singletonMap("Charlie", 35));
        
        System.out.println("List of singleton maps:");
        mapList.forEach(map -> 
            map.forEach((k, v) -> System.out.println(k + ": " + v)));
        
        // Extract all values
        List<Integer> ages = new ArrayList<>();
        mapList.forEach(map -> ages.addAll(map.values()));
        
        System.out.println("\nAll ages: " + ages);
    }
}

Here we see how singleton maps can be used alongside other collection types. We create a list of singleton maps, each representing a person's age. Then we extract all values into a separate list.

This demonstrates the interoperability of singleton maps with the rest of the Collections framework. The output shows the combined data from all maps in the list.

Performance Considerations

This final example examines the performance benefits of singletonMap compared to regular maps. We'll measure memory usage and access times for both.

SingletonMapPerformance.java
package com.zetcode;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class SingletonMapPerformance {

    public static void main(String[] args) {
        
        final int iterations = 10_000_000;
        
        // Test singleton map
        long startTime = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            Map<Integer, String> map = Collections.singletonMap(i, "value");
        }
        long singletonTime = System.nanoTime() - startTime;
        
        // Test HashMap
        startTime = System.nanoTime();
        for (int i = 0; i < iterations; i++) {
            Map<Integer, String> map = new HashMap<>();
            map.put(i, "value");
        }
        long hashMapTime = System.nanoTime() - startTime;
        
        System.out.println("SingletonMap creation time: " + 
            (singletonTime / 1_000_000) + " ms");
        System.out.println("HashMap creation time: " + 
            (hashMapTime / 1_000_000) + " ms");
        System.out.println("Ratio: " + 
            ((double)hashMapTime / singletonTime));
    }
}

The performance test shows that singletonMap is significantly faster for creation than HashMap when you only need one entry. It also uses less memory as it doesn't allocate a hash table.

The output demonstrates the time difference in creating millions of each map type. Singleton maps are optimal for single-entry cases where immutability is acceptable.

Source

Java Collections.singletonMap Documentation

In this article, we've explored the Java Collections.singletonMap method in depth. We've covered basic usage, null handling, practical applications, performance, and integration with other collections.

Author

My name is Jan Bodnar, and I am a dedicated programmer with many years of experience in the field. I began writing programming articles in 2007 and have since authored over 1,400 articles and eight e-books. With more than eight years of teaching experience, I am committed to sharing my knowledge and helping others master programming concepts.

List all Java tutorials.