Что такое Consumer в Java и как его используют?

Ответ

Consumer<T> — это функциональный интерфейс из пакета java.util.function. Он представляет операцию, которая принимает один аргумент типа T и не возвращает результата (void).

Основное назначение: выполнение действий (побочных эффектов) над объектом, например, модификация, логирование или вывод.

Простой пример:

Consumer<String> printer = s -> System.out.println(s);
printer.accept("Hello, Consumer!"); // Выведет: Hello, Consumer!

Consumer<String> upperCasePrinter = str -> {
    String upper = str.toUpperCase();
    System.out.println(upper);
};
upperCasePrinter.accept("test"); // Выведет: TEST

Частое применение в Stream API:

List<String> names = Arrays.asList("Anna", "Bob", "Clara");
// forEach принимает Consumer
names.forEach(name -> System.out.println("Processing: " + name));

Композиция Consumers: метод andThen позволяет объединить несколько действий.

Consumer<String> log = s -> System.out.println("Log: " + s);
Consumer<String> notify = s -> System.out.println("Notifying about: " + s);

Consumer<String> fullPipeline = log.andThen(notify);
fullPipeline.accept("event");
// Вывод:
// Log: event
// Notifying about: event

Важно: Consumer предназначен именно для действий с побочными эффектами, а не для преобразования данных (для этого используется Function<T, R>).

Ответ 18+ 🔞

Ну слушай, вот есть у нас в Java эта штука — Consumer<T>. Представь себе такого работягу, который берет один объект, делает с ним что-то полезное (или не очень) и... всё. Ничего не возвращает, просто делает своё дело и идет дальше. Вообще нихуя не отдаёт, только принимает. Как будто ты ему кинул мячик, а он его поймал и положил в карман — и молчок.

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

Вот смотри, простейший пример:

Consumer<String> printer = s -> System.out.println(s);
printer.accept("Hello, Consumer!"); // Выведет: Hello, Consumer!

Видишь? Принял строку, выплюнул её в консоль — и свободен. Никаких возвратов, чисто действие.

А ещё его часто в Stream API юзают, там где forEach:

List<String> names = Arrays.asList("Anna", "Bob", "Clara");
names.forEach(name -> System.out.println("Processing: " + name));

Тут forEach как раз ждёт от тебя Consumer — "скажи, что делать с каждым элементом, а результат мне нахуй не нужен".

А вот ещё фишка — их можно цепочкой собирать, как паровозик! Есть метод andThen:

Consumer<String> log = s -> System.out.println("Log: " + s);
Consumer<String> notify = s -> System.out.println("Notifying about: " + s);

Consumer<String> fullPipeline = log.andThen(notify);
fullPipeline.accept("event");
// Выведет:
// Log: event
// Notifying about: event

Сначала один отработает, потом второй. Красота, блядь!

Но запомни раз и навсегда: Consumer — это про действия, про побочные эффекты. Если тебе нужно взять объект, преобразовать его и получить что-то на выходе — это уже не сюда, это к его братану Function<T, R>. А Consumer — он простой работяга: принял, сделал, забыл. В рот меня чих-пых, иногда и такое нужно.