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

Приведи пример использования reduce в Stream API

2.0 Middle🔥 211 комментариев
#Stream API и функциональное программирование

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

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

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

Использование reduce в Stream API

reduce — это терминальная операция в Stream API, которая преобразует поток элементов в одно значение путем аккумуляции. Она особенно полезна для операций типа суммирования, нахождения минимума/максимума, конкатенации строк и других сборок данных.

Три перегрузки метода reduce

// 1. Optional<T> reduce(BinaryOperator<T> accumulator)
Optional<Integer> sum = Arrays.stream(new int[]{1, 2, 3, 4})
    .boxed()
    .reduce((a, b) -> a + b);
// Результат: Optional[10]

// 2. T reduce(T identity, BinaryOperator<T> accumulator)
int sum = Arrays.stream(new int[]{1, 2, 3, 4})
    .boxed()
    .reduce(0, (a, b) -> a + b);
// Результат: 10

// 3. <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner)
Integer sum = Arrays.stream(new int[]{1, 2, 3, 4})
    .boxed()
    .reduce(0, 
        (accumulator, value) -> accumulator + value,  // accumulator
        (accumulator1, accumulator2) -> accumulator1 + accumulator2  // combiner
    );
// Результат: 10

Практические примеры

Пример 1: Суммирование чисел

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// С начальным значением
int sum = numbers.stream()
    .reduce(0, Integer::sum);
System.out.println(sum);  // 15

// Без начального значения (возвращает Optional)
Optional<Integer> optionalSum = numbers.stream()
    .reduce(Integer::sum);
optionalSum.ifPresent(System.out::println);  // 15

Пример 2: Нахождение максимума и минимума

List<Integer> numbers = Arrays.asList(5, 3, 8, 2, 9, 1);

// Максимум
Optional<Integer> max = numbers.stream()
    .reduce(Integer::max);
System.out.println(max.orElse(0));  // 9

// Минимум
Optional<Integer> min = numbers.stream()
    .reduce(Integer::min);
System.out.println(min.orElse(0));  // 1

Пример 3: Конкатенация строк

List<String> words = Arrays.asList("Hello", "World", "Java");

// С разделителем
String result = words.stream()
    .reduce("", (acc, word) -> acc.isEmpty() ? word : acc + " " + word);
System.out.println(result);  // Hello World Java

// Альтернатива через String.join
String result2 = String.join(" ", words);
System.out.println(result2);  // Hello World Java

Пример 4: Сборка объекта (используется третья перегрузка)

public class Person {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

List<Person> people = Arrays.asList(
    new Person("Alice", 25),
    new Person("Bob", 30),
    new Person("Charlie", 35)
);

// Подсчет сумму всех возрастов
int totalAge = people.stream()
    .reduce(0, 
        (sum, person) -> sum + person.age,
        Integer::sum
    );
System.out.println(totalAge);  // 90

Пример 5: Аккумуляция в коллекцию

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// Сборка в StringBuilder
String result = numbers.stream()
    .reduce(
        new StringBuilder(),
        (sb, num) -> sb.append(num).append(","),
        (sb1, sb2) -> sb1.append(sb2)
    )
    .toString();
System.out.println(result);  // 1,2,3,4,5,

// Лучше использовать collect
String resultBetter = numbers.stream()
    .map(String::valueOf)
    .collect(Collectors.joining(","));
System.out.println(resultBetter);  // 1,2,3,4,5

Разница между reduce и collect

Операцияreducecollect
НазначениеСвертка потока в одно значениеНакопление в контейнер
Тип результатаОдин элемент или OptionalКоллекция или контейнер
ПараллелизмТребует стороннего combinerВстроенная поддержка параллелизма
ПроизводительностьМожет быть медленнее для параллельных потоковОптимизирована для параллелизма
// reduce
int sum = numbers.stream()
    .reduce(0, Integer::sum);

// collect (лучше для сборки)
List<Integer> doubled = numbers.stream()
    .map(n -> n * 2)
    .collect(Collectors.toList());

Использование в параллельных потоках

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// Работает безопасно с параллельными потоками
int sum = numbers.parallelStream()
    .reduce(
        0,
        Integer::sum,           // accumulator
        Integer::sum            // combiner для объединения результатов
    );
System.out.println(sum);  // 55

Таким образом, reduce в Stream API предоставляет мощный инструмент для трансформации потока данных в одно агрегированное значение, поддерживая как последовательные, так и параллельные обработки.

Приведи пример использования reduce в Stream API | PrepBro