Java Collections.singletonMap 方法
最后修改时间:2025 年 5 月 1 日
Collections.singletonMap
方法是 Java Collections 框架中一个有用的工具,它允许创建一个包含恰好一个键值对的不可变 Map。作为 java.util.Collections
类的一部分,它提供了一种简化的方法来处理单条目 Map,而无需使用完整的集合。
当需要一个单条目 Map 且不需要修改时,单例 Map 是理想的选择。它们具有很高的内存效率,并且本质上是线程安全的,这使得它们在并发环境中成为一个可靠的选择。自 Java 1.3 引入以来,singletonMap
一直是简化基于 Map 操作的常用工具。
Collections.singletonMap 概述
Collections.singletonMap
方法返回一个不可变且可序列化的 Map,其中包含单个键值对。虽然它实现了 Map
接口,但任何试图修改其内容(例如添加或删除元素)的操作都会导致 UnsupportedOperationException
。
singletonMap
的关键特征包括
- 固定大小,恰好有一个条目。
- 支持空值(如果值类型允许)。
- 优化内存使用,不分配额外的存储空间。
- 线程安全设计,使其适用于并发应用程序。
由于其效率和简单性,singletonMap
常用在方法参数、API 调用以及倾向于不可变性而非动态修改的场景中。
基本 singletonMap 用法
此示例演示了 Collections.singletonMap
的最基本用法。我们创建一个包含一个键值对的 Map,并通过尝试修改它来演示其不可变性。
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()); } } }
此代码创建一个单例 Map,其中 "John" 作为键,30 作为值。我们演示了访问值并检查 Map 大小。尝试添加另一个条目会抛出一个异常,证明了其不可变性。
输出显示了成功的读取操作,以及在尝试修改时预期的异常。此行为是单例集合的基础。
在 singletonMap 中使用 Null 值
此示例探讨了 singletonMap
如何处理空值。虽然键不能为 null,但如果值类型允许,值可以为 null。我们演示了这两种情况。
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()); } } }
示例显示,虽然允许空值(当值类型允许时),但禁止空键。尝试使用空键会抛出 NullPointerException
。
此行为与 Java 中的一般 Map 契约相符,其中键不能为 null,但值可以为 null(除非由实现限制)。输出演示了这两种情况。
在方法参数中使用 singletonMap
Collections.singletonMap
方法提供了一种快速的方法,可以将单条目 Map 传递给需要 Map
参数的方法。当调用 API 或实用程序函数(不需要完整的 Map)时,这特别有用。在此示例中,我们模拟一个系统,该系统使用单例 Map 检索特定城市的天气数据。
package com.zetcode; import java.util.Collections; import java.util.Map; public class SingletonMapParameter { public static void displayWeatherInfo(Map<String, Integer> weatherData) { System.out.println("Weather Report:"); weatherData.forEach((city, temp) -> System.out.println("The temperature in " + city + " is " + temp + "°C")); System.out.println("Total locations processed: " + weatherData.size()); } public static void main(String[] args) { // Using singletonMap to pass a single city's weather data displayWeatherInfo(Collections.singletonMap("Bratislava", 18)); // Alternative approach without singletonMap: // Map<String, Integer> weatherMap = new HashMap<>(); // weatherMap.put("Bratislava", 18); // displayWeatherInfo(weatherMap); } }
此示例突出显示了 singletonMap
如何简化将单值 Map 传递给方法的操作,从而减少冗余,同时保持效率。无需手动创建和填充可变 Map,单例 Map 提供了一种简化的替代方案。
这种模式被广泛应用于 Java 应用程序中,特别是在 API 调用、配置设置以及只需要一个键值对的场景中。输出演示了方法如何无缝地处理单例 Map。
将 singletonMap 与常规 Map 进行比较
此示例比较了 singletonMap
与常规 HashMap 的内存使用和性能特征。我们演示了内存占用和修改行为的差异。
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"); } }
该示例突出了单例 Map 和常规 HashMap 之间的主要区别。单例 Map 的内存开销最小,因为它们不需要哈希表结构。它们是不可变的,而 HashMaps 默认是可变的。
输出显示了不同的行为,并提醒我们根据需求选择合适的 Map 类型。单例 Map 非常适合不可变的单条目情况。
在 Java 中使用 singletonMap 与自定义对象
Collections.singletonMap
方法允许创建一个包含单个键值对的不可变 Map。此示例演示了使用自定义对象作为键和值时的行为,特别是使用 Person
记录。我们将探讨对象引用在单例 Map 中的工作方式。
package com.zetcode; import java.util.Collections; import java.util.Map; record Person(String 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.name() + " is married to " + v.name())); // Changing the reference doesn't affect the map john = new Person("Johnny Doe"); // New object, but map remains unchanged System.out.println("\nAfter modifying original reference:"); marriage.forEach((k, v) -> System.out.println(k.name() + " is married to " + v.name())); } }
此示例强调了 singletonMap
存储对象引用而不是副本。虽然我们将一个新的 Person
实例分配给 john
变量,但原始映射保持不变,因为不可变集合不会动态更新。
此行为在所有 Java 集合中都是一致的:修改引用不会改变已存储在集合中的对象。
Collections 框架中的 singletonMap
此示例显示了 singletonMap
如何融入更广泛的 Collections 框架。我们将把它与其他集合一起使用,并演示互操作性。
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); } }
在这里,我们看到单例 Map 如何与其他集合类型一起使用。我们创建了一个单例 Map 的列表,每个 Map 代表一个人的年龄。然后,我们将所有值提取到单独的列表中。
这演示了单例 Map 与 Collections 框架其余部分的互操作性。输出显示了列表中所有 Map 的合并数据。
性能注意事项
此最终示例考察了 singletonMap
与常规 Map 相比的性能优势。我们将测量两者使用的内存和访问时间。
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)); } }
性能测试表明,当您只需要一个条目时,singletonMap
的创建速度比 HashMap 快得多。它也使用更少的内存,因为它不分配哈希表。
输出演示了创建数百万个 Map 类型的时差。对于不可变性可接受的单条目情况,单例 Map 是最佳选择。
来源
Java Collections.singletonMap 文档
在本文中,我们深入探讨了 Java Collections.singletonMap
方法。我们涵盖了基本用法、空值处理、实际应用、性能以及与其他集合的集成。
作者
列出所有Java教程。