ZetCode

Java Collections.emptyMap 方法

上次修改时间:2025 年 4 月 20 日

Collections.emptyMap 方法返回一个不可变的空 Map。它是 Java Collections 实用程序类的一部分。此方法提供了一种类型安全的方式来获取一个空的 Map 实例。

返回的 Map 是可序列化的,并实现了 Map 接口。创建后它不能被修改。这使得它对于从方法返回空结果非常有用。

Collections.emptyMap 概述

Collections.emptyMap 在 Java 1.5 中引入。它返回一个单例的空 Map 实例。该方法是通用的,并返回一个具有指定类型参数的 Map<K,V>

主要优势是内存效率。由于它是不可变的和共享的,它不会创建新的实例。当需要频繁使用空 Map 时,这会减少内存使用。

基本 emptyMap 用法

此示例演示了 Collections.emptyMap 的最基本用法。我们获取一个空 Map 并验证其属性。该示例通过尝试修改 Map 来展示其不可变性。

EmptyMapBasic.java
package com.zetcode;

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

public class EmptyMapBasic {

    public static void main(String[] args) {
        
        // Get empty map
        Map<String, Integer> emptyMap = Collections.emptyMap();
        
        // Verify properties
        System.out.println("Map size: " + emptyMap.size());
        System.out.println("Is empty: " + emptyMap.isEmpty());
        
        try {
            // Attempt to modify
            emptyMap.put("key", 1);
        } catch (UnsupportedOperationException e) {
            System.out.println("Expected exception: " + e.getMessage());
        }
    }
}

此代码展示了如何使用 Collections.emptyMap 获取一个空 Map。我们通过检查 size 和 isEmpty 来验证它是否为空。尝试修改它会抛出 UnsupportedOperationException

输出结果展示了 Map 的不可变性。这种行为与 Collections 类提供的所有不可变集合视图一致。

从方法返回空 Map

emptyMap 的一个常见用例是从方法返回空结果。此示例展示了一个根据条件返回已填充的 Map 或空 Map 的方法。

EmptyMapReturn.java
package com.zetcode;

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

public class EmptyMapReturn {

    public static Map<String, Integer> getWordCounts(String text) {
        if (text == null || text.trim().isEmpty()) {
            return Collections.emptyMap();
        }
        
        Map<String, Integer> counts = new HashMap<>();
        String[] words = text.split("\\s+");
        
        for (String word : words) {
            counts.merge(word, 1, Integer::sum);
        }
        
        return counts;
    }

    public static void main(String[] args) {
        System.out.println("Non-empty text: " + 
            getWordCounts("hello world hello"));
        System.out.println("Empty text: " + 
            getWordCounts(""));
    }
}

此示例演示了将 emptyMap 用作返回值。getWordCounts 方法对于空输入返回一个空 Map。对于非空输入,它返回一个带有单词计数的已填充 Map。

在这里使用 emptyMap 比创建新的 HashMap 实例更有效。它还清楚地向调用代码发出了空结果信号。

类型安全的空 Map

Collections.emptyMap 通过泛型提供类型安全。此示例展示了如何将其与不同的类型参数一起使用。编译器在编译时强制执行类型安全。

EmptyMapTypes.java
package com.zetcode;

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

public class EmptyMapTypes {

    public static void main(String[] args) {
        
        // String-Integer map
        Map<String, Integer> stringIntMap = Collections.emptyMap();
        System.out.println("String-Integer map: " + stringIntMap);
        
        // Integer-String map
        Map<Integer, String> intStringMap = Collections.emptyMap();
        System.out.println("Integer-String map: " + intStringMap);
        
        // Nested maps
        Map<String, Map<String, Integer>> nestedMap = Collections.emptyMap();
        System.out.println("Nested map: " + nestedMap);
        
        // The following would cause compile-time error:
        // stringIntMap.put(1, "one"); // Incompatible types
    }
}

此示例展示了具有不同泛型类型参数的 emptyMap。我们演示了简单的 Map、嵌套 Map,以及编译器如何防止类型不匹配。类型安全有助于及早发现错误。

输出结果表明,无论类型参数如何,这些 Map 都是空的。类型参数只影响编译时检查,而不影响运行时行为。

空 Map 作为默认值

空 Map 可以用作 Map 字段或参数的默认值。此示例展示了使用 emptyMap 来初始化一个字段并提供默认参数值。

EmptyMapDefault.java
package com.zetcode;

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

public class EmptyMapDefault {

    private Map<String, String> configurations = Collections.emptyMap();

    public void printConfigurations(
            Map<String, String> overrideConfigs) {
        
        Map<String, String> effectiveConfigs = overrideConfigs.isEmpty() 
            ? configurations 
            : overrideConfigs;
        
        System.out.println("Current configurations:");
        effectiveConfigs.forEach((k, v) -> 
            System.out.println(k + " = " + v));
    }

