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

Пустое множество через Collections.emptySet()
Раздел: Коллекции, Утилиты
Collections.emptySet(): Set

Описание и сигнатура

Метод Collections.emptySet() возвращает пустое множество типа Set<T>. Сигнатура метода в стандартной библиотеке выглядит так: public static <T> Set<T> emptySet(). Метод не принимает аргументов и всегда возвращает множество без элементов.

Ключевые свойства возвращаемого объекта:

  • Пустое по содержимому - размер равен 0.
  • Неподдерживающее модификацию: операции добавления/удаления приводят к UnsupportedOperationException.
  • Типобезопасное при использовании с параметрами типа благодаря generics; до Java 5 существовала константа Collections.EMPTY_SET без generics.
  • Чтение потокобезопасно, так как состояние не меняется. По сути реализуется как неизменяемая (immutable) структура.
  • Может быть реализовано как одиночный экземпляр (singleton) внутри JDK; гарантии конкретной реализации не заданы, но семантика единичности и сериализуемости обычно соблюдается.

Сценарии использования: возврат пустого множества вместо null из методов, передача в конструкторы для создания копии, оптимизация при отсутствии элементов, указание дефолтного неизменяемого результата.

Возвращаемое значение: Set<T> (пустое и неизменяемое). Аргументы отсутствуют.

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

Пример 1: простое получение пустого множества и проверка размера.

import java.util.*;

public class E1 {
    public static void main(String[] args) {
        Set s = Collections.emptySet();
        System.out.println(s.size());
        System.out.println(s.isEmpty());
    }
}
0
true

Пример 2: попытка изменить множество приводит к исключению.

import java.util.*;

public class E2 {
    public static void main(String[] args) {
        Set s = Collections.emptySet();
        s.add("a");
    }
}
Exception in thread "main" java.lang.UnsupportedOperationException
    at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
    at java.base/java.util.ImmutableCollections$AbstractImmutableSet.add(ImmutableCollections.java:348)
    at E2.main(E2.java:7)

Пример 3: получение модифицируемой копии из пустого множества.

import java.util.*;

public class E3 {
    public static void main(String[] args) {
        Set s = new HashSet<>(Collections.emptySet());
        s.add("x");
        System.out.println(s);
    }
}
[x]

Пример 4: сравнение с Java 9+ Set.of().

import java.util.*;

public class E4 {
    public static void main(String[] args) {
        Set a = Collections.emptySet();
        Set b = Set.of();
        System.out.println(a.equals(b));
        System.out.println(a == b); // может быть true или false в зависимости от реализации
    }
}
true
true

Аналоги в Java и их особенности

  • Collections.EMPTY_SET - устаревшая по семантике константа без generics. Требуется приведение типов при использовании в обобщённых контекстах; предпочтение отдаётся Collections.emptySet().
  • Set.of() (Java 9+) - возвращает неизменяемое множество; для пустого множества используется Set.of(). Отличие небольшое: Set.of() часть новой реализации неизменяемых коллекций.
  • Collections.singleton(element) - создаёт неизменяемое множество с одним элементом, применяется вместо пустого, когда нужен единственный элемент.
  • new HashSet<>() - создаёт пустое модифицируемое множество; предпочтение зависит от необходимости изменения содержимого.
  • Guava ImmutableSet.of() - альтернатива из сторонних библиотек с дополнительными гарантиями и вспомогательными методами.

Выбор зависит от требуемой мутабельности и окружения: для возвращаемого неизменяемого значения обычно подходит Collections.emptySet() или Set.of(), для изменяемого требуется создание новой коллекции.

Похожие конструкции в других языках

Краткие примеры и отличия от Java.

JavaScript - встроенный Set (мутируемый):

// Node.js / браузер
const s = new Set();
console.log(s.size);
0

Отличие: по умолчанию множество в JS изменяемое; для иммутабельности требуются внешние приёмы.

Python - mutable set и immutable frozenset:

# Python
s = set()
print(len(s))
fs = frozenset()
print(len(fs))
0
0

Отличие: frozenset предоставляет неизменяемое множество аналогично Collections.emptySet(), но типы и операции отличаются.

PHP - пустой массив как множество (часто) или SplObjectStorage:

// PHP
$s = [];
var_dump(count($s));
int(0)

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

C# - пустая коллекция через Enumerable.Empty<T>() или new HashSet<T>():

using System;
using System.Linq;

class P {
    static void Main() {
        var e = Enumerable.Empty();
        Console.WriteLine(e.Count());
        var hs = new HashSet();
        Console.WriteLine(hs.Count);
    }
}
0
0

Отличие: Enumerable.Empty<T>() возвращает пустой последовательный набор (IEnumerable), но не обязательно коллекцию с операциями множества.

Go - пустое множество моделируется через map[T]struct{}:

