狂野飙车6鸿蒙版
471.84M · 2025-10-31
reduce是 Java Stream API 中一个非常强大的操作,它可以将流中的元素组合起来,生成一个单一的结果。下面我将全面讲解 reduce的使用方法、原理和实际应用场景。
reduce方法的基本概念reduce操作又称为"归约"操作,它通过反复应用组合操作,将流中的元素组合成一个单一的结果。这个过程类似于将一堆数据"缩减"为一个值,因此得名"reduce"。
reduce方法的三种形式Optional<T> reduce(BinaryOperator<T> accumulator)这是最简单的形式,它接受一个 BinaryOperator(二元操作符)作为参数。
Optional<Integer> sum = numbers.stream()
.reduce((a, b) -> a + b);
特点:
Optional,因为流可能为空BinaryOperator,即一个接受两个参数并返回一个结果的函数T reduce(T identity, BinaryOperator<T> accumulator)这个方法接受一个初始值(identity)和一个 BinaryOperator。
Integer sum = numbers.stream()
.reduce(0, (a, b) -> a + b);
特点:
Optional<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)这是最复杂的形式,用于并行流处理。
Integer sum = numbers.parallelStream()
.reduce(
0,
(subTotal, element) -> subTotal + element,
Integer::sum
);
特点:
reduce的工作原理reduce对于顺序流,reduce操作可以理解为:
reduce对于并行流,处理过程更复杂:
// 方法1
Optional<Integer> sum1 = numbers.stream().reduce(Integer::sum);
// 方法2
Integer sum2 = numbers.stream().reduce(0, Integer::sum);
// 方法3 (并行)
Integer sum3 = numbers.parallelStream().reduce(0, Integer::sum, Integer::sum);
Optional<Integer> max = numbers.stream().reduce(Integer::max);
List<String> words = Arrays.asList("Hello", "World", "!");
String sentence = words.stream().reduce("", (a, b) -> a + " " + b).trim();
class Person {
String name;
int age;
// getters, setters, constructor
}
List<Person> people = // 初始化人员列表
// 计算总年龄
int totalAge = people.stream()
.map(Person::getAge)
.reduce(0, Integer::sum);
// 找出最年长的人
Optional<Person> oldest = people.stream()
.reduce((p1, p2) -> p1.getAge() > p2.getAge() ? p1 : p2);
顺序流 vs 并行流:
避免装箱操作:
mapToInt()等原始类型流// 更高效的求和方式
int sum = numbers.stream().mapToInt(Integer::intValue).sum();
组合器的选择:
忽略空流情况:
// 危险:如果numbers为空,get()会抛出NoSuchElementException
int sum = numbers.stream().reduce((a, b) -> a + b).get();
// 安全做法
int sum = numbers.stream().reduce(0, (a, b) -> a + b);
在并行流中使用非结合性操作:
// 错误:减法不是结合性操作
int difference = numbers.parallelStream().reduce(0, (a, b) -> a - b);
初始值选择不当:
// 错误:初始值1会影响乘积结果
int product = numbers.stream().reduce(1, (a, b) -> a * b);
明确使用场景:
reducecollect优先使用内置方法:
// 优于手写reduce
int sum = numbers.stream().mapToInt(Integer::intValue).sum();
并行流注意事项:
代码可读性:
Optional<Integer> max = numbers.stream().reduce(Math::max);
reduce与 collect的比较| 特性 | reduce | collect |
|---|---|---|
| 可变性 | 不可变 | 可变 |
| 并行支持 | 需要显式组合器 | 内置支持 |
| 使用场景 | 简单归约操作 | 复杂可变归约 |
| 性能 | 通常较低(需要创建中间对象) | 通常较高(可重用容器) |
| 典型用途 | 求和、求积、最大值等 | 收集到集合、字符串拼接等 |
// 计算加权平均值
class WeightedAverage {
private double sum = 0;
private int count = 0;
public void accumulate(double value, int weight) {
sum += value * weight;
count += weight;
}
public WeightedAverage combine(WeightedAverage other) {
sum += other.sum;
count += other.count;
return this;
}
public double getAverage() {
return count == 0 ? 0 : sum / count;
}
}
List<Double> values = Arrays.asList(1.0, 2.0, 3.0);
List<Integer> weights = Arrays.asList(1, 2, 3);
WeightedAverage average = IntStream.range(0, values.size())
.mapToObj(i -> new AbstractMap.SimpleEntry<>(values.get(i), weights.get(i)))
.reduce(
new WeightedAverage(),
(wa, entry) -> {
wa.accumulate(entry.getKey(), entry.getValue());
return wa;
},
WeightedAverage::combine
);
System.out.println("Weighted average: " + average.getAverage());
reduce实现 map功能// 使用reduce实现map功能(不推荐,仅演示)
List<String> upperCaseNames = people.stream()
.reduce(
new ArrayList<String>(),
(list, person) -> {
list.add(person.getName().toUpperCase());
return list;
},
(list1, list2) -> {
list1.addAll(list2);
return list1;
}
);
reduce是 Java Stream API 中一个强大的工具,特别适合用于值的聚合操作。使用时需要注意:
reduce重载形式IntStream)提高数值计算性能collect可能是更好的选择