← Назад к вопросам
Как найти сумму всех четных чисел в потоке целых чисел используя 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 элементов) |
*Параллельные потоки работают лучше только для больших наборов данных. На маленьких они медленнее из-за оверхэда создания потоков.
Ключевые моменты
- IntStream vs Stream<Integer>: IntStream эффективнее избегает оверхэда оборачивания/разворачивания
- filter + sum — самая читаемая и эффективная комбинация
- Параллелизм — только для наборов > 100K элементов
- mapToInt vs map + reduce — первый предпочтительнее для целых чисел
- Нет побочных эффектов — Stream API предполагает чистые функции (без состояния)
В большинстве случаев правильный ответ:
int sum = numbers.stream()
.filter(n -> n % 2 == 0)
.mapToInt(Integer::intValue)
.sum();