Что такое интерфейс Consumer?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Интерфейс Consumer в Java
Consumer — это функциональный интерфейс из пакета java.util.function, который представляет операцию, принимающую один параметр и не возвращающую результат. Consumer используется для выполнения побочных эффектов (side effects) над переданным аргументом, таких как вывод данных, логирование, сохранение в базу данных или другие действия, которые не требуют возврата значения.
Consumer являются обратными вызовами (callbacks), позволяя передавать код как параметр функции.
Определение Consumer
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
// Метод по умолчанию для цепочки consumers
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> {
accept(t);
after.accept(t);
};
}
}
Основной метод accept(T t) принимает значение типа T и выполняет над ним операцию. Метод по умолчанию andThen() позволяет объединять несколько consumers в цепочку.
Простые примеры использования
Вывод элементов списка:
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class ConsumerExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Иван", "Мария", "Петр");
// Способ 1: с помощью람-выражения
Consumer<String> printer = name -> System.out.println(name);
names.forEach(printer);
// Способ 2: напрямую в forEach
names.forEach(name -> System.out.println("Привет, " + name));
// Способ 3: с использованием ссылки на метод
names.forEach(System.out::println);
}
}
Consumer с логированием
import java.util.function.Consumer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class LoggingConsumer {
// Consumer для логирования с временем
static Consumer<String> logger = message -> {
String timestamp = LocalDateTime.now()
.format(DateTimeFormatter.ISO_LOCAL_TIME);
System.out.println("[" + timestamp + "] " + message);
};
public static void main(String[] args) {
logger.accept("Приложение запущено");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
logger.accept("Операция завершена");
}
}
Consumer в Stream API
Consumer часто используется с потоками данных для обработки элементов:
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class StreamConsumer {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// forEach принимает Consumer
numbers.stream()
.filter(n -> n % 2 == 0)
.forEach(n -> System.out.println("Чётное число: " + n));
// Использование peek для отладки (тоже Consumer)
numbers.stream()
.filter(n -> n > 2)
.peek(n -> System.out.println("Обрабатываю: " + n))
.map(n -> n * 2)
.forEach(n -> System.out.println("Результат: " + n));
}
}
Consumer с объектами
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
public class UserProcessor {
static class User {
String name;
int age;
User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "User{" + "name='" + name + "', age=" + age + "'}'";
}
}
public static void main(String[] args) {
List<User> users = Arrays.asList(
new User("Иван", 28),
new User("Мария", 35),
new User("Петр", 22)
);
// Consumer для сохранения в БД (имитация)
Consumer<User> saveToDb = user -> {
System.out.println("Сохраняю: " + user.name + " в БД");
// db.save(user);
};
// Consumer для отправки уведомления
Consumer<User> sendNotification = user -> {
System.out.println("Отправляю уведомление пользователю " + user.name);
// emailService.send(user.email, "Добро пожаловать!");
};
users.forEach(saveToDb.andThen(sendNotification));
}
}
Цепочка Consumer с andThen()
import java.util.function.Consumer;
public class ConsumerChain {
public static void main(String[] args) {
// Создаём несколько consumers
Consumer<Integer> printNumber = n -> System.out.println("Число: " + n);
Consumer<Integer> printSquare = n -> System.out.println("Квадрат: " + (n * n));
Consumer<Integer> printCube = n -> System.out.println("Куб: " + (n * n * n));
// Объединяем в цепочку с помощью andThen()
Consumer<Integer> chain = printNumber
.andThen(printSquare)
.andThen(printCube);
// Выполняем всю цепочку для каждого числа
for (int i = 1; i <= 3; i++) {
System.out.println("--- Число " + i + " ---");
chain.accept(i);
}
}
}
// Результат:
// --- Число 1 ---
// Число: 1
// Квадрат: 1
// Куб: 1
// --- Число 2 ---
// Число: 2
// Квадрат: 4
// Куб: 8
BiConsumer — Consumer с двумя параметрами
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
public class BiConsumerExample {
public static void main(String[] args) {
Map<String, Integer> ages = new HashMap<>();
ages.put("Иван", 28);
ages.put("Мария", 35);
ages.put("Петр", 22);
// BiConsumer для forEach в Map
BiConsumer<String, Integer> printEntry = (name, age) ->
System.out.println(name + " - " + age + " лет");
ages.forEach(printEntry);
}
}
Практический пример: обработчик событий
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class EventSystem {
static class Event {
String type;
String message;
Event(String type, String message) {
this.type = type;
this.message = message;
}
}
static class EventBus {
private List<Consumer<Event>> subscribers = new ArrayList<>();
// Подписываем consumer на события
public void subscribe(Consumer<Event> listener) {
subscribers.add(listener);
}
// Отправляем событие всем подписчикам
public void emit(Event event) {
subscribers.forEach(listener -> listener.accept(event));
}
}
public static void main(String[] args) {
EventBus bus = new EventBus();
// Логирование
Consumer<Event> logger = event ->
System.out.println("[LOG] " + event.type + ": " + event.message);
// Отправка уведомления
Consumer<Event> notifier = event -> {
if ("error".equals(event.type)) {
System.out.println("[ALERT] Ошибка: " + event.message);
}
};
// Сохранение в архив
Consumer<Event> archiver = event ->
System.out.println("[ARCHIVE] Сохранено в архив: " + event.type);
// Подписываемся
bus.subscribe(logger);
bus.subscribe(notifier);
bus.subscribe(archiver);
// Генерируем события
bus.emit(new Event("info", "Приложение запущено"));
bus.emit(new Event("error", "Потеря соединения"));
}
}
Consumer vs Function
| Consumer | Function |
|---|---|
| Принимает параметр, не возвращает результат | Принимает параметр, возвращает результат |
void accept(T t) | R apply(T t) |
| Используется для побочных эффектов | Используется для трансформации |
| Пример: вывод, логирование, сохранение | Пример: фильтр, маппинг, расчёты |
Когда использовать Consumer
- Логирование и отладка — вывод информации
- Сохранение данных — в БД, кеш, файл
- Отправка уведомлений — письма, SMS, push
- Обработка событий — реакция на действия пользователя
- Валидация и проверки — проверка constraints
- Трансформация состояния — изменение объектов
Consumer — это элегантный способ передать функцию-обработчик в метод, не создавая отдельный класс, делая код более выразительным и функциональным.