← Назад к вопросам

Какие знаешь варианты Set?

2.2 Middle🔥 171 комментариев
#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Варианты Set в Java

Set — это интерфейс коллекции из пакета java.util, который представляет неупорядоченное собрание уникальных элементов. Java предоставляет множество реализаций Set, каждая из которых имеет свои характеристики и применение.

1. HashSet

HashSet — наиболее распространённая реализация Set, основанная на хеш-таблице. Обеспечивает быстрые операции поиска, добавления и удаления.

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

public class HashSetExample {
    public static void main(String[] args) {
        Set<String> fruits = new HashSet<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Apple"); // Дубликат, не добавится

        System.out.println(fruits); // Порядок не гарантирован
        System.out.println("Size: " + fruits.size()); // 2
        System.out.println("Contains Apple: " + fruits.contains("Apple")); // true
    }
}

Характеристики:

  • Время операций: O(1) в среднем
  • Не упорядочена
  • Не потокобезопасна
  • Допускает null элементы (один null)

2. LinkedHashSet

LinkedHashSet — расширение HashSet с сохранением порядка вставки элементов. Использует хеш-таблицу с двусвязным списком.

import java.util.LinkedHashSet;
import java.util.Set;

public class LinkedHashSetExample {
    public static void main(String[] args) {
        Set<String> fruits = new LinkedHashSet<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Cherry");
        fruits.add("Apple"); // Дубликат

        System.out.println(fruits); // [Apple, Banana, Cherry]
        // Порядок вставки сохранён!
    }
}

Характеристики:

  • Время операций: O(1) в среднем
  • Упорядочена по порядку вставки
  • Не потокобезопасна
  • Допускает null элементы

3. TreeSet

TreeSet — отсортированное множество элементов, основанное на красно-чёрном дереве (Red-Black Tree). Элементы хранятся в порядке сортировки.

import java.util.TreeSet;
import java.util.Set;

public class TreeSetExample {
    public static void main(String[] args) {
        Set<Integer> numbers = new TreeSet<>();
        numbers.add(5);
        numbers.add(2);
        numbers.add(8);
        numbers.add(2); // Дубликат
        numbers.add(1);

        System.out.println(numbers); // [1, 2, 5, 8] - отсортировано!

        // Навигационные методы
        TreeSet<Integer> treeSet = (TreeSet<Integer>) numbers;
        System.out.println("First: " + treeSet.first()); // 1
        System.out.println("Last: " + treeSet.last()); // 8
        System.out.println("Lower than 5: " + treeSet.lower(5)); // 2
        System.out.println("Higher than 5: " + treeSet.higher(5)); // 8
    }
}

Характеристики:

  • Время операций: O(log n)
  • Отсортирована в натуральном порядке или по Comparator
  • Не потокобезопасна
  • НЕ допускает null элементы

4. CopyOnWriteArraySet

CopyOnWriteArraySet — потокобезопасное множество, основанное на CopyOnWriteArrayList. При каждой модификации создаётся копия массива.

import java.util.concurrent.CopyOnWriteArraySet;
import java.util.Set;

public class CopyOnWriteArraySetExample {
    public static void main(String[] args) {
        Set<String> fruits = new CopyOnWriteArraySet<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Cherry");

        // Потокобезопасно для многопоточных операций
        for (String fruit : fruits) {
            System.out.println(fruit);
        }
    }
}

Характеристики:

  • Потокобезопасна
  • Хорошо для чтения, плохо для записи (копирование массива)
  • Итерация не требует синхронизации
  • Допускает null элементы

5. Collections.synchronizedSet

synchronizedSet — получение потокобезопасного обёртки для обычного Set.

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

public class SynchronizedSetExample {
    public static void main(String[] args) {
        Set<String> unsafeSet = new HashSet<>();
        Set<String> safeSet = Collections.synchronizedSet(unsafeSet);

        safeSet.add("Apple");
        safeSet.add("Banana");

        // Потокобезопасно
        for (String fruit : safeSet) {
            System.out.println(fruit);
        }
    }
}

Характеристики:

  • Оборачивает обычный Set
  • Потокобезопасна
  • Требует синхронизации при итерации

6. EnumSet

EnumSet — специализированное множество для работы с элементами enum. Очень эффективно по памяти и производительности.

import java.util.EnumSet;
import java.util.Set;

public enum Color {
    RED, GREEN, BLUE, YELLOW, ORANGE
}

public class EnumSetExample {
    public static void main(String[] args) {
        Set<Color> colors = EnumSet.of(Color.RED, Color.BLUE, Color.GREEN);
        System.out.println(colors); // [RED, BLUE, GREEN]

        // Все элементы enum
        Set<Color> allColors = EnumSet.allOf(Color.class);
        System.out.println("All colors: " + allColors);

        // Диапазон enum
        Set<Color> range = EnumSet.range(Color.RED, Color.BLUE);
        System.out.println("Range: " + range);
    }
}

Характеристики:

  • Самый эффективный вариант для enum
  • Использует битовую маску
  • Очень быстро
  • Только для enum типов

7. NavigableSet

NavigableSet — расширение SortedSet с дополнительными методами навигации. Реализуется TreeSet.

import java.util.NavigableSet;
import java.util.TreeSet;

public class NavigableSetExample {
    public static void main(String[] args) {
        NavigableSet<Integer> numbers = new TreeSet<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        numbers.add(40);
        numbers.add(50);

        // Методы NavigableSet
        System.out.println("Floor of 35: " + numbers.floor(35)); // 30
        System.out.println("Ceiling of 35: " + numbers.ceiling(35)); // 40
        System.out.println("Lower of 30: " + numbers.lower(30)); // 20
        System.out.println("Higher of 30: " + numbers.higher(30)); // 40
        System.out.println("Descending set: " + numbers.descendingSet()); // [50, 40, 30, 20, 10]
        System.out.println("Head set (exclusive 30): " + numbers.headSet(30, false)); // [10, 20]
    }
}

8. Custom Set с Comparator

import java.util.Set;
import java.util.TreeSet;

public class CustomSetExample {
    static class Person implements Comparable<Person> {
        private String name;
        private int age;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public int compareTo(Person other) {
            return Integer.compare(this.age, other.age);
        }

        @Override
        public String toString() {
            return name + "(" + age + ")";
        }
    }

    public static void main(String[] args) {
        Set<Person> people = new TreeSet<>();
        people.add(new Person("Alice", 30));
        people.add(new Person("Bob", 25));
        people.add(new Person("Charlie", 35));

        System.out.println(people); // Отсортировано по возрасту
    }
}

Таблица сравнения

SetУпорядоченаПотокобезопаснаПроизводительностьПамятьNull
HashSetНетНетO(1)СредняяДа
LinkedHashSetПо вставкеНетO(1)ВышеДа
TreeSetПо сортировкеНетO(log n)ВышеНет
CopyOnWriteArraySetДаДаO(n)ВышеДа
synchronizedSetЗависитДаЗависитЗависитЗависит
EnumSetПо enumНетO(1)НизкаяНет

Рекомендации по использованию

  • HashSet — стандартный выбор для большинства случаев
  • LinkedHashSet — когда важен порядок вставки
  • TreeSet — для отсортированного набора или навигационных операций
  • CopyOnWriteArraySet — для многопоточных приложений с частым чтением
  • EnumSet — для работы с enum, всегда первый выбор для enum
  • Collections.synchronizedSet() — для обёртки существующего Set