В чем разница между Consumer и Supplier?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Consumer и Supplier: функциональные интерфейсы Java
Consumer и Supplier — это два базовых функциональных интерфейса из пакета java.util.function, которые часто используются в потоках обработки данных (Stream API) и функциональном программировании. Они имеют противоположное поведение: если Consumer принимает значение, то Supplier его производит.
Consumer: потребитель данных
Consumer — это функциональный интерфейс, который принимает один аргумент и не возвращает значение (возвращает void).
Сигнатура:
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
Примеры использования:
// Пример 1: Печать элементов списка
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Consumer<String> printConsumer = name -> System.out.println(name);
names.forEach(printConsumer);
// Пример 2: Обновление объекта
Consumer<User> updateUser = user -> {
user.setLastLoginTime(LocalDateTime.now());
user.setLoginCount(user.getLoginCount() + 1);
};
User user = new User("john", "john@example.com");
updateUser.accept(user);
// Пример 3: Логирование в Stream API
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
.filter(n -> n > 2)
.peek(n -> System.out.println("Filtered: " + n)) // Consumer через peek()
.map(n -> n * 2)
.forEach(System.out::println); // Consumer через forEach()
// Пример 4: Цепочка Consumer с andThen()
Consumer<String> logConsumer = msg -> System.out.println("[LOG] " + msg);
Consumer<String> alertConsumer = msg -> System.out.println("[ALERT] " + msg);
Consumer<String> chainedConsumer = logConsumer.andThen(alertConsumer);
chainedConsumer.accept("Error occurred");
// Вывод:
// [LOG] Error occurred
// [ALERT] Error occurred
Supplier: поставщик данных
Supplier — это функциональный интерфейс, который не принимает аргументов и возвращает значение.
Сигнатура:
@FunctionalInterface
public interface Supplier<T> {
T get();
}
Примеры использования:
// Пример 1: Ленивая инициализация объекта
Supplier<LocalDateTime> dateTimeSupplier = LocalDateTime::now;
LocalDateTime now = dateTimeSupplier.get();
// Пример 2: Создание экземпляра класса
Supplier<User> userSupplier = () -> new User("guest", "guest@example.com");
User newUser = userSupplier.get();
// Пример 3: Логирование с ленивым вычислением
class Logger {
void debug(Supplier<String> messageSupplier) {
if (isDebugEnabled()) {
System.out.println(messageSupplier.get());
}
}
}
Logger logger = new Logger();
// Сообщение вычисляется только если debug включен
logger.debug(() -> "Expensive calculation: " + expensiveOperation());
// Пример 4: Stream API с генерацией значений
Supplier<Double> randomSupplier = Math::random;
Stream.generate(randomSupplier)
.limit(5)
.forEach(System.out::println);
Основные различия
| Характеристика | Consumer | Supplier |
|---|---|---|
| Параметры | Принимает 1 аргумент (T) | Не принимает аргументов |
| Возвращаемое значение | void (ничего не возвращает) | T (возвращает значение) |
| Роль | Потребляет данные | Производит данные |
| Сигнатура метода | void accept(T t) | T get() |
| Применение | Побочные эффекты, логирование | Ленивая инициализация, фабрики |
Вариации функциональных интерфейсов
// Для примитивных типов (оптимизация)
IntConsumer intConsumer = i -> System.out.println(i);
LongConsumer longConsumer = l -> System.out.println(l);
IntSupplier intSupplier = () -> 42;
DoubleSupplier doubleSupplier = () -> 3.14;
// Два параметра
BiConsumer<String, Integer> biConsumer = (name, age) ->
System.out.println(name + " is " + age + " years old");
biConsumer.accept("John", 30);
// С функцией
Function<Integer, Integer> doubleValue = x -> x * 2;
Function<Integer, String> toString = Object::toString;
Практический пример: обработка данных
public class DataProcessor<T> {
private Supplier<List<T>> dataSource;
private Consumer<T> processor;
public DataProcessor(Supplier<List<T>> dataSource, Consumer<T> processor) {
this.dataSource = dataSource;
this.processor = processor;
}
public void process() {
// Supplier получает данные
List<T> data = dataSource.get();
// Consumer обрабатывает каждый элемент
data.forEach(processor);
}
}
// Использование
Supplier<List<User>> userLoader = () -> userRepository.findAll();
Consumer<User> emailSender = user -> sendEmail(user.getEmail());
DataProcessor<User> processor = new DataProcessor<>(userLoader, emailSender);
processor.process();
Consumer и Supplier — это строительные блоки функционального программирования в Java. Consumer используется для выполнения действий над данными, а Supplier — для производства данных. Правильное их применение делает код более читаемым, модульным и функциональным.