ZetCode

Java Collections.singleton 方法

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

Collections.singleton 方法是 Java Collections Framework 中的一个实用方法。它创建一个只包含指定对象的不可变 Set。当您需要一个单元素、不可修改的 Set 时,此方法非常有用。

返回的 Set 是可序列化的,并且具有固定大小 1。尝试修改它将抛出 UnsupportedOperationException 异常。这使其成为需要只读单元素集合的 API 的理想选择。

Collections.singleton 概述

singleton 方法是 java.util.Collections 类的一部分。它在 Java 1.3 中引入,并且自那时以来一直没有改变。该方法接受一个参数并返回包含该参数的 Set。

该实现是内存高效的,因为它不会创建一个完整的 HashSet。它是线程安全的,并为基本操作提供恒定时间性能。Set 通过泛型维护元素的类型。

Collections.singleton 的基本用法

此示例演示了 Collections.singleton 的最基本用法。我们创建一个包含字符串的单元素 Set。该示例展示了如何创建 Set 并验证其内容。

SingletonBasicExample.java
package com.zetcode;

import java.util.Collections;
import java.util.Set;

public class SingletonBasicExample {

    public static void main(String[] args) {
        
        // Create a singleton Set
        Set<String> singleElementSet = Collections.singleton("Hello");
        
        // Print the Set
        System.out.println("Singleton Set: " + singleElementSet);
        
        // Check size
        System.out.println("Set size: " + singleElementSet.size());
        
        // Check contains
        System.out.println("Contains 'Hello': " + 
            singleElementSet.contains("Hello"));
    }
}

此代码创建一个只包含字符串 "Hello" 的不可变 Set。然后,我们演示了 Set 上的基本操作。输出显示了 Set 的内容、大小和成员资格检查。

该 Set 在创建后无法修改。任何添加或删除元素的尝试都会抛出 UnsupportedOperationException 异常。

将 singleton 与 Collection 方法一起使用

Collections.singleton 方法通常与其他 collection 方法一起使用。此示例展示了如何将其与 removeAll 一起使用以从集合中删除特定元素。

SingletonWithRemoveAll.java
package com.zetcode;

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

public class SingletonWithRemoveAll {

    public static void main(String[] args) {
        
        List<String> colors = new ArrayList<>();
        colors.add("Red");
        colors.add("Green");
        colors.add("Blue");
        colors.add("Green");
        
        System.out.println("Original list: " + colors);
        
        // Remove all occurrences of "Green"
        colors.removeAll(Collections.singleton("Green"));
        
        System.out.println("After removal: " + colors);
    }
}

此示例演示了 Collections.singleton 的一个常见用例。我们创建一个包含多个元素的 List,包括重复项。然后,我们使用带有 singleton Set 的 removeAll 来删除所有出现的 "Green"。

输出显示了删除操作前后的 List。与手动迭代删除元素相比,此技术更简洁。

singleton 的不可变性

Collections.singleton 返回的 Set 是不可变的。此示例演示了尝试修改 Set 时会发生什么。所有修改尝试都会导致异常。

SingletonImmutability.java
package com.zetcode;

import java.util.Collections;
import java.util.Set;

public class SingletonImmutability {

    public static void main(String[] args) {
        
        Set<Integer> singleNumber = Collections.singleton(42);
        
        System.out.println("Original Set: " + singleNumber);
        
        try {
            // Attempt to add element
            singleNumber.add(99);
        } catch (UnsupportedOperationException e) {
            System.out.println("Cannot add: " + e.getMessage());
        }
        
        try {
            // Attempt to remove element
            singleNumber.remove(42);
        } catch (UnsupportedOperationException e) {
            System.out.println("Cannot remove: " + e.getMessage());
        }
        
        try {
            // Attempt to clear
            singleNumber.clear();
        } catch (UnsupportedOperationException e) {
            System.out.println("Cannot clear: " + e.getMessage());
        }
    }
}

此代码有意触发异常以演示 singleton Set 的不可变性。我们尝试添加、删除和清除 Set,所有这些都因 UnsupportedOperationException 而失败。

输出显示了每个失败的操作。这种不变性是设计使然,可确保 Set 在创建后保持不变。

将 singleton 与 Stream API 一起使用

Collections.singleton 方法与 Java 的 Stream API 配合良好。此示例展示了如何从 singleton Set 创建流并对其执行操作。

SingletonWithStreams.java
package com.zetcode;

import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;

public class SingletonWithStreams {

    public static void main(String[] args) {
        
        Set<String> singleWord = Collections.singleton("Java");
        
        // Create stream from singleton
        String result = singleWord.stream()
            .map(String::toUpperCase)
            .collect(Collectors.joining());
            
        System.out.println("Original: " + singleWord);
        System.out.println("Transformed: " + result);
        
        // Filter example
        long count = singleWord.stream()
            .filter(s -> s.length() > 3)
            .count();
            
        System.out.println("Count of words longer than 3: " + count);
    }
}

