(四)Reactor核心-前置知识3

发布于:2025-03-21 ⋅ 阅读:(20) ⋅ 点赞:(0)

        本章是Reactor核心-前置知识(第三期),主要讲解StreamAPIStream流可以抽象为工厂的流水线,整条流水线走完,数据就处理完了。StreamAPI可以抽象为流水线上的各种操作,比如筛选、转换、组合等。本文章只适合有基础或从业人员进行学习。如果觉得文章有用,就点赞加藏关注支持一下吧。

最佳实战:以后凡是你写for循环处理数据的都可以用StreamAPI进行替换;

一、Stream基础知识

  • Stream Pipeline:流管道、流水线
  • Intermediate Operations:中间操作
  • Terminal Operation:终止操作

流管道组成:

  • 一个数据源(可以是一个数组、集合、生成器函数、I/O管道)
  • 零或多个中间操作(将一个流变形成另一个流)
  • 一个终止操作(产生最终结果)

注意:流是惰性的;只有执行终止操作时才会对源数据进行计算,而且只在需要时才会消耗源元素

        Stream所有数据和操作被组合成流管道(流水线):声明式处理集合数据,包括筛选、转换、组合等.

二、创建流

API: of、builder、empty、ofNullable、generate、concat、集合.stream、just、range

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamCreationExamples {
    public static void main(String[] args) {
        // 1. 使用Stream.of创建流
        Stream<Integer> streamOf = Stream.of(1, 2, 3, 4, 5);
        List<Integer> resultOf = streamOf.collect(Collectors.toList());
        System.out.println("Stream.of: " + resultOf);

        // 2. 使用Stream.builder创建流
        Stream.Builder<Integer> builder = Stream.builder();
        builder.add(6).add(7).add(8);
        Stream<Integer> streamBuilder = builder.build();
        List<Integer> resultBuilder = streamBuilder.collect(Collectors.toList());
        System.out.println("Stream.builder: " + resultBuilder);

        // 3. 使用Stream.empty创建空流
        Stream<Integer> emptyStream = Stream.empty();
        List<Integer> resultEmpty = emptyStream.collect(Collectors.toList());
        System.out.println("Stream.empty: " + resultEmpty);

        // 4. 使用Stream.ofNullable创建流(可能为空)
        Integer num = null;
        Stream<Integer> streamOfNullable = Stream.ofNullable(num);
        List<Integer> resultOfNullable = streamOfNullable.collect(Collectors.toList());
        System.out.println("Stream.ofNullable: " + resultOfNullable);

        // 5. 使用Stream.generate创建无限流(这里只取前5个元素示例)
        Stream<Double> generatedStream = Stream.generate(() -> Math.random());
        List<Double> resultGenerated = generatedStream.limit(5).collect(Collectors.toList());
        System.out.println("Stream.generate: " + resultGenerated);

        // 6. 使用Stream.concat连接两个流
        Stream<Integer> stream1 = Stream.of(1, 2, 3);
        Stream<Integer> stream2 = Stream.of(4, 5, 6);
        Stream<Integer> concatenatedStream = Stream.concat(stream1, stream2);
        List<Integer> resultConcat = concatenatedStream.collect(Collectors.toList());
        System.out.println("Stream.concat: " + resultConcat);

        // 7. 使用集合的stream方法创建流
        List<Integer> list = new ArrayList<>();
        list.add(7);
        list.add(8);
        list.add(9);
        Stream<Integer> streamFromList = list.stream();
        List<Integer> resultFromList = streamFromList.collect(Collectors.toList());
        System.out.println("集合.stream: " + resultFromList);

        // 8. 使用Stream.just(Java 9引入)创建单元素流(这里使用Optional来演示类似功能)
        java.util.Optional<Integer> optional = java.util.Optional.of(10);
        Stream<Integer> justStream = optional.stream();
        List<Integer> resultJust = justStream.collect(Collectors.toList());
        System.out.println("Stream.just(类似Optional.stream): " + resultJust);

        // 9. 使用IntStream.range创建整数范围的流(IntStream是Stream的特化)
        java.util.stream.IntStream rangeStream = java.util.stream.IntStream.range(1, 6);
        List<Integer> resultRange = rangeStream.boxed().collect(Collectors.toList());
        System.out.println("IntStream.range: " + resultRange);
    }
}

