在 Java 8 中,reduce
是一个流操作方法,用于将流中的元素按照指定的操作进行归约(reduce)操作,最终得到一个结果。
reduce
方法有三种重载形式:
-
T reduce(T identity, BinaryOperator<T> accumulator)
这个方法接受一个初始值
identity
和一个二元操作符accumulator
。它使用初始值和流中的元素依次进行二元操作,将结果累积到最终的结果中,并返回最终结果。 -
<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner)
这个方法接受一个初始值
identity
、一个累加器函数accumulator
和一个组合器函数combiner
。它与第一种形式的reduce
方法类似,但是可以用于并行流的归约操作。在并行流中,流被分成多个子流并行处理,然后使用组合器函数将各个子流的结果合并成最终结果。 -
Optional<T> reduce(BinaryOperator<T> accumulator)
这个方法只接受一个二元操作符
accumulator
,它没有初始值。它将流中的元素依次进行二元操作,最终返回一个Optional
对象,表示可能存在的结果。
reduce
方法的使用可以实现多种操作,例如对流中的元素求和、求最大值、求最小值等。下面是一些示例用法:
java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 求和(首次运行前认为a=0,b为第1个元素,第二次运行前a=0+b(上一轮结果),b为第2个元素,依次类推得到结果15)
int sum = numbers.stream().reduce(0, (a, b) -> a + b);
System.out.println(sum); // 输出: 15
// 求最大值
Optional<Integer> max = numbers.stream().reduce(Integer::max);
max.ifPresent(System.out::println); // 输出: 5
// 求乘积(首次运行前认为a=第1个元素,b为第2个元素,第二次运行前a=元素1*元素2(上一轮结果),b为第3个元素)
Optional<Integer> product = numbers.stream().reduce((a, b) -> a * b);
product.ifPresent(System.out::println); // 输出: 120
// 表达式return方式
User1 user1 = new User1(1,"1");
User1 user2 = new User1(2,"2");
User1 user3 = new User1(3,"3");
User1 user4 = new User1(4,"4");
User1 user5 = new User1(5,"5");
List<User1> user1List = Lists.newArrayList();
List<User1> user2List = Lists.newArrayList();
user1List.add(user1);
user1List.add(user2);
user1List.add(user3);
user1List.add(user4);
user1List.add(user5);
final AtomicInteger index = new AtomicInteger(0);
user1List.stream().reduce((a,b)->{
System.out.println("第"+ (index.getAndAdd(1)) +"轮开始");
System.out.println("a---->"+JSON.toJSONString(a));
System.out.println("b---->"+JSON.toJSONString(b));
User1 user11 = new User1();
user11.setHigh(a.getHigh()+b.getHigh());
System.out.println("user11---->"+JSON.toJSONString(user11));
System.out.println("第"+ (index.get()) +"轮结束");
System.out.println();
return user11;
}).ifPresent(user2List::add);
System.out.println("user2List---->"+JSON.toJSONString(user2List));
--输出
第0轮开始
a---->{"high":1,"name":"1"}
b---->{"high":2,"name":"2"}
user11---->{"high":3,"name":"1"}
第1轮结束
第1轮开始
a---->{"high":3,"name":"1"}
b---->{"high":3,"name":"3"}
user11---->{"high":6,"name":"1"}
第2轮结束
第2轮开始
a---->{"high":6,"name":"1"}
b---->{"high":4,"name":"4"}
user11---->{"high":10,"name":"1"}
第3轮结束
第3轮开始
a---->{"high":10,"name":"1"}
b---->{"high":5,"name":"5"}
user11---->{"high":15,"name":"1"}
第4轮结束
user2List---->[{"high":15,"name":"1"}]
从结果可以看到每次的return都作为下一轮的初始值。
在这些示例中,reduce
方法根据提供的操作符对流中的元素进行归约操作,得到最终的结果。注意,reduce
方法返回的结果可能是一个 Optional
对象,因为流中可能没有元素或者操作过程中产生了空值。因此,你可以使用 Optional
的方法来处理可能为空的结果。
以下是更多的示例用法:
java
List<String> words = Arrays.asList("Hello", "World", "Java", "Programming");
// 拼接字符串
String concatenated = words.stream().reduce("", (a, b) -> a + " " + b);
System.out.println(concatenated); // 输出: " Hello World Java Programming"
// 求字符串列表中最长的单词
Optional<String> longestWord = words.stream().reduce((a, b) -> a.length() > b.length() ? a : b);
longestWord.ifPresent(System.out::println); // 输出: "Programming"
// 检查是否存在以大写字母开头的单词
boolean hasUpperCase = words.stream().anyMatch(s -> Character.isUpperCase(s.charAt(0)));
System.out.println(hasUpperCase); // 输出: true
// 计算数字列表的平均值
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
double average = numbers.stream().mapToDouble(Integer::doubleValue).average().orElse(0);
System.out.println(average); // 输出: 3.0
// 连接两个字符串列表
List<String> list1 = Arrays.asList("Hello", "World");
List<String> list2 = Arrays.asList("Java", "Programming");
List<String> combined = Stream.concat(list1.stream(), list2.stream()).collect(Collectors.toList());
System.out.println(combined); // 输出: ["Hello", "World", "Java", "Programming"]