Для чего используется функциональный интерфейс Consumer в Java?

«Для чего используется функциональный интерфейс Consumer в Java?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Сигнатура: void accept(T t)

Основные сценарии применения:

  1. Итерация по коллекциям (метод forEach):

    List<String> names = List.of("Alice", "Bob", "Charlie");
    // Consumer как лямбда
    names.forEach(name -> System.out.println(name));
    // Или через ссылку на метод
    names.forEach(System.out::println);
  2. Обработка элементов в Stream API: Для выполнения финального действия над элементом (например, сохранение, логирование).

    Stream.of("data1.txt", "data2.txt")
          .map(Paths::get)
          .forEach(path -> System.out.println("Processing: " + path));
  3. Модификация объектов или конфигурация:

    Consumer<StringBuilder> addHeader = sb -> sb.insert(0, "HEADERn");
    StringBuilder log = new StringBuilder("Main content");
    addHeader.accept(log); // log теперь содержит "HEADERnMain content"
  4. Композиция операций с andThen:

    Consumer<String> log = s -> System.out.println("[LOG] " + s);
    Consumer<String> save = s -> repository.save(s);
    // Сначала залогировать, затем сохранить
    log.andThen(save).accept("New data");

Где ещё встречается: В Optional.ifPresent(), CompletableFuture.thenAccept(), различных callback-механизмах.