Collections.singleton: примеры (JAVA)

Метод Collections.singleton() и типичные сценарии использования
Раздел: Коллекции, Утилиты
Collections.singleton(T o): Set

Описание Collections.singleton()

Метод Collections.singleton возвращает неизменяемое множество, содержащее ровно один указанный элемент. Подпись метода в Java:

public static <T> Set<T> singleton(T o)

Аргументы и поведение:

  • o - элемент типа T, который будет единственным элементом возвращаемого множества. Значение null допустимо.
  • Возвращаемое значение: объект типа Set<T>, содержащий ровно один элемент o. Множество неизменяемое: попытки изменить (add, remove, clear и т. п.) приводят к UnsupportedOperationException.
  • Если элемент реализует Serializable, возвращаемое множество также сериализуется; сериализация множества может вызвать исключение, если элемент не сериализуем.

Реализация и свойства:

  • Реализовано в виде внутреннего класса (например, Collections$SingletonSet). Итератор возвращает единственный элемент, а размер равен 1.
  • Семантика неизменяемости - методы модификации поднимают UnsupportedOperationException.
  • Сложность операций доступа - константная для основных операций (contains, size, iterator).

Типичные сценарии применения: создание простого неизменяемого набора для передачи в метод, где требуется коллекция, использование в качестве неизменяемой константы в API, быстрые сравнения (например, set.equals(Collections.singleton(x))).

Краткие примеры использования

Создание и чтение единственного элемента:

Set<String> s = Collections.singleton("hello");
System.out.println(s.size());
System.out.println(s.contains("hello"));
for (String v : s) System.out.println(v);
1
true
hello

Создание множества с null и проверка:

Set<Object> sNull = Collections.singleton(null);
System.out.println(sNull.size());
System.out.println(sNull.contains(null));
1
true

Попытка модификации приводит к исключению:

Set<String> s2 = Collections.singleton("a");
s2.add("b");
Exception in thread "main" java.lang.UnsupportedOperationException
    at java.base/java.util.Collections$SingletonSet.add(Collections.java:...)
    ...

Сериализация работает, если элемент сериализуем:

Set<String> sSer = Collections.singleton("ok");
byte[] data = serialize(sSer); // вспомогательная функция сериализации
Set<String> restored = deserialize(data);
(после успешной сериализации и десериализации восстановлено множество с одним элементом "ok")

Похожие методы в Java

  • Set.of(E) (Java 9+) - создаёт неизменяемое множество. Отличие: Set.of не допускает null и выбрасывает NullPointerException при попытке создать множество с null.
  • Collections.singletonList - аналог для списка, возвращает неизменяемый список из одного элемента. Предпочтительно, если нужен список, а не множество.
  • Collections.singletonMap - аналог для отображения (Map) с одной парой ключ-значение.
  • Collections.unmodifiableSet - обёртка над существующим множеством, делает его только для чтения, но исходное множество может быть изменено напрямую; отличается от singleton, который предоставляет собственную неизменяемую реализацию.
  • Guava ImmutableSet.of(element) - из сторонней библиотеки, также создает неизменяемое множество; полезно при использовании Guava и требовании дополнительных гарантий и API.

Аналоги в других языках и отличия

Python:

s = frozenset([42])  # неизменяемое множество
print(s)
frozenset({42})

Отличия: frozenset неизменяем; обычный set изменяем. None допустим.

JavaScript:

const s = new Set(["x"]);
console.log(s.has("x"));
true

Отличия: Set в JS изменяемый. Для имитации неизменяемости используется Object.freeze на структуре, но Set не полностью защищается.

Python (список-эквивалент):

t = ("x",)
print(t)
('x',)

C#:

var s = new HashSet<int> { 1 };
// или неизменяемое множество (System.Collections.Immutable)
var im = System.Collections.Immutable.ImmutableHashSet.Create(1);
Console.WriteLine(im.Contains(1));
True

Отличия: стандартный HashSet изменяем. Для гарантии неизменяемости используется коллекция из пакета Immutable.

Kotlin:

val s = setOf("a")
println(s.size)
1

Отличия: setOf возвращает неизменяемое множество и допускает null для nullable типов.

Go:

s := map[string]struct{}{"a": {}}
fmt.Println(len(s))
1

Отличия: в Go нет встроенного типа Set; используют map[T]struct{} как набор. Нет встроенной неизменяемости.

PHP:

$arr = ["a"]; // массив с одним элементом
print_r($arr);
Array
(
    [0] => a
)