在上述代码中:

  1. Stream.of 用于创建包含指定元素的流。

  2. Stream.builder 允许逐步构建流,最后通过 build 方法生成流。

  3. Stream.empty 创建一个空流。

  4. Stream.ofNullable 创建一个可能包含单个元素(如果参数不为 null)的流。

  5. Stream.generate 生成一个无限流,通过提供的 Supplier 函数不断生成元素,这里使用 limit 方法限制只取前几个元素。

  6. Stream.concat 连接两个流。

  7. 集合的 stream 方法将集合转换为流。

  8. Stream.just(在示例中使用 Optional.stream 演示类似功能)创建包含单个元素的流。

  9. IntStream.range 创建一个包含指定范围内整数的流,这里使用 boxed 方法 IntStream 转换为 Stream<Integer>

三、中间操作( intermediate operation)

API: filter、 map、mapToInt、mapToLong、mapToDouble flatMap、flatMapToInt、flatMapToLong、flatMapToDouble mapMulti、mapMultiToInt、mapMultiToLong、mapMultiToDouble、 parallel、unordered、onClose、sequential distinct、sorted、peek、limit、skip、takeWhile、dropWhile

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StreamApiExamples {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // 1. filter: 过滤出偶数
        List<Integer> evenNumbers = numbers.stream()
               .filter(n -> n % 2 == 0)
               .collect(Collectors.toList());
        System.out.println("filter (even numbers): " + evenNumbers);

        // 2. map: 将每个数乘以 2
        List<Integer> doubledNumbers = numbers.stream()
               .map(n -> n * 2)
               .collect(Collectors.toList());
        System.out.println("map (doubled numbers): " + doubledNumbers);

        // 3. mapToInt: 将元素转换为 int 类型并计算总和
        int sum = numbers.stream()
               .mapToInt(Integer::intValue)
               .sum();
        System.out.println("mapToInt (sum): " + sum);

        // 4. mapToLong: 将元素转换为 long 类型并计算总和
        long longSum = numbers.stream()
               .mapToLong(Integer::longValue)
               .sum();
        System.out.println("mapToLong (long sum): " + longSum);

        // 5. mapToDouble: 将元素转换为 double 类型并计算平均值
        double average = numbers.stream()
               .mapToDouble(Integer::doubleValue)
               .average()
               .orElse(0);
        System.out.println("mapToDouble (average): " + average);

        // 6. flatMap: 将嵌套列表展开
        List<List<Integer>> nestedList = Arrays.asList(
                Arrays.asList(1, 2),
                Arrays.asList(3, 4),
                Arrays.asList(5, 6)
        );
        List<Integer> flattenedList = nestedList.stream()
               .flatMap(List::stream)
               .collect(Collectors.toList());
        System.out.println("flatMap (flattened list): " + flattenedList);

        // 7. flatMapToInt: 将嵌套的 IntStream 展开
        List<IntStream> nestedIntStreams = Arrays.asList(
                IntStream.of(1, 2),
                IntStream.of(3, 4),
                IntStream.of(5, 6)
        );
        int flatIntSum = nestedIntStreams.stream()
               .flatMapToInt(s -> s)
               .sum();
        System.out.println("flatMapToInt (sum of flattened IntStream): " + flatIntSum);

        // 8. flatMapToLong: 这里简单模拟将 IntStream 转换为 LongStream 并展开
        long flatLongSum = nestedIntStreams.stream()
               .flatMapToLong(s -> s.asLongStream())
               .sum();
        System.out.println("flatMapToLong (sum of flattened LongStream): " + flatLongSum);

        // 9. flatMapToDouble: 这里简单模拟将 IntStream 转换为 DoubleStream 并展开
        double flatDoubleSum = nestedIntStreams.stream()
               .flatMapToDouble(s -> s.asDoubleStream())
               .sum();
        System.out.println("flatMapToDouble (sum of flattened DoubleStream): " + flatDoubleSum);

        // 10. mapMulti (Java 16+): 生成多个结果
        List<Integer> mapMultiResult = numbers.stream()
               .<Integer>mapMulti((n, consumer) -> {
                    if (n % 2 == 0) {
                        consumer.accept(n);
                        consumer.accept(n * 2);
                    }
                })
               .collect(Collectors.toList());
        System.out.println("mapMulti: " + mapMultiResult);

        // 11. mapMultiToInt (Java 16+): 生成多个 int 结果
        int mapMultiToIntSum = numbers.stream()
               .mapMultiToInt((n, consumer) -> {
                    if (n % 2 == 0) {
                        consumer.accept(n);
                        consumer.accept(n * 2);
                    }
                })
               .sum();
        System.out.println("mapMultiToInt (sum): " + mapMultiToIntSum);

        // 12. mapMultiToLong (Java 16+): 生成多个 long 结果
        long mapMultiToLongSum = numbers.stream()
               .mapMultiToLong((n, consumer) -> {
                    if (n % 2 == 0) {
                        consumer.accept(n);
                        consumer.accept(n * 2);
                    }
                })
               .sum();
        System.out.println("mapMultiToLong (sum): " + mapMultiToLongSum);

        // 13. mapMultiToDouble (Java 16+): 生成多个 double 结果
        double mapMultiToDoubleSum = numbers.stream()
               .mapMultiToDouble((n, consumer) -> {
                    if (n % 2 == 0) {
                        consumer.accept(n);
                        consumer.accept(n * 2);
                    }
                })
               .sum();
        System.out.println("mapMultiToDouble (sum): " + mapMultiToDoubleSum);

        // 14. parallel: 并行处理流
        long parallelCount = numbers.parallelStream()
               .filter(n -> n % 2 == 0)
               .count();
        System.out.println("parallel (count of even numbers): " + parallelCount);

        // 15. unordered: 去除流的顺序约束
        List<Integer> unorderedList = numbers.stream()
               .unordered()
               .collect(Collectors.toList());
        System.out.println("unordered: " + unorderedList);

        // 16. onClose: 流关闭时执行操作
        Stream<Integer> streamWithClose = numbers.stream()
               .onClose(() -> System.out.println("Stream is closed."));
        streamWithClose.collect(Collectors.toList());
        streamWithClose.close();

        // 17. sequential: 将并行流转换为顺序流
        long sequentialCount = numbers.parallelStream()
               .sequential()
               .filter(n -> n % 2 == 0)
               .count();
        System.out.println("sequential (count of even numbers): " + sequentialCount);

        // 18. distinct: 去除重复元素
        List<Integer> distinctNumbers = Arrays.asList(1, 2, 2, 3, 3, 3).stream()
               .distinct()
               .collect(Collectors.toList());
        System.out.println("distinct: " + distinctNumbers);

        // 19. sorted: 对流元素进行排序
        List<Integer> sortedNumbers = numbers.stream()
               .sorted()
               .collect(Collectors.toList());
        System.out.println("sorted: " + sortedNumbers);

        // 20. peek: 用于调试,在每个元素上执行操作
        List<Integer> peekedNumbers = numbers.stream()
               .peek(n -> System.out.println("Processing: " + n))
               .filter(n -> n % 2 == 0)
               .collect(Collectors.toList());
        System.out.println("peek: " + peekedNumbers);

        // 21. limit: 限制流的元素数量
        List<Integer> limitedNumbers = numbers.stream()
               .limit(3)
               .collect(Collectors.toList());
        System.out.println("limit: " + limitedNumbers);

        // 22. skip: 跳过前几个元素
        List<Integer> skippedNumbers = numbers.stream()
               .skip(3)
               .collect(Collectors.toList());
        System.out.println("skip: " + skippedNumbers);

        // 23. takeWhile (Java 9+): 取满足条件的元素,直到不满足为止
        List<Integer> takenWhileNumbers = numbers.stream()
               .takeWhile(n -> n < 5)
               .collect(Collectors.toList());
        System.out.println("takeWhile: " + takenWhileNumbers);

        // 24. dropWhile (Java 9+): 丢弃满足条件的元素,直到不满足为止
        List<Integer> droppedWhileNumbers = numbers.stream()
               .dropWhile(n -> n < 5)
               .collect(Collectors.toList());
        System.out.println("dropWhile: " + droppedWhileNumbers);
    }
}