此示例演示了如何将 singleton Set 与 Java Streams 一起使用。我们从 Set 创建一个流,将其元素转换为大写,然后收集结果。我们还展示了过滤,即使只有一个元素。

输出显示了原始值和转换后的值。虽然很简单,但当处理期望集合的 API 时,此模式可能很有用。

性能注意事项

Collections.singleton 方法比常规 Set 实现具有性能优势。此示例比较了 singleton 和 HashSet 之间的内存使用情况和操作时间。

SingletonPerformance.java
package com.zetcode;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class SingletonPerformance {

    public static void main(String[] args) {
        
        // Measure memory before
        long memoryBefore = Runtime.getRuntime().freeMemory();
        
        // Create 100,000 singleton sets
        for (int i = 0; i < 100_000; i++) {
            Set<Integer> s = Collections.singleton(i);
        }
        
        // Measure memory after
        long memoryAfter = Runtime.getRuntime().freeMemory();
        System.out.println("Memory used by singletons: " + 
            (memoryBefore - memoryAfter) + " bytes");
            
        // Reset
        memoryBefore = Runtime.getRuntime().freeMemory();
        
        // Create 100,000 HashSets
        for (int i = 0; i < 100_000; i++) {
            Set<Integer> s = new HashSet<>();
            s.add(i);
        }
        
        // Measure memory after
        memoryAfter = Runtime.getRuntime().freeMemory();
        System.out.println("Memory used by HashSets: " + 
            (memoryBefore - memoryAfter) + " bytes");
    }
}

此示例比较了 singleton Set 与常规 HashSet 的内存使用情况。我们创建 100,000 个并测量内存差异。Singleton Set 的内存效率明显更高。

输出显示了内存消耗差异。对于单元素 Set,当可接受不变性时,应首选 Collections.singleton

在方法参数中使用 singleton

Collections.singleton 方法通常用于将单个元素传递给期望集合的方法。此示例演示了具有处理值 Set 的方法模式。

SingletonAsParameter.java
package com.zetcode;

import java.util.Collections;
import java.util.Set;

public class SingletonAsParameter {

    public static void main(String[] args) {
        
        // Call method with multiple values
        printLanguages(Set.of("Java", "Python", "C++"));
        
        // Call same method with single value using singleton
        printLanguages(Collections.singleton("JavaScript"));
    }
    
    private static void printLanguages(Set<String> languages) {
        System.out.println("Languages:");
        languages.forEach(System.out::println);
        System.out.println("-----");
    }
}

此示例展示了如何使用 Collections.singleton 将单个值传递给期望 Set 的方法。我们定义了一个打印 Set 中所有元素的方法,然后使用多元素 Set 和 singleton 调用它。

输出表明该方法在这两种情况下都以相同的方式工作。此模式提供了 API 灵活性,同时保持了类型安全。

将 singleton 与其他方法进行比较

Java 提供了几种创建单元素集合的方法。此示例比较了 Collections.singletonSet.of(Java 9+)和手动 Set 创建。

SingletonComparison.java
package com.zetcode;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

public class SingletonComparison {

    public static void main(String[] args) {
        
        // Method 1: Collections.singleton
        Set<String> s1 = Collections.singleton("A");
        
        // Method 2: Set.of (Java 9+)
        Set<String> s2 = Set.of("A");
        
        // Method 3: Manual HashSet
        Set<String> s3 = new HashSet<>();
        s3.add("A");
        
        System.out.println("Collections.singleton: " + s1);
        System.out.println("Set.of: " + s2);
        System.out.println("Manual HashSet: " + s3);
        
        // Attempt modifications
        try {
            s1.add("B");
        } catch (Exception e) {
            System.out.println("s1 is immutable");
        }
        
        try {
            s2.add("B");
        } catch (Exception e) {
            System.out.println("s2 is immutable");
        }
        
        s3.add("B");
        System.out.println("Modified s3: " + s3);
    }
}

此示例比较了创建单元素 Set 的三种方法。我们展示了 Collections.singletonSet.of (Java 9+) 和手动 HashSet 创建。每种方法在可变性方面都有不同的特征。

输出表明 Collections.singletonSet.of 都会生成不可变的 Set,而 HashSet 仍然是可变的。选择取决于 Java 版本和可变性要求。

来源

Java Collections.singleton 文档

在本文中,我们深入探讨了 Collections.singleton 方法。我们介绍了基本用法、不变性、性能以及与其他替代方案的比较。此方法是处理单元素集合的宝贵工具。

作者

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

列出所有Java教程