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

Как найти сумму всех четных чисел в потоке целых чисел используя Stream API

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

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

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

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

# Сумма всех чётных чисел в потоке данных

Простой способ

Используем filter() для отбора чётных и reduce() или sum() для суммирования:

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

// Вариант 1: с IntStream
int sum = numbers.stream()
    .filter(n -> n % 2 == 0)  // Оставляем только чётные
    .mapToInt(Integer::intValue) // Преобразуем в IntStream
    .sum(); // Суммируем

System.out.println(sum); // 2 + 4 + 6 + 8 + 10 = 30

// Вариант 2: с reduce()
int sum = numbers.stream()
    .filter(n -> n % 2 == 0)
    .reduce(0, Integer::sum); // Начальное значение 0, операция sum

// Вариант 3: с Integer.sum()
int sum = numbers.stream()
    .filter(n -> n % 2 == 0)
    .reduce(Integer::sum)
    .orElse(0); // На случай, если нет чётных чисел

Работающие примеры

Пример 1: базовый список

public class EvenSumExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        
        int sum = numbers.stream()
            .filter(n -> n % 2 == 0)
            .mapToInt(Integer::intValue)
            .sum();
        
        System.out.println("Сумма чётных: " + sum); // 30
    }
}

Пример 2: массив

public class ArrayEvenSum {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        
        int sum = Arrays.stream(numbers)
            .filter(n -> n % 2 == 0)
            .sum();
        
        System.out.println("Сумма чётных: " + sum); // 30
    }
}

Пример 3: натуральный поток (infinite stream)

public class InfiniteStreamExample {
    public static void main(String[] args) {
        // Генерируем числа от 1 до 100 и считаем сумму чётных
        int sum = IntStream.rangeClosed(1, 100)
            .filter(n -> n % 2 == 0)
            .sum();
        
        System.out.println("Сумма чётных от 1 до 100: " + sum); // 2550
    }
}

Оптимизация производительности

Параллельный поток для больших данных

public class ParallelEvenSum {
    public static void main(String[] args) {
        List<Integer> largeList = new ArrayList<>();
        for (int i = 1; i <= 10_000_000; i++) {
            largeList.add(i);
        }
        
        // Последовательно
        long start = System.currentTimeMillis();
        int sum = largeList.stream()
            .filter(n -> n % 2 == 0)
            .mapToInt(Integer::intValue)
            .sum();
        System.out.println("Время: " + (System.currentTimeMillis() - start) + "ms");
        
        // Параллельно (для больших объёмов)
        start = System.currentTimeMillis();
        int parallelSum = largeList.parallelStream()
            .filter(n -> n % 2 == 0)
            .mapToInt(Integer::intValue)
            .sum();
        System.out.println("Параллельное время: " + (System.currentTimeMillis() - start) + "ms");
        
        System.out.println("Результат: " + parallelSum);
    }
}

Лучше использовать IntStream для целых чисел

// Менее эффективно: с оберткой Integer
int sum1 = Arrays.asList(1, 2, 3, 4, 5)
    .stream()
    .filter(n -> n % 2 == 0)
    .mapToInt(Integer::intValue)
    .sum(); // Требует упаковки/распаковки

// Более эффективно: сразу IntStream
int sum2 = IntStream.of(1, 2, 3, 4, 5)
    .filter(n -> n % 2 == 0)
    .sum(); // Нет оверхэда упаковки

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

Пример 1: суммирование чётных цен товаров

class Product {
    private String name;
    private double price;
    
    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }
    
    public double getPrice() { return price; }
}

public class ProductExample {
    public static void main(String[] args) {
        List<Product> products = Arrays.asList(
            new Product("Товар 1", 10.0),
            new Product("Товар 2", 20.5),
            new Product("Товар 3", 30.0),
            new Product("Товар 4", 15.0)
        );
        
        double sum = products.stream()
            .map(p -> (int) p.getPrice()) // Приводим к целому числу
            .filter(price -> price % 2 == 0) // Чётные цены
            .mapToDouble(Integer::doubleValue)
            .sum();
        
        System.out.println("Сумма чётных цен: " + sum); // 10 + 20 + 30 = 60
    }
}

Пример 2: чётные ID из коллекции

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

long sum = ids.stream()
    .filter(id -> id % 2 == 0)
    .mapToLong(Long::longValue)
    .sum();

System.out.println("Сумма чётных ID: " + sum); // 30

Альтернативные способы

Без Stream (классический способ)

int sum = 0;
for (int number : numbers) {
    if (number % 2 == 0) {
        sum += number;
    }
}
System.out.println(sum); // 30

С использованием собирателя (Collector)

int sum = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.summingInt(Integer::intValue));

System.out.println(sum); // 30

Сравнение подходов

ПодходПроизводительностьЧитаемостьКогда использовать
IntStream.sum()ОтличнаяХорошаяЦелые числа, нужна скорость
.reduce()ХорошаяСредняяФункциональный стиль
Collectors.summingInt()ХорошаяХорошаяУдобство, не нужна микро-оптимизация
Классический циклОтличнаяПлохаяLegacy код, micro-benchmarks
parallelStream()Отличная*ХорошаяТолько для больших наборов (> 100K элементов)

*Параллельные потоки работают лучше только для больших наборов данных. На маленьких они медленнее из-за оверхэда создания потоков.

Ключевые моменты

  1. IntStream vs Stream<Integer>: IntStream эффективнее избегает оверхэда оборачивания/разворачивания
  2. filter + sum — самая читаемая и эффективная комбинация
  3. Параллелизм — только для наборов > 100K элементов
  4. mapToInt vs map + reduce — первый предпочтительнее для целых чисел
  5. Нет побочных эффектов — Stream API предполагает чистые функции (без состояния)

В большинстве случаев правильный ответ:

int sum = numbers.stream()
    .filter(n -> n % 2 == 0)
    .mapToInt(Integer::intValue)
    .sum();