Что такое функциональный интерфейс Consumer в Java?

Ответ

Consumer — это функциональный интерфейс из пакета java.util.function, который представляет операцию, принимающую один аргумент типа T и не возвращающую результат (void). Используется для выполнения действий с побочными эффектами (side-effects), таких как модификация объекта или вывод данных.

Сигнатура:

void accept(T t);

Примеры использования:

  1. Простой Consumer для вывода в консоль:

    Consumer<String> printer = s -> System.out.println(s);
    printer.accept("Hello!"); // Выведет: Hello!
  2. Consumer для модификации коллекции:

    List<String> list = new ArrayList<>(Arrays.asList("a", "b"));
    Consumer<String> addExclamation = s -> list.add(s + "!");
    addExclamation.accept("c");
    // Теперь list содержит: [a, b, c!]
  3. Использование в Stream API с forEach():

    List<String> names = List.of("Alice", "Bob", "Charlie");
    names.forEach(name -> System.out.println("Name: " + name));

Важные методы интерфейса Consumer:

  • default Consumer<T> andThen(Consumer<? super T> after) — позволяет объединять несколько операций в цепочку. Операции выполняются последовательно.
    Consumer<String> log = s -> System.out.print("Log: " + s);
    Consumer<String> save = s -> System.out.print(" | Saved: " + s);
    Consumer<String> pipeline = log.andThen(save);
    pipeline.accept("data"); // Выведет: Log: data | Saved: data

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

Ответ 18+ 🔞

Э, слушай, смотри, вот есть такая штука — Consumer. Это, блядь, как тот чувак в баре, который только потребляет, но нихуя не возвращает. Взял стакан, выпил, поставил — и всё, конец истории. В пакете java.util.function он живёт, и его главная фишка — принять один аргумент типа T и сделать с ним что-то, но ничего не вернуть (void). Чистый побочный эффект, ёпта! Записать куда-то, вывести, изменить — вот его работа.

Вот его главный метод, смотри:

void accept(T t);

Просто взял и принял. Без вопросов.

Ну и примеры, чтобы не быть мудаком, который нихуя не понял:

  1. Простейший Consumer, который орёт в консоль:

    Consumer<String> printer = s -> System.out.println(s);
    printer.accept("Привет, мудила!"); // Напечатает: Привет, мудила!
  2. Consumer, который лезет в коллекцию и там что-то портит:

    List<String> list = new ArrayList<>(Arrays.asList("a", "b"));
    Consumer<String> addExclamation = s -> list.add(s + "!");
    addExclamation.accept("c");
    // Теперь в list: [a, b, c!] — добавил и доволен.
  3. А вот где он реально пашет — в Stream API с forEach():

    List<String> names = List.of("Алиса", "Боб", "Чарли");
    names.forEach(name -> System.out.println("Имя: " + name));
    // Пройдётся по всем и каждого по имени назовёт.

А ещё у него есть хитрая жопа — метод andThen():

  • default Consumer<T> andThen(Consumer<? super T> after) — это чтобы строить цепочки, как дурак на конвейере. Сделал одно действие — потом сразу другое.
    Consumer<String> log = s -> System.out.print("Лог: " + s);
    Consumer<String> save = s -> System.out.print(" | Сохранено: " + s);
    Consumer<String> pipeline = log.andThen(save); // Сцепил, блядь!
    pipeline.accept("данные"); // Выведет: Лог: данные | Сохранено: данные

Где это, блядь, применять? Да везде, где нужно что-то сделать, а не что-то получить. Логирование, запись в файл, отправка уведомления, тыкание палкой в другие объекты — вот это всё его епархия. Главное — процесс, а не результат, в рот меня чих-пых!