在上述代码中:

  1. filter:根据指定的条件过滤流中的元素,只保留满足条件的元素。

  2. map:将流中的每个元素按照指定的映射函数进行转换。

  3. mapToIntmapToLongmapToDouble:将流中的元素分别转换为 intlongdouble 类型的流。

  4. flatMap:将嵌套的流展开为一个单一的流。

  5. flatMapToIntflatMapToLongflatMapToDouble:将嵌套的特定类型流展开为对应的基本类型流。

  6. mapMulti 及其变体(Java 16+):可以为每个输入元素生成多个输出元素。

  7. parallel:将流转换为并行流,以并行方式处理元素。

  8. unordered:去除流的顺序约束,允许并行处理时更高效。

  9. onClose:在流关闭时执行指定的操作。

  10. sequential:将并行流转换为顺序流。

  11. distinct:去除流中重复的元素。

  12. sorted:对流中的元素进行排序。

  13. peek:用于调试,在每个元素上执行指定的操作,同时保持流的连续性。

  14. limit:限制流中元素的数量。

  15. skip:跳过流中的前几个元素。

  16. takeWhile(Java 9+):取满足条件的元素,直到遇到不满足条件的元素为止。

  17. dropWhile(Java 9+):丢弃满足条件的元素,直到遇到不满足条件的元素为止。

