Bootstrap

求职之路 | 2024年Java从入门到干活:第18章JDK8-JDK21新特性(二)——Stream API

 跟领导技术层面意见不合时,别犟,领导要考虑如何赚钱,你考虑如何做好,有时候错的是对的,对的反而是错的,但跟同事,必须一战到底,教他如何做一名合格的程序员。

——大龙不聋

《求职之路 | 2024年Java从入门到干活:第18章JDK8-JDK21新特性(一)——Lambda表达式》

接着上一章节,我们继续学习Java8的新特性。

目录

5、Stream API

5.1 介绍

5.2 存在的意义

5.3 什么是Stream

5.4 Stream的操作三个步骤

5.5 创建Stream的方式

5.5.1 方式一:通过集合创建

5.5.2 方式二:通过数组创建

5.5.3 方式三:通过Stream的of()创建

5.5.4 方式四:创建无线流(迭代、生成)

5.6 Stream中间操作

5.6.1 筛选与切片

5.6.2 映射

5.6.3 排序

5.7 终止操作

5.7.1 匹配与查找

5.7.2 归约

5.7.3 收集


5、Stream API

5.1 介绍

Stream API把真正的函数式编程引入到Java中。毫不夸张的说,他是目前为止对Java类库最好的补充,它极大提升Java程序员的生产力,写出高效、简洁的代码,让程序员的思绪在指尖跳舞,牛逼的不要不要滴。

Stream API是处理集合的关键抽象概念,对集合可以执行复杂的操作,如查找、过滤、映射等等,使用起来就像使用SQL操作数据库一样操作集合。Stream API提供一种高效且易于使用的处理数据的方式。

5.2 存在的意义

我们在项目开发中,许多项目(比如web项目)数据层用Oracle、MySql等关系型数据库,这些关系型数据库通过Sql即可实现增删改查。但是现在许多项目用MongDB、NoSQL、Redis等非关系型数据库,对这些数据的处理,往往需要在Java层面进行操作了。

说的这么多,究竟啥意思?我画图解释一下哈。

一个web项目,数据源是关系型数据库,基于Sql可以完成对数据的重要操作,如下图:

一个非关系型数据库项目,我们可以在内存中基于Stream API对数据进行操作,如下图:

5.3 什么是Stream

Stream是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列,它可以实现对数据源的复杂操作,例如查找、过滤、排序和映射等。

Stream VS Collection集合的区别:

①、Collection是一种静态的内存数据结构,存储在内存中,它的本质是数据

②、Stream是通过CPU来进行运算的,它的本质是计算

5.4 Stream的操作三个步骤

①、创建Stream

一个数据源(集合,数组),获取一个流。

②、中间操作

一个中间操作链,对数据源的数据进行处理,但在终结操作前,并不会真正执行。如筛选与切片、映射、排序。

③、终止操作

 一个终止操作,执行中间操作链,最终产生结果并结束Stream。如匹配与查找、归约、收集

5.5 创建Stream的方式

5.5.1 方式一:通过集合创建

Java 8 中Collection接口中扩展两个默认方法(Java 8新特性,接口中可以扩展静态方法和默认方法):

  • default Stream<E> stream() : 返回一个顺序流
  • default Stream<E> parallelStream() : 返回一个并行流
public class StreamAPITest {

    // 方式一:通过集合创建
    // Collection | default Stream<E> stream():返回一个顺序流
    // Collection | default Stream<E> parallelStream():返回一个并行流
    @Test
    public void test1() {

        List<Employee> list = new ArrayList<>();
        list.add(new Employee("张三", 35, 6899.0));
        list.add(new Employee("张龙", 25, 5769.0));
        list.add(new Employee("赵武", 26, 4568.0));
        list.add(new Employee("马汉", 38, 7568.0));

        // 创建一个顺序流
        Stream<Employee> stream1 = list.stream();
        stream1.forEach(System.out :: println);

        System.out.println("====================我是分割线====================");

        // 创建一个并行流
        Stream<Employee> stream2 = list.parallelStream();
        stream2.forEach(System.out :: println);
    }

}

class Employee {

    private String name;
    private int age;
    private double salary;

    public Employee() {
        System.out.println("Employee().....");
    }

    public Employee(String name) {
        this.name = name;
    }

    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Employee(String name, int age, double salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee{" + "name='" + name + '\'' + ", age=" + age + ", salary=" + salary + '}';
    }
}
5.5.2 方式二:通过数组创建

Java8中Arrays静态方法stream() 可以获取数组流:

  • public static IntStream stream(int[] array)
  • public static LongStream stream(long[] array)
  • public static DoubleStream stream(double[] array)
  • static<T> Stream<T> stream(T[] array)
    // 方式二:通过数组创建
    // Arrays | static <T> Stream<T> stream重载方法:返回一个流
    @Test
    public void test2() {
        // Arrays 有多个stream重载方法,可传入基本类型,也可传入类类型
        int[] arr1 = new int[]{1, 2, 3, 4, 5};
        IntStream stream1 = Arrays.stream(arr1);

        double[] arr2 = new double[]{1.0, 2.0, 3.0, 4.0, 5.0};
        DoubleStream stream2 = Arrays.stream(arr2);

        long[] arr3 = new long[]{1, 2, 3, 4, 5};
        LongStream stream3 = Arrays.stream(arr3);

        Integer[] arr4 = new Integer[]{1, 2, 3, 4, 5};
        Stream<Integer> stream = Arrays.stream(arr4);

        // ...
    }
5.5.3 方式三:通过Stream的of()创建

可以调用Stream的静态方法of(),显示创建一个流,它的参数是可变长参数:

  • public static<T> Stream<T> of(T ... values):返回一个流
    // 方式三:通过Stream的o
;