← Назад к вопросам

Какой функциональный интерфейс получаешь в For Each?

1.3 Junior🔥 191 комментариев
#Stream API и функциональное программирование#ООП

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI21 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Функциональный интерфейс в forEach

В методе forEach мы работаем с функциональным интерфейсом Consumer<T>. Расскажу о нём подробно.

Consumer<T> — основной интерфейс

Это функциональный интерфейс, определённый в пакете java.util.function:

@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); };
    }
}

Ключевые характеристики:

  • Принимает один аргумент типа T
  • Не возвращает значение (void)
  • Используется для операций с побочными эффектами

Примеры использования forEach

1. С лямбда-выражением:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));
// Output:
// Alice
// Bob
// Charlie

2. С ссылкой на метод:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.forEach(System.out::println);

3. С более сложной логикой:

List<User> users = getUserList();
users.forEach(user -> {
    user.setActive(true);
    user.setLastLoginTime(LocalDateTime.now());
    saveUser(user);
});

forEach в разных контекстах

Для Iterable (коллекции):

@FunctionalInterface
public interface Iterable<T> {
    Iterator<T> iterator();
    
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
}

Для Stream:

List<Integer> numbers = Arrays.asList(1, 2, 3);
numbers.stream()
    .filter(n -> n > 1)
    .forEach(System.out::println);
// Output: 2, 3

Важные особенности

1. Terminal операция в Stream: forEach в Stream API — это терминальная операция, которая завершает stream pipeline и не может быть цепована дальше.

2. Порядок выполнения: Для параллельных потоков порядок может быть произвольным:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.parallelStream()
    .forEach(System.out::println);
// Выведет числа в произвольном порядке

Если нужен порядок — используй forEachOrdered():

numbers.parallelStream()
    .forEachOrdered(System.out::println);
// Выведет в исходном порядке

3. Использование andThen():

Consumer<String> printName = name -> System.out.println("Name: " + name);
Consumer<String> printUpper = name -> System.out.println("Upper: " + name.toUpperCase());

Consumer<String> combined = printName.andThen(printUpper);
names.forEach(combined);

Отличия от других операций

  • forEach — для побочных эффектов, не трансформирует данные
  • map() — трансформирует элементы, требует Consumer вместе с другими операциями
  • filter() — отбирает элементы по условию
  • reduce() — агрегирует элементы в один результат

То есть, Consumer<T> в forEach — это прямой способ выполнить действие с каждым элементом коллекции или потока без изменения самих данных.

Какой функциональный интерфейс получаешь в For Each? | PrepBro