reduce()这个方法可能平时用得不多,因为它的常用方法都被单独封装起来了。比如sum()
、max()
、min()
、count()都是通过reduce()操作的。
另外的几种:
Mqtt是javaBean对象:
Optional<Mqtt> maxTemperature = list.stream().max(Comparator.comparingInt(Mqtt::getTemperature));
Optional<Mqtt> maxMethane = list.stream().max(Comparator.comparingInt(Mqtt::getMethane));
Optional<Mqtt> maxHumidity = list.stream().max(Comparator.comparingInt(Mqtt::getHumidity));
不给定初始值也可,此时返回类型会变成 Optional<Integer>
@Test
public void testReduce() {
Stream<Integer> stream = Arrays.stream(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8});
//求集合元素只和
Integer result = stream.reduce(0, Integer::sum);
System.out.println(result);
stream = Arrays.stream(new Integer[]{1, 2, 3, 4, 5, 6, 7});
//求和
stream.reduce((i, j) -> i + j).ifPresent(System.out::println);
stream = Arrays.stream(new Integer[]{1, 2, 3, 4, 5, 6, 7});
//求最大值
stream.reduce(Integer::max).ifPresent(System.out::println);
stream = Arrays.stream(new Integer[]{1, 2, 3, 4, 5, 6, 7});
//求最小值
stream.reduce(Integer::min).ifPresent(System.out::println);
stream = Arrays.stream(new Integer[]{1, 2, 3, 4, 5, 6, 7});
//做逻辑
stream.reduce((i, j) -> i > j ? j : i).ifPresent(System.out::println);
stream = Arrays.stream(new Integer[]{1, 2, 3, 4, 5, 6, 7});
//求逻辑求乘机
int result2 = stream.filter(i -> i % 2 == 0).reduce(1, (i, j) -> i * j);
Optional.of(result2).ifPresent(System.out::println);
}
给定一个初始化值开始计算:
不给定初始值也可,此时返回类型会变成 Optional<Integer>,初始值为什么类型,返回值就是必须是什么类型
/**
* T reduce(T identity, BinaryOperator<T> accumulator);
* identity:它允许用户提供一个循环计算的初始值。
* accumulator:计算的累加器,
*/
private static void testReduce() {
//T reduce(T identity, BinaryOperator<T> accumulator);
System.out.println("给定个初始值,求和");
System.out.println(Stream.of(1, 2, 3, 4).reduce(100, (sum, item) -> sum + item));
System.out.println(Stream.of(1, 2, 3, 4).reduce(100, Integer::sum));
System.out.println("给定个初始值,求min");
System.out.println(Stream.of(1, 2, 3, 4).reduce(100, (min, item) -> Math.min(min, item)));
System.out.println(Stream.of(1, 2, 3, 4).reduce(100, Integer::min));
System.out.println("给定个初始值,求max");
System.out.println(Stream.of(1, 2, 3, 4).reduce(100, (max, item) -> Math.max(max, item)));
System.out.println(Stream.of(1, 2, 3, 4).reduce(100, Integer::max));
//Optional<T> reduce(BinaryOperator<T> accumulator);
// 注意返回值,上面的返回是T,泛型,传进去啥类型,返回就是啥类型。
// 下面的返回的则是Optional类型
System.out.println("无初始值,求和");
System.out.println(Stream.of(1, 2, 3, 4).reduce(Integer::sum).orElse(0));
System.out.println("无初始值,求max");
System.out.println(Stream.of(1, 2, 3, 4).reduce(Integer::max).orElse(0));
System.out.println("无初始值,求min");
System.out.println(Stream.of(1, 2, 3, 4).reduce(Integer::min).orElse(0));
}
进阶并行操作:
主要功能 是单参数方法的 ,下面两个一个增加初始值identity,一个是增加并行处理时,多段值的操作
定义初始值为string类型,返回值就是string类型,
而且串行流中组合型函数在并行执行中 (str1, str2) -> "-----" 没起到任何作用,不会调用
第三个参数(str1, str2) -> "-----"就是所谓的组合器 combiner,这里因为是串行流,所以组合器 combiner 不会被调用,可以直接返回 null。但 combiner 本身不能为 null,否则会抛空指针异常。
串行流写法(第三个参数不起任何作用占位,返回null也行):
String reduce = Stream.of(1, 2, 3, 4, 5).
reduce("拼接字符串-", (str, v) -> str + v, (str1, str2) -> "-----");
// 拼接字符串-12345
串行流和并行流对比: parallel()表示并行执行
//串行流,只是在当前数据集合 基础上增加1 ,第三个参数 Integer::sum 占位的,不生效
Integer reduce = Arrays.asList(1, 2, 3).stream().reduce(1, Integer::sum, Integer::sum);
System.err.println(reduce);
//7
/*
串行流说明:
1+1=2
2=2
3=3
7
*/
//并行流,集合中每个在在多线程都去扩大1在做相加计算 ,第三个参数 Integer::sum 生效
Integer reduce1 = Arrays.asList(1, 2, 3).stream().parallel().reduce(1, Integer::sum, Integer::sum);
System.err.println(reduce1);
//9
/*
并行流说明:
1+1=2
2+1=3
3+1=4
9
*/
并行内部计算调用:
List<Integer> integers = Arrays.asList(1, 2, 3, 4);
Integer reduce = integers.stream().parallel()
.reduce(1, (a, b) -> {
int c = a + b;
String name = Thread.currentThread().getName();
System.out.printf("[内部线程调用1111]:%s,%d+%d=%d%n", name, a, b, c);
return c;
}, (a, b) -> {
int c = a + b;
String name = Thread.currentThread().getName();
System.out.printf("[内部线程调用22222]:%s,%d+%d=%d%n", name, a, b, c);
return c;
});
System.err.println(reduce);
[内部线程调用1111]:main,1+3=4
[内部线程调用1111]:ForkJoinPool.commonPool-worker-9,1+2=3
[内部线程调用1111]:ForkJoinPool.commonPool-worker-2,1+4=5
[内部线程调用1111]:ForkJoinPool.commonPool-worker-11,1+1=2
[内部线程调用22222]:ForkJoinPool.commonPool-worker-2,4+5=9
[内部线程调用22222]:ForkJoinPool.commonPool-worker-11,2+3=5
[内部线程调用22222]:ForkJoinPool.commonPool-worker-11,5+9=14
collect()的使用:
Map<String, Integer> count = Stream.of("hello", "world", "hello", "me", "hello", "yukina", "hello", "happy", "world")
.parallel().collect(() -> new HashMap<>(),
(acc, x) -> {
if (!acc.containsKey(x))
acc.put(x, 0);
acc.compute(x, (k, v) -> v + 1);
}, (a, b) -> {
// combine 时必须把第二个值合并到第一个值
b.forEach((kb, vb) -> {
if (!a.containsKey(kb))
a.put(kb, 0);
a.compute(kb, (ka, va) -> va + vb);
});
});
// {yukina=1, world=2, happy=1, me=1, hello=4}