四、终止操作(terminal operation)

API: forEach、forEachOrdered、toArray、reduce、collect、toList、min、 max、count、anyMatch、allMatch、noneMatch、findFirst、findAny、iterator

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamApiMethodsExample {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // 1. forEach: 对每个元素执行操作
        System.out.println("forEach:");
        numbers.stream().forEach(num -> System.out.print(num + " "));
        System.out.println();

        // 2. forEachOrdered: 按顺序对每个元素执行操作,在并行流中更能体现差异
        System.out.println("forEachOrdered:");
        numbers.parallelStream().forEachOrdered(num -> System.out.print(num + " "));
        System.out.println();

        // 3. toArray: 将流转换为数组
        Integer[] numberArray = numbers.stream().toArray(Integer[]::new);
        System.out.println("toArray: " + Arrays.toString(numberArray));

        // 4. reduce: 对流中的元素进行归约操作,这里求元素总和
        Optional<Integer> sumOptional = numbers.stream().reduce(Integer::sum);
        System.out.println("reduce (sum): " + sumOptional.orElse(0));

        // 5. collect: 使用收集器收集流中的元素,这里将元素收集到一个新的列表中
        List<Integer> collectedList = numbers.stream().collect(Collectors.toList());
        System.out.println("collect (to List): " + collectedList);

        // 6. toList: Java 16 引入的便捷方法,将流转换为不可变列表
        List<Integer> newList = numbers.stream().toList();
        System.out.println("toList: " + newList);

        // 7. min: 找出流中的最小值
        Optional<Integer> minOptional = numbers.stream().min(Integer::compareTo);
        System.out.println("min: " + minOptional.orElse(0));

        // 8. max: 找出流中的最大值
        Optional<Integer> maxOptional = numbers.stream().max(Integer::compareTo);
        System.out.println("max: " + maxOptional.orElse(0));

        // 9. count: 统计流中元素的数量
        long count = numbers.stream().count();
        System.out.println("count: " + count);

        // 10. anyMatch: 判断流中是否有任何元素满足条件
        boolean anyMatch = numbers.stream().anyMatch(num -> num > 5);
        System.out.println("anyMatch (any number > 5): " + anyMatch);

        // 11. allMatch: 判断流中所有元素是否都满足条件
        boolean allMatch = numbers.stream().allMatch(num -> num > 0);
        System.out.println("allMatch (all numbers > 0): " + allMatch);

        // 12. noneMatch: 判断流中是否没有元素满足条件
        boolean noneMatch = numbers.stream().noneMatch(num -> num < 0);
        System.out.println("noneMatch (no number < 0): " + noneMatch);

        // 13. findFirst: 找到流中的第一个元素
        Optional<Integer> firstOptional = numbers.stream().findFirst();
        System.out.println("findFirst: " + firstOptional.orElse(0));

        // 14. findAny: 找到流中的任意一个元素,在顺序流中通常返回第一个元素,在并行流中可能不同
        Optional<Integer> anyOptional = numbers.parallelStream().findAny();
        System.out.println("findAny: " + anyOptional.orElse(0));

        // 15. iterator: 获取流的迭代器
        Iterator<Integer> iterator = numbers.stream().iterator();
        System.out.print("iterator: ");
        while (iterator.hasNext()) {
            System.out.print(iterator.next() + " ");
        }
        System.out.println();
    }
}

