Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Методы Compute в Map Java: Функции

forEach() не единственный метод в Map, работающий с лямбда-функциями. Кроме него есть набор методов compute. Они позволяют вычислять значение динамически, базируясь на том, существует ли запрашиваемый ключ в коллекции или нет.

compute()

Метод compute() обновляет значение ключа в Map, на основе логики, заданной внутри лямбда-функции. Эта лямбда-функция получает на вход текущее значение ключа, выполняет с ним необходимые операции и возвращает новое значение.

import java.util.List;
import java.util.HashMap;

public class WordCountExample {
    public static void main(String[] args) {
        var words = List.of("apple", "banana", "apple", "orange", "banana", "apple");
        var wordCount = new HashMap<String, Integer>();

        words.forEach((word) -> {
            // Для данной задачи key не используется
            wordCount.compute(word, (key, count) -> count == null ? 1 : count + 1);
        });

        System.out.println(wordCount); // => {orange=1, banana=2, apple=3}
    }
}

В примере выше, метод compute() вызывается для каждого слова из списка. Лямбда-функция принимает на вход ключ и значение, которое является количеством повторений слова в списке. Дальше в зависимости от того, первый ли раз встречается это слово или нет, изменяется количество повторений. Без compute() нам бы пришлось написать код похожий на этот:

words.forEach((word) -> {
    var count = wordCount.get(word);
    wordCount.put(word, count == null ? 1 : count + 1);
});

Здесь мы встречаемся с интересной особенностью сокращенной версии лямбда-функции. В примерах выше не прописан явно возврат, но он выполняется, иначе значение было бы невозможно использовать. Возврат, в сокращенной версии лямбда-функции, выполняется автоматически. Полная версия выглядела бы так:

wordCount.compute(word, (key, count) -> {
    return count == null ? 1 : count + 1;
});

computeIfAbsent()

Метод computeIfAbsent() отличается от compute(), тем, что лямбда вызывается только в том случае, если ключа в коллекции до этого не было. С его помощью, например, реализуется кеш, специальное хранилище, которое хранит данные, полученные в результате выполнения тяжелой операции. Это позволяет экономить ресурсы на повторных запросах, которые проходят уже без вычисления.

import java.util.Map;
import java.util.HashMap;

public class CacheExample {
    private static Map<String, Integer> cache = new HashMap<>();

    public static int computeExpensiveOperation(String key) {
        // Симулируем тяжелую операцию
        return key.length();
    }

    public static int getValue(String key) {
        return cache.computeIfAbsent(key, (k) -> CacheExample.computeExpensiveOperation(k));
    }

    public static void main(String[] args) {
        System.out.println(getValue("hello")); // => 5
        System.out.println(getValue("java"));  // => 4
        System.out.println(getValue("hello")); // => 5 (получено из кеша, вычисление не выполняется)
    }
}

computeIfPresent()

Метод computeIfPresent() отличается от compute() тем, что лямбда вызывается только в том случае, если ключ уже был добавлен в коллекцию. Ниже пример кода, который применяет скидку к товарам, находящимся внутри коллекции без проверки того, есть ли они там на самом деле:

import java.util.HashMap;

public class DiscountExample {
    public static void main(String[] args) {
        var prices = new HashMap<String, Double>();
        prices.put("T-shirt", 20.0);
        prices.put("Jeans", 40.0);

        // Применяет 10% скидку только если такой товар существует
        prices.computeIfPresent("Jeans", (key, value) -> value * 0.9);

        // Ничего не происходит, так как такого товара нет
        prices.computeIfPresent("Socks", (key, value) -> value * 0.9);

        System.out.println(prices); // => {T-shirt=20.0, Jeans=36.0}
    }
}

Дополнительные материалы

  1. Метод compute()
  2. Метод computeIfAbsent()
  3. Метод computeIfPresent()

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 6 300 ₽ в месяц
Разработка приложений на языке Java
10 месяцев
с нуля
Старт 2 мая

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»
Изображение Тото

Задавайте вопросы, если хотите обсудить теорию или упражнения. Команда поддержки Хекслета и опытные участники сообщества помогут найти ответы и решить задачу