☕ Java

Множества (Set) в Java 17: подробное руководство

Множества (Set) в Java

Что такое множество и зачем оно нужно?

Представь, что у тебя есть коробка, в которую можно класть только уникальные предметы. Если ты попробуешь положить туда два одинаковых яблока, второе просто не поместится — в коробке уже есть такое яблоко. В программировании такая «коробка» называется множеством (Set).

Множество — это коллекция, которая хранит элементы без повторений. Порядок элементов в обычном множестве не важен. Главное правило: каждый элемент может встречаться только один раз.

Когда это полезно?

  • Нужно собрать только уникальные ингредиенты для пиццы
  • Хранить список контактов без дубликатов
  • Проверять, есть ли товар в списке обязательных
  • Объединять два списка покупок, убирая повторы

Основной синтаксис

В Java 17 чаще всего используется HashSet — самая быстрая и простая реализация множества. Вот как с ним работать:

// Создаем пустое множество для строк
Set<String> названия = new HashSet<>();

// Добавляем элементы
названия.add("Яблоко");
названия.add("Банан");
названия.add("Яблоко"); // Не добавится — уже есть!

// Проверяем размер
System.out.println(названия.size()); // Выведет: 2

// Проверяем, есть ли элемент
if (названия.contains("Банан")) {
    System.out.println("Банан есть в множестве");
}

// Удаляем элемент
названия.remove("Банан");

// Перебираем все элементы
for (String фрукт : названия) {
    System.out.println(фрукт);
}

Разбор типичных задач

Задача 1: Уникальные ингредиенты пиццы

Пользователь вводит ингредиенты через запятую. Нужно вывести только уникальные.

import java.util.*;

public class УникальныеИнгредиенты {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("Введите ингредиенты через запятую:");
        String ввод = scanner.nextLine();
        
        // Разделяем строку по запятым
        String[] части = ввод.split(",");
        
        // Создаем множество для уникальных ингредиентов
        Set<String> ингредиенты = new HashSet<>();
        
        // Добавляем каждый ингредиент (пробелы убираем)
        for (String ингредиент : части) {
            ингредиенты.add(ингредиент.trim());
        }
        
        System.out.println("Уникальные ингредиенты: " + ингредиенты);
        System.out.println("Количество: " + ингредиенты.size());
    }
}

Пример работы:

Введите ингредиенты через запятую:
сыр, помидор, сыр, базилик, помидор, оливки
Уникальные ингредиенты: [сыр, помидор, базилик, оливки]
Количество: 4

Задача 2: Объединение списков покупок

У вас есть свой список, гости добавляют свои. Нужно получить итоговый список без повторов.

import java.util.*;

public class СписокПокупок {
    public static void main(String[] args) {
        // Ваш предварительный список
        Set<String> мойСписок = new HashSet<>();
        мойСписок.add("Кола");
        мойСписок.add("Чипсы");
        мойСписок.add("Печенье");
        
        // Гости добавили свои пожелания
        Set<String> гостиДобавили = new HashSet<>();
        гостиДобавили.add("Сок");
        гостиДобавили.add("Чипсы");  // Повторяется!
        гостиДобавили.add("Орехи");
        
        // Объединяем — все уникальные элементы из обоих множеств
        мойСписок.addAll(гостиДобавили);
        
        System.out.println("Итоговый список покупок:");
        for (String товар : мойСписок) {
            System.out.println("- " + товар);
        }
    }
}

Пример работы:

Итоговый список покупок:
- Кола
- Чипсы
- Печенье
- Сок
- Орехи

Задача 3: Удаление лишнего из списка

У вас есть список продуктов. Некоторые вы решили убрать. Нужно удалить их из множества.

import java.util.*;

public class УдалениеЛишнего {
    public static void main(String[] args) {
        Set<String> покупки = new HashSet<>();
        покупки.add("Молоко");
        покупки.add("Хлеб");
        покупки.add("Яйца");
        покупки.add("Сыр");
        покупки.add("Масло");
        
        System.out.println("Текущий список: " + покупки);
        System.out.println("Что убрать? Введите через запятую:");
        
        Scanner scanner = new Scanner(System.in);
        String ввод = scanner.nextLine();
        String[] удалить = ввод.split(",");
        
        for (String товар : удалить) {
            покупки.remove(товар.trim());
        }
        
        System.out.println("Осталось: " + покупки);
    }
}

