美文网首页
Java8 Stream 基础

Java8 Stream 基础

作者: Tinyspot | 来源:发表于2022-08-19 07:38 被阅读0次

    1. 流(Stream)

    • 流(Stream)中保存对集合或数组数据的操作。和集合类似,但集合中保存的是数据
    • 流到底是什么?简短的定义就是“从支持数据处理操作的源生成的元素序列”
    • 类似于生活中的流水线

    1.1 Stream 特点

    • Stream 自己不会存储元素
    • Stream 不会改变源对象。相反,它们会返回一个持有结果的新 Stream
    • Stream 操作是延迟执行的,这意味着它们会等到需要结果的时候才执行

    优点:

    • 声明性—更简洁,更易读;
    • 可复合—更灵活;
    • 可并行——性能更好

    for-each 外部迭代;Stream库使用内部迭代
    和迭代器类似,流只能遍历一次
    管道( | ) 一个程序的输出流作为另一个程序的输入流

    1.2 Stream 使用步骤

    1. 构建流:创建一个流
    2. 中间操作:在一个或多个步骤中,将初始 Stream 转化到另一个 Stream 的中间操作
    3. 终止操作:使用一个终止操作来产生一个结果。该操作会强制它之前的延迟操作立即执行,在这之后,该 Steam 就不能使用了

    使用链接方法(chaining):
    可以连接起来的流操作称为中间操作,关闭流的操作称为终端操作

    1.3 三类接口

    • 中间方法:将流转换为另一个流
    • 终止方法:返回结果或执行操作,在执行方法终止后,流会自动关闭
    • 静态方法:创建一个流

    2. 构建流

    public interface Stream<T> extends BaseStream<T, Stream<T>> {
        public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {}
        public static<T> Stream<T> generate(Supplier<T> s) {}
    }
    

    示例:

      List<String> list = new ArrayList<>();
      list.add("aaa");
      Stream<String> stream = list.stream();
      Stream<String> parallelStream = list.parallelStream();
    
      // Arrays.stream
      String[] arr = {"aaa", "bbb"};
      Stream<String> stream = Arrays.stream(arr);
      stream.forEach(System.out::println);
    

    2.2 迭代流

    无限流 iterate(...) 接受一个初始值,还有一个依次应用在每个产生的新值上的 Lambda UnaryOperator<T>类型

      Stream<Integer> iterate = Stream.iterate(0, n -> n + 2);
      // limit(...)中间操作,限制下数量,不然会一直迭代
      iterate.limit(10).forEach(System.out::println);
    
      // Stream.iterate(0, n -> n + 2).limit(10).forEach(System.out::println);
    

    2.4 生成流

    generate(...) 不是依次对每个新生成的值应用函数的。它接受一个Supplier<T>类型的Lambda提供新的值

      Stream<Integer> generate = Stream.generate(() -> new Random().nextInt());
      generate.limit(5).forEach(System.out::println);
    
      Stream.generate(Math::random).limit(5).forEach(System.out::println);
    

    2.5 IntStream / LongStream / DoubleStream

    range(...) / rangeClosed(...)

    IntStream intStream = IntStream.rangeClosed(0, 10);
    intStream.forEach(System.out::println);
    

    3. 惰性中间方法

    • 流是惰性的,仅仅当终止操作开始时才会进行计算
    • filter, distinct, sorted
    • limit(n) 截断流;skip(n) 返回一个扔掉了前n个元素的流
    • map, flatMap, mapToInt
    • sorted

    3.1 filter(...)

    • Stream<T> filter(Predicate<? super T> predicate)
    • filter(Predicate) 接受一个谓词作为参数,并返回一个包括所有符合谓词的元素的流
    list.stream()
            .filter(str -> {
                System.out.println("filter run....");
                return str.equals("111");
            });
            // .forEach(System.out::println);
    // 不加 forEach(), filter() 里的内容不会执行
    

    3.2 map(...)

    • <R> Stream<R> map(Function<? super T, ? extends R> mapper);
    • map(Function<T, R>) 接受一个函数作为参数,这个函数会被应用到每个元素上,并将其映射成一个新的元素

    3.3 flatMap

    • 流的扁平化
    • flatMap(Arrays::stream) 生成的单个流都被合并起来,即扁平化为一个流
    • flatMap() 把一个流中的每个值都换成另一个流,然后把所有的流连接起来成为一个流
    flatMap(Function<? super List<Child>, ? extends Stream<? extends R>> mapper)
    // .flatMap(Collection::stream)
    
    flatMap(Function<? super String[], ? extends Stream<? extends R>> mapper)
    // .flatMap(Arrays::stream)
    
        List<String> words = Arrays.asList("hello", "world");
        List<String> collect = words.stream().distinct().collect(Collectors.toList());
    
        List<String> list = words.stream()
                .map(str -> str.split("")) // Stream<String[]>
                .flatMap(Arrays::stream) // Stream<String>
                .distinct()
                .collect(Collectors.toList());
        System.out.println(list);
    
        Student student = new Student();
        Student student2 = new Student();
        List<Student> students = Arrays.asList(student, student2);
        List<Child> childList = students.stream() // Stream<Student>
                .map(Student::getChilds) // Stream<List<Child>>
                .flatMap(Collection::stream) // Stream<Child>
                .collect(Collectors.toList());
    
        Stream<List<Child>> listStream = students.stream().map(Student::getChilds);
        Stream<Child> childStream = students.stream().map(Student::getChilds).flatMap(Collection::stream);
        Stream<Child> childStream2 = students.stream().map(Student::getChilds).flatMap(childs -> childs.stream());
    
    public class Student {
      List<Child> childs;
    }
    

    4. 终止方法

    • void forEach(Consumer<? super T> action)
    • collect
    • max, min, count, sum, average
    • reduce
    • findFirst, firstAny, anyMatch, allmatch, noneMath, toArray

    4.1 collect

    List<String> aaa = list.stream().filter(str -> str.equals("aaa")).collect(Collectors.toList());
    

    4.2 reduce(...)

    • 归约操作:将流中的元素规约为单一值(通过重复应用二元运算符)
    • Stream.reduce(T identity, BinaryOperator<T> accumulator)
    // map 和 reduce 的连接通常称为 map-reduce 模式
    Optional<Integer> reduce = list.stream()
                                .map(OrderDO::getId)
                                .reduce(Integer::sum);
    // Integer.sum(int a, int b)
    public static int sum(int a, int b) {
      return a + b;
    }
    
    Optional<Integer> count = list.stream()
                      .map(OrderDO::getId)
                      .reduce((a, b) -> a + b);
    

    Reference

    • 《Java 实战》
    • 尚硅谷Java8新特性-李贺飞

    相关文章

      网友评论

          本文标题:Java8 Stream 基础

          本文链接:https://www.haomeiwen.com/subject/ujntgrtx.html