В чем разница между интерфейсами Supplier и Consumer в Java?

Ответ

Supplier<T> и Consumer<T> — это функциональные интерфейсы из пакета java.util.function, предназначенные для разных целей.

Интерфейс Сигнатура Описание Ключевой метод
Supplier<T> T get() Поставщик. Не принимает аргументов, возвращает (поставляет) объект типа T. Используется для ленивой генерации или предоставления значений. get()
Consumer<T> void accept(T t) Потребитель. Принимает аргумент типа T, выполняет над ним действие и ничего не возвращает (void). accept(T t)

Примеры:

// Supplier: Создает новую строку или объект
Supplier<String> randomGreeting = () -> "Hello, World!";
Supplier<LocalDate> todaySupplier = LocalDate::now;
System.out.println(randomGreeting.get()); // Вызов поставщика

// Consumer: Выполняет действие с переданным объектом
Consumer<String> printer = System.out::println;
Consumer<List<String>> sorter = Collections::sort;
printer.accept("Message"); // Потребление объекта

// Практическое сочетание: forEach принимает Consumer
List.of("A", "B", "C").forEach(printer);

Ключевое отличие: Supplier производит данные, Consumer потребляет (использует) данные.

Ответ 18+ 🔞

Да ты посмотри, какие интерфейсы придумали, ёпта! Сидят там, блядь, в java.util.function и думают: "А давайте сделаем так, чтобы один только поставлял, а другой — только жрал". Идея, блядь, проще пареной репы, но пока в голове не уляжется — пиздец.

Вот смотри, представь себе пивной ларек. Supplier — это такой чувак, который из подвала достает тебе бутылку. Ничего не просит, просто возвращает тебе её, сука. Метод у него один — get(). Вызвал get() — получил пиво. Всё, блядь.

Supplier<String> бариста = () -> "Твой капучино, мудак!";
String напиток = бариста.get(); // Всё, забрал и пошёл.

А Consumer — это уже ты сам, который эту бутылку получает и делает с ней что-то. Выпил, блядь, или об голову кого-то разбил. Метод у него — accept(T t). Принял объект, что-то с ним сделал и нихуя не вернул. void он, сука.

Consumer<String> алкаш = (бутылка) -> System.out.println("Выпил " + бутылка + " и уснул в кустах.");
алкаш.accept("Балтику 9"); // Действие совершил, результат — ноль.

И главное, блядь, их не перепутать! Поставщик (Supplier) — он как девственница, только отдаёт. Потребитель (Consumer) — он как похотливый мужик, только принимает и тратит. Один — get() (взять), другой — accept() (принять). Запутаешься — получишь void там, где ждал объект, и охуеешь нахуй.

Вот, например, как они в деле работают:

// Supplier: вечно поставляет текущую дату, как заведённый
Supplier<LocalDateTime> машинаВремени = LocalDateTime::now;
System.out.println("А сейчас: " + машинаВремени.get());

// Consumer: тупо жрёт всё, что ему скормят, и печатает
Consumer<Object> пожиратель = obj -> System.out.println("Съел: " + obj);
пожиратель.accept(new Object()); // Съел какой-то объект, и ему похуй.

А вместе их, блядь, часто используют. Классика — метод forEach. Ему скорми список, а он для каждого элемента вызовет твоего Consumer-алкаша, который будет его обрабатывать.

List<String> грехи = List.of("Лень", "Чревоугодие", "Гордыня");
Consumer<String> исповедь = грех -> System.out.println("Каюсь в " + грех);
грехи.forEach(исповедь); // Каждую падлу по очереди в рот берёт.

Короче, запомни, чтобы не быть мудем: Supplier — это "дай", Consumer — это "на". Один тебе что-то в руки суёт, другой у тебя из рук забирает и делает свои тёмные делишки. Всё, блядь, элементарно!