🎯 Kotlin

Mengen (Set) in Kotlin 1.9: Eine ausführliche Anleitung

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

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

Множество хранит только уникальные элементы. Если попытаться добавить в него то, что уже есть, ничего не произойдёт. Это очень удобно, когда нужно избавиться от дубликатов или проверить, есть ли что-то в коллекции.

Как создать множество

В Kotlin 1.9 есть два вида множеств:

  • setOf() — неизменяемое множество (нельзя добавить или удалить элементы)
  • mutableSetOf() — изменяемое множество (можно менять)
// Неизменяемое множество
val fruits = setOf("яблоко", "банан", "апельсин", "яблоко")
println(fruits) // [яблоко, банан, апельсин] — дубликат удалён

// Изменяемое множество
val numbers = mutableSetOf(1, 2, 3)
numbers.add(4)    // добавили 4
numbers.add(2)    // 2 уже есть — ничего не произойдёт
numbers.remove(1) // удалили 1
println(numbers)  // [2, 3, 4]

Основные операции с множествами

Вот самые полезные действия, которые можно делать с множествами:

val set1 = setOf(1, 2, 3, 4)
val set2 = setOf(3, 4, 5, 6)

// Объединение — всё, что есть в первом ИЛИ во втором
val union = set1.union(set2) // [1, 2, 3, 4, 5, 6]

// Пересечение — только то, что есть И в первом, И во втором
val intersect = set1.intersect(set2) // [3, 4]

// Разность — то, что есть в первом, но нет во втором
val diff = set1.subtract(set2) // [1, 2]

// Проверка вхождения
println(3 in set1) // true
println(10 in set1) // false

Как решать задачи с множествами

Давай разберём типичные задачи, похожие на те, что ты будешь решать.

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

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

fun main() {
    println("Введите ингредиенты через запятую:")
    val input = readLine() ?: ""
    
    // Разделяем строку на части, убираем лишние пробелы
    val ingredients = input.split(",").map { it.trim() }
    
    // Превращаем список в множество — дубликаты исчезнут
    val uniqueIngredients = ingredients.toSet()
    
    println("Уникальные ингредиенты:")
    for (item in uniqueIngredients) {
        println("- $item")
    }
}

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

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

fun main() {
    val myList = mutableSetOf("хлеб", "молоко", "сыр", "яблоки")
    
    println("Мой список: $myList")
    println("Введите покупки друга через запятую:")
    val friendInput = readLine() ?: ""
    
    val friendItems = friendInput.split(",").map { it.trim() }
    
    // Добавляем всё из списка друга в наше множество
    myList.addAll(friendItems)
    
    println("Итоговый список покупок: $myList")
}

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

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

fun main() {
    val shoppingList = mutableSetOf("молоко", "хлеб", "яйца", "сыр", "колбаса")
    
    println("Текущий список: $shoppingList")
    println("Что нужно удалить? Введите через запятую:")
    val removeInput = readLine() ?: ""
    
    val toRemove = removeInput.split(",").map { it.trim() }
    
    // Удаляем все указанные элементы
    shoppingList.removeAll(toRemove)
    
    println("Обновлённый список: $shoppingList")
}

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

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

fun main() {
    val required = setOf("хлеб", "молоко", "яйца", "масло")
    
    println("Обязательные товары: $required")
    println("Введите товары на складе через запятую:")
    val stockInput = readLine() ?: ""
    
    val inStock = stockInput.split(",").map { it.trim() }.toSet()
    
    // Проверяем, все ли обязательные товары есть на складе
    if (inStock.containsAll(required)) {
        println("Все товары есть в наличии!")
    } else {
        val missing = required.subtract(inStock)
        println("Не хватает: $missing")
    }
}

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

  • Путают множество и список: В списке (List) элементы могут повторяться и хранятся по порядку. В множестве — только уникальные, порядок не гарантируется.
  • Пытаются обратиться по индексу: У множества нет индексов. Нельзя написать mySet[0]. Только перебирать через цикл или проверять наличие.
  • Забывают про mutableSetOf: Если нужно добавлять или удалять элементы, используй изменяемое множество. Неизменяемое (setOf) не даст этого сделать.
  • Путают subtract и removeAll: subtract создаёт новое множество (разность), а removeAll изменяет текущее, удаляя элементы.

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

Давай соберём всё вместе. Создадим программу, которая хранит имена контактов (без повторов) и позволяет их просматривать.

fun main() {
    val contacts = mutableSetOf()
    
    while (true) {
        println("\n--- Записная книжка ---")
        println("1. Добавить контакт")
        println("2. Показать все контакты")
        println("3. Удалить контакт")
        println("4. Выйти")
        print("Выбери действие: ")
        
        when (readLine()) {
            "1" -> {
                print("Введите имя контакта: ")
                val name = readLine() ?: ""
                if (contacts.add(name)) {
                    println("Контакт '$name' добавлен!")
                } else {
                    println("Контакт '$name' уже существует.")
                }
            }
            "2" -> {
                if (contacts.isEmpty()) {
                    println("Список контактов пуст.")
                } else {
                    println("Твои контакты:")
                    for (contact in contacts) {
                        println("- $contact")
                    }
                }
            }
            "3" -> {
                print("Какое имя удалить? ")
                val name = readLine() ?: ""
                if (contacts.remove(name)) {
                    println("Контакт '$name' удалён.")
                } else {
                    println("Такого контакта нет.")
                }
            }
            "4" -> {
                println("До свидания!")
                break
            }
            else -> println("Неверный выбор, попробуй снова.")
        }
    }
}

В этом примере мы используем множество, чтобы гарантировать, что у нас не будет двух контактов с одинаковым именем. Операции add, remove, isEmpty и цикл for — это всё, что нужно для работы с множествами в реальных задачах.

Запомни главное: множество = уникальность. Если нужно избавиться от дубликатов или проверить наличие элемента — используй Set!