在上述代码中:

  1. forEach:对流中的每个元素执行给定的操作,操作顺序不确定,尤其是在并行流中。

  2. forEachOrdered:与 forEach 类似,但会按流中元素的顺序执行操作,在并行流中更能体现其与 forEach 的差异。

  3. toArray:将流中的元素收集到一个数组中,需要指定数组的类型。

  4. reduce:通过指定的归约操作(如求和、求积等)将流中的元素合并为一个结果,返回一个 Optional 对象,因为流可能为空。

  5. collect:使用收集器将流中的元素收集到一个集合或其他数据结构中,这里使用 Collectors.toList() 将元素收集到一个列表中。

  6. toList:Java 16 引入的便捷方法,将流中的元素收集到一个不可变列表中。

  7. min:根据指定的比较器找出流中的最小值,返回一个 Optional 对象。

  8. max:根据指定的比较器找出流中的最大值,返回一个 Optional 对象。

  9. count:统计流中元素的数量。

  10. anyMatch:判断流中是否有任何元素满足给定的条件。

  11. allMatch:判断流中所有元素是否都满足给定的条件。

  12. noneMatch:判断流中是否没有元素满足给定的条件。

  13. findFirst:返回流中的第一个元素,返回一个 Optional 对象。

  14. findAny:返回流中的任意一个元素,在顺序流中通常返回第一个元素,在并行流中可能返回不同的元素,返回一个 Optional 对象。

  15. iterator:获取流的迭代器,允许以传统的迭代方式遍历流中的元素。

五、流与集合

  • 集合关注高效数据管理和访问。
  • 流没有提供直接访问或操作其元素的手段,关注声明性地描述源头数据的一系列操作。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class ComplexStreamExample {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("apple", "banana", "orange", "grape", "avocado", "blueberry");
        List<String> result = words.stream()
                // 过滤长度大于5的单词
                .filter(word -> word.length() > 5)
                // 将单词转换为大写形式
                .map(String::toUpperCase)
                // 将每个单词拆分为字符,并放入新的流中
                .flatMap(word -> Arrays.stream(word.split("")))
                // 去重
                .distinct()
                // 按照字母顺序排序
                .sorted()
                // 在每个字符上执行某些操作,并打印调试信息
                .peek(System.out::println)
                // 取前4个字符
                .limit(4)
                // 跳过前两个字符
                .skip(2)
                // 使用takeWhile,保留小于'F'的字符
                .takeWhile(ch -> ch.charAt(0) < 'F')
                // 收集结果并转为列表
                .collect(Collectors.toList());
        System.out.println("Result: " + result);
    }
}

下期预告:Reactor核心-前置知识(第四期)

Reactor核心-前置知识一共有四期

(第一期):Lambda表达式

(第二期):Function函数式接口出入参定义

(第三期):StreamAPI

(第四期):线程池

什么问题都可以评论区留言,看见都会回复的

如果你觉得本篇文章对你有所帮助的,把“文章有帮助的”打在评论区

多多支持吧!!!

点赞加藏评论,是对小编莫大的肯定。抱拳了!