    public static void main(String[] args) {
        EmptyMapDefault demo = new EmptyMapDefault();
        
        // Use default empty map
        demo.printConfigurations(Collections.emptyMap());
        
        // Use provided map
        demo.printConfigurations(
            Map.of("timeout", "100", "retries", "3"));
    }
}

此示例演示了将 emptyMap 用作默认值。类字段使用一个空 Map 进行初始化。该方法使用默认的或提供的配置 Map。

输出结果展示了两种情况:使用默认的空 Map 和使用提供的 Map。这种模式在配置处理和类似场景中很常见。

Collections 框架中的空 Map

空 Map 与其他 Collections 框架功能集成。此示例展示了如何将其与诸如 putAll 和流操作之类的方法一起使用。

EmptyMapFramework.java
package com.zetcode;

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

public class EmptyMapFramework {

    public static void main(String[] args) {
        
        // Using with putAll
        Map<String, Integer> map1 = new HashMap<>();
        map1.putAll(Collections.emptyMap());
        System.out.println("After putAll: " + map1);
        
        // Using with streams
        Map<String, Integer> result = Collections.emptyMap()
            .entrySet()
            .stream()
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue));
        
        System.out.println("Stream result: " + result);
        
        // Using with Map.copyOf (Java 10+)
        Map<String, Integer> copiedMap = Map.copyOf(Collections.emptyMap());
        System.out.println("Copied map: " + copiedMap);
    }
}

此示例展示了 emptyMap 与其他 Collections 框架功能的配合使用。我们演示了 putAll、流和 Map.copyOf。空 Map 在所有情况下都表现正确。

输出结果表明,使用空 Map 的操作会产生空或未更改的结果。这使得空 Map 可以安全地用于各种集合操作。

性能注意事项

使用 Collections.emptyMap 具有性能优势。此示例将其与创建新的 HashMap 实例进行了比较。我们测量了内存使用量和执行时间。

EmptyMapPerformance.java
package com.zetcode;

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

public class EmptyMapPerformance {

    public static void main(String[] args) {
        final int ITERATIONS = 1_000_000;
        
        // Test emptyMap
        long start = System.nanoTime();
        for (int i = 0; i < ITERATIONS; i++) {
            Map<String, String> m = Collections.emptyMap();
        }
        long emptyMapTime = System.nanoTime() - start;
        
        // Test new HashMap
        start = System.nanoTime();
        for (int i = 0; i < ITERATIONS; i++) {
            Map<String, String> m = new HashMap<>();
        }
        long hashMapTime = System.nanoTime() - start;
        
        System.out.println("Collections.emptyMap time: " + 
            emptyMapTime / 1_000_000 + " ms");
        System.out.println("new HashMap time: " + 
            hashMapTime / 1_000_000 + " ms");
        System.out.println("Ratio: " + 
            (double)hashMapTime / emptyMapTime);
    }
}

此示例比较了 emptyMap 与创建新的 HashMap 实例的性能。测试创建了每种类型的 Map 一百万次,并测量了经过的时间。

输出结果表明 emptyMap 明显更快。这是因为它重用了单个不可变实例,而不是创建新对象。

空 Map 序列化

Collections.emptyMap 返回的空 Map 是可序列化的。此示例演示了序列化和反序列化一个空 Map。我们使用 Java 的标准序列化机制。

EmptyMapSerialization.java
package com.zetcode;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Collections;
import java.util.Map;

public class EmptyMapSerialization {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Map<String, Integer> originalMap = Collections.emptyMap();
        
        // Serialize
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(originalMap);
        oos.close();
        
        // Deserialize
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        @SuppressWarnings("unchecked")
        Map<String, Integer> deserializedMap = (Map<String, Integer>) ois.readObject();
        
        System.out.println("Original map: " + originalMap);
        System.out.println("Deserialized map: " + deserializedMap);
        System.out.println("Same instance: " + 
            (originalMap == deserializedMap));
    }
}

此示例展示了空 Map 可以被序列化和反序列化。该过程保留了 Map 的空状态。反序列化后,我们仍然有一个可用的空 Map。

输出结果确认了序列化工作正常。请注意,反序列化的 Map 可能不是完全相同的单例实例,但行为将完全相同。

来源

Java Collections.emptyMap 文档

在本文中,我们深入探讨了 Java 的 Collections.emptyMap 方法。我们涵盖了基本用法、类型安全、性能以及与其他集合功能的集成。空 Map 是许多场景中一个有用的工具。

作者

我的名字是 Jan Bodnar,我是一位经验丰富的程序员,在该领域拥有多年经验。我从 2007 年开始撰写编程文章,至今已撰写了 1,400 多篇文章和八本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程