package main
import "fmt"
func main() {
    s := make(map[string]struct{})
    fmt.Println(len(s))
}
0

Отличие: в Go нет встроенного типа set; используется map с пустой структурой.

Kotlin - пустое множество через emptySet<T>() или setOf():

fun main() {
    val s = emptySet()
    println(s.size)
    println(s === emptySet()) // возможна единичная реализация
}
0
true

Отличие: Kotlin предоставляет удобные функции и подходит для использования в JVM и Kotlin-коде; семантика близка к Java.

Типичные ошибки и последствия

Ошибка 1: попытка модификации возвращённого множества.

import java.util.*;

public class Err1 {
    public static void main(String[] args) {
        Set s = Collections.emptySet();
        s.add("a");
    }
}
java.lang.UnsupportedOperationException
    at ...

Ошибка 2: использование Collections.EMPTY_SET без приведения типов или с ожиданием generics может вызвать предупреждения компилятора и возможные исключения времени выполнения при неправильном приведении.

import java.util.*;

public class Err2 {
    public static void main(String[] args) {
        Set<String> s = (Set<String>) Collections.EMPTY_SET; // unchecked cast
        // компилятор выдаст предупреждение, но выполнение может быть корректным
    }
}
(Warning: unchecked cast)

Ошибка 3: ожидание наличия уникальной идентичности (==) между вызовами. equals возвращает true, но ссылка может не совпадать в разных реализациях; ориентироваться следует на equals(), а не на ==.

Изменения в реализации и истории

  • Generics: поддержка параметров типа появилась с Java 5, что позволило объявить метод как <T> Set<T> emptySet().
  • Java 9: появление фабричных методов коллекций (Set.of(), List.of(), Map.of()), которые предоставляют альтернативу для создания неизменяемых коллекций, в том числе пустых.
  • Других существенных изменений в поведении Collections.emptySet() в последних версиях не отмечено; метод остаётся удобным способом вернуть типобезопасное пустое множество.

Расширенные и нетипичные примеры применения

Пример A: возврат текстуального API-метода вместо null для упрощения клиентского кода.

Пример java
import java.util.*;

public class AdvA {
    public static Set<String> findTags(String s) {
        if (s == null || s.isBlank()) return Collections.emptySet();
        // условная логика разбора
        return Set.of("tag1");
    }

    public static void main(String[] args) {
        System.out.println(findTags(null));
        System.out.println(findTags(""));
    }
}
[]
[]

Пояснение: возвращение пустого множества избавляет от проверок на null у вызывающей стороны.

Пример B: использование в качестве ключа в Map и поведение при поиске.

Пример java
import java.util.*;

public class AdvB {
    public static void main(String[] args) {
        Map<Set<String>, Integer> map = new HashMap<>();
        map.put(Collections.emptySet(), 1);
        System.out.println(map.get(Collections.emptySet()));
    }
}
1

Пояснение: equals для пустых множеств соблюдается, потому поиск по другому пустому множеству возвращает значение.

Пример C: создание специализированного пустого EnumSet и сравнение с Collections.emptySet().

Пример java
import java.util.*;

enum Color { RED, GREEN }

public class AdvC {
    public static void main(String[] args) {
        Set<Color> enumEmpty = EnumSet.noneOf(Color.class);
        Set<Color> collEmpty = Collections.emptySet();
        System.out.println(enumEmpty.getClass());
        System.out.println(collEmpty.getClass());
        System.out.println(enumEmpty.equals(collEmpty));
    }
}
class java.util.RegularEnumSet
class java.util.ImmutableCollections$EmptySet
true

Пояснение: EnumSet.noneOf() возвращает специализированную реализацию, оптимизированную для перечислений; хотя множества равны по содержимому, их классы различаются и одно из них остаётся модифицируемым.

Пример D: использование с потоками и коллекционными операциями.

Пример java
import java.util.*;
import java.util.stream.*;

public class AdvD {
    public static void main(String[] args) {
        Set<Integer> s = Collections.emptySet();
        List<Integer> list = s.stream().collect(Collectors.toList());
        System.out.println(list);
    }
}
[]

Пояснение: пустое множество корректно интегрируется в Stream API и другие утилиты коллекций.

Пример E: синхронизированная оболочка над пустым множеством (всё равно неизменяема).

Пример java
import java.util.*;

public class AdvE {
    public static void main(String[] args) {
        Set<String> sync = Collections.synchronizedSet(Collections.emptySet());
        System.out.println(sync.size());
        try { sync.add("x"); } catch (Exception ex) { System.out.println(ex.getClass().getSimpleName()); }
    }
}
0
UnsupportedOperationException

Пояснение: синхронизированная оболочка не делает коллекцию изменяемой; защита нужна только для многопоточного доступа к изменяемой коллекции.

джава Collections.emptySet() function comments

En
Collections.emptySet() Возвращает пустой неизменяемый набор