Отличия: в PHP нет встроенного множества; используют массивы или SPL-классы.

Lua:

s = { a = true }
for k in pairs(s) do print(k) end
a

SQL:

SELECT 1 AS val;
-- результат представляет собой набор из одной строки
val
---
1

Кратко: во многих языках есть эквиваленты (immutable set, single-element collection или map), но у каждого языка свои правила по null/None и по изменяемости.

Типичные ошибки и примеры

1) Ожидание модификации множества. Попытка добавить или удалить элемент вызывает UnsupportedOperationException:

Set<String> s = Collections.singleton("x");
s.remove("x");
Exception in thread "main" java.lang.UnsupportedOperationException
    at java.base/java.util.Collections$SingletonSet.remove(Collections.java:...)
    ...

2) Ошибка приведения типов. Попытка привести возвращаемое множество к конкретной реализации, чтобы его модифицировать, приводит к ClassCastException:

Set<String> s = Collections.singleton("x");
HashSet<String> h = (HashSet<String>) s; // неправильное приведение
Exception in thread "main" java.lang.ClassCastException: java.util.Collections$SingletonSet cannot be cast to java.util.HashSet
    at ...

3) Сериализация при несериализуемом элементе приводит к NotSerializableException в момент сериализации:

Object nonSer = new Object();
Set<Object> s = Collections.singleton(nonSer);
serialize(s); // попытка сериализации
java.io.NotSerializableException: java.lang.Object
    at ...

4) Путаница с Set.of (Java 9+) по части null. Collections.singleton(null) допустимо, а Set.of(null) вызовет NPE:

Set<Object> a = Collections.singleton(null); // OK
Set<Object> b = Set.of(null); // NPE
Exception in thread "main" java.lang.NullPointerException
    at java.base/java.util.ImmutableCollections.a(ImmutableCollections.java:...)
    ...

Изменения в поведении и истории

  • Метод Collections.singleton присутствует в JDK с ранних версий и не претерпел принципиальных изменений.
  • В Java 9 добавлены фабричные методы коллекций (Set.of, List.of, Map.of), предлагающие компактный синтаксис и дополнительные гарантии (например, отказ от null при Set.of).
  • Рекомендация при использовании новых API: при необходимости строгой проверки на null или при создании нескольких элементов отдавать предпочтение Set.of или коллекциям из Immutable-библиотек; для простого случая одного элемента Collections.singleton остаётся корректным вариантом.

Расширенные и редкие сценарии использования

1) Передача в API, ожидающее Collection, для установки единственного разрешённого значения:

Пример java
void processAllowed(Set<String> allowed) {
    if (allowed.contains("admin")) System.out.println("has admin");
}
// Вызов
processAllowed(Collections.singleton("admin"));
has admin

2) Использование в Stream и объединение с другими коллекциями:

Пример java
Set<String> s1 = Collections.singleton("x");
Set<String> s2 = new HashSet<>(Arrays.asList("y","z"));
Set<String> merged = Stream.concat(s1.stream(), s2.stream()).collect(Collectors.toSet());
System.out.println(merged);
[x, y, z] (порядок может отличаться)

3) Быстрая передача одиночного элемента в методы из Collections, например для поиска пересечений:

Пример java
List<String> list = Arrays.asList("a","b","c");
boolean disjoint = Collections.disjoint(list, Collections.singleton("b"));
System.out.println(disjoint);
false

4) Использование как ключа при сравнении множеств (удобно в тестах):

Пример java
Set<Integer> actual = someMethod();
assert actual.equals(Collections.singleton(42));
(проверяется, что actual содержит только 42)

5) Передача в API безопасности/валидации: набор допустимых ролей из одного значения, безопасный для многопоточного чтения благодаря неизменяемости.

Пример java
final Set<String> allowed = Collections.singleton("ROLE_USER");
// shared between threads for checks
if (allowed.contains(userRole)) doSomething();
(корректная многопоточная проверка без синхронизации)

6) Сериализация и десериализация при сложных типах: при необходимости сохранить и восстановить множество, важно чтобы элемент был сериализуем. Пример использования: кэширование небольших конфигураций как singleton-коллекций.

7) Комбинации с Guava/Immutable коллекциями: при миграции кода можно заменить Collections.singleton(x) на ImmutableSet.of(x) для единообразия API, если используется Guava.

джава Collections.singleton function comments

En
Collections.singleton Создает набор из одного элемента