Пример работы:

Текущий список: [Молоко, Хлеб, Яйца, Сыр, Масло]
Что убрать? Введите через запятую:
Хлеб, Масло
Осталось: [Молоко, Яйца, Сыр]

Задача 4: Проверка наличия товаров

В магазине есть обязательный список товаров. Нужно проверить, все ли они есть на складе.

import java.util.*;

public class ПроверкаТоваров {
    public static void main(String[] args) {
        Set<String> обязательные = new HashSet<>();
        обязательные.add("Хлеб");
        обязательные.add("Молоко");
        обязательные.add("Яйца");
        
        Scanner scanner = new Scanner(System.in);
        System.out.println("Введите товары на складе через запятую:");
        String ввод = scanner.nextLine();
        
        Set<String> склад = new HashSet<>();
        for (String товар : ввод.split(",")) {
            склад.add(товар.trim());
        }
        
        // Проверяем, все ли обязательные товары есть на складе
        if (склад.containsAll(обязательные)) {
            System.out.println("Все обязательные товары в наличии!");
        } else {
            System.out.println("Не хватает товаров:");
            // Находим, каких товаров не хватает
            Set<String> копия = new HashSet<>(обязательные);
            копия.removeAll(склад);
            for (String товар : копия) {
                System.out.println("- " + товар);
            }
        }
    }
}

Частые ошибки новичков

  1. Забывают импортировать java.util.* — без этого Set и HashSet не будут работать.
  2. Пытаются обратиться по индексу — во множестве нет индексов, элементы не упорядочены. Используй цикл for или contains().
  3. Думают, что порядок сохраняется — в HashSet порядок не гарантирован. Если нужен порядок, используй LinkedHashSet.
  4. Путают remove() и removeAll() — remove("А") удаляет один элемент "А", а removeAll(другоеМножество) удаляет все элементы, которые есть в другом множестве.
  5. Не обрабатывают пробелы — при split(",") у строк могут остаться пробелы. Всегда используй trim().

Итоговый пример: Записная книжка контактов

Создадим программу, которая хранит имена контактов (уникальные) и номера телефонов. Если контакт с таким именем уже есть, программа сообщит об этом.

import java.util.*;

public class ЗаписнаяКнижка {
    public static void main(String[] args) {
        // Множество для хранения имен (уникальные)
        Set<String> имена = new HashSet<>();
        // Карта для хранения имени и телефона (понадобится отдельно)
        Map<String, String> телефоны = new HashMap<>();
        
        Scanner scanner = new Scanner(System.in);
        
        while (true) {
            System.out.println("\n1. Добавить контакт");
            System.out.println("2. Показать все контакты");
            System.out.println("3. Выход");
            System.out.print("Выберите действие: ");
            
            String выбор = scanner.nextLine();
            
            if (выбор.equals("1")) {
                System.out.print("Введите имя: ");
                String имя = scanner.nextLine();
                
                // Проверяем, есть ли уже такое имя
                if (имена.contains(имя)) {
                    System.out.println("Контакт с таким именем уже существует!");
                } else {
                    System.out.print("Введите номер телефона: ");
                    String телефон = scanner.nextLine();
                    
                    имена.add(имя);
                    телефоны.put(имя, телефон);
                    System.out.println("Контакт добавлен!");
                }
            } else if (выбор.equals("2")) {
                if (имена.isEmpty()) {
                    System.out.println("Записная книжка пуста.");
                } else {
                    System.out.println("Ваши контакты:");
                    for (String имя : имена) {
                        System.out.println(имя + ": " + телефоны.get(имя));
                    }
                }
            } else if (выбор.equals("3")) {
                System.out.println("До свидания!");
                break;
            } else {
                System.out.println("Неверный ввод. Попробуйте снова.");
            }
        }
    }
}

Пример работы:

1. Добавить контакт
2. Показать все контакты
3. Выход
Выберите действие: 1
Введите имя: Анна
Введите номер телефона: 8-900-123-45-67
Контакт добавлен!

1. Добавить контакт
2. Показать все контакты
3. Выход
Выберите действие: 1
Введите имя: Анна
Контакт с таким именем уже существует!

Множества — это простой и мощный инструмент для работы с уникальными данными. Они помогают избегать дубликатов, быстро проверять наличие элементов и объединять коллекции без лишних повторов. Используй их, когда нужно гарантировать, что каждый элемент встречается только один раз!