Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Словари: Map и HashMap

Словарь (Map) хранит пары «ключ — значение»: телефон по имени, цену по названию товара, количество по слову. По ключу значение находится сразу, без перебора всех элементов.

Создание и чтение

Основная реализация — HashMap. В угловых скобках указывают два типа: ключа и значения. put() добавляет пару, get() возвращает значение по ключу:

void main() {
    Map<String, Integer> ages = new HashMap<>();
    ages.put("Анна", 28);
    ages.put("Олег", 35);
    IO.println(ages.get("Анна"));
    IO.println(ages.size());
}

Результат:

28
2

Ключи в словаре уникальны. Повторный put() с тем же ключом заменяет старое значение.

Если ключа нет

Для отсутствующего ключа get() возвращает null. Метод getOrDefault() позволяет указать запасное значение, а containsKey() — просто проверить ключ:

void main() {
    Map<String, Double> prices = new HashMap<>();
    prices.put("чай", 4.5);
 
    IO.println(prices.get("кофе"));
    IO.println(prices.getOrDefault("кофе", 0.0));
    IO.println(prices.containsKey("чай"));
}

Результат:

null
0.0
true

Изменение и удаление

put() перезаписывает значение, remove() удаляет пару по ключу. Map.of() создаёт небольшой неизменяемый словарь:

void main() {
    Map<String, Integer> stock = new HashMap<>(Map.of("яблоки", 10, "груши", 4));
    stock.put("яблоки", 7);
    stock.remove("груши");
    IO.println(stock);
}

Результат:

{яблоки=7}

Подсчёт с merge()

Метод merge() удобен для счётчиков: если ключа нет, он кладёт начальное значение, а если есть — объединяет старое и новое значение функцией. Integer::sum означает «сложить два числа»:

void main() {
    String text = "кот пёс кот рыба кот пёс";
    Map<String, Integer> counts = new TreeMap<>();
    for (String word : text.split(" ")) {
        counts.merge(word, 1, Integer::sum);
    }
    IO.println(counts);
}

Результат:

{кот=3, пёс=2, рыба=1}

Запись Integer::sum — ссылка на метод; подробно они разобраны в главе об обобщениях и лямбдах.

Порядок ключей

HashMap, как и HashSet, не хранит порядок. TreeMap из примера выше держит ключи отсортированными, а LinkedHashMap помнит порядок добавления:

void main() {
    Map<String, Integer> menu = new LinkedHashMap<>();
    menu.put("суп", 5);
    menu.put("салат", 4);
    menu.put("десерт", 3);
    for (Map.Entry<String, Integer> item : menu.entrySet()) {
        IO.println(item.getKey() + ": " + item.getValue() + " €");
    }
}

Результат:

суп: 5 €
салат: 4 €
десерт: 3 €

entrySet() возвращает все пары, а у каждой пары есть getKey() и getValue(). Другие способы обойти словарь — в следующем уроке.

Частая ошибка

Если значение отсутствующего ключа сразу положить в int, Java попытается превратить null в число и упадёт:

void main() {
    Map<String, Integer> stock = Map.of("чай", 3);
    int coffee = stock.get("кофе");
}

Результат:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because the return value of "java.util.Map.get(Object)" is null

Используйте getOrDefault("кофе", 0) или проверьте ключ через containsKey().

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.