Java Stream流全面指南与多样实例

Java Stream流全方位指南与多元实例

Java Stream流最详尽教程

前言

我在日常项目中频繁使用Stream流,但对其理解尚浅,因此在此深入探究。使用Stream流时通常会涉及Java8的几项新特性,接下来我会简要介绍这些知识,以便在学习或应用Stream流时更为顺畅。

1. Lambda表达式

建议先熟悉函数式接口

1.1 语法规则

parameter -> expression body;

1.2 无参数的情况

当没有参数时,可呈现单条语句或多条语句的形式。例如:

()->System.out.println("baicaizhi");
()->{
    System.out.println("baicaizhi1");
    System.out.println("baicaizhi1");
}

1.3 单参数的情况

对于单个参数,有单条语句或多条语句的表现。比如:

a->System.out.println(a);
a->{
    System.out.println(a);
    System.out.println(a);
}

1.4 多参数的情况

多个参数时,有单条语句或多条语句的形式。例如:

(a,b)->a+b;
(a,b)->{
    int c = a+b;
    System.out.println(c);
}

2. 方法引用

应用场景:可用于静态方法调用或实例创建等情况

Test::new
Test::getName

3. Optional类

以下是Optional接口的相关信息:

接口方法 功能描述
Optional empty() 创建一个空的Optional实例
Optional of(T value) 创建一个非空的Optional实例,如果传入值为null则报错
Optional ofNullable(T value) 创建一个Optional实例,允许值为null
T get() 获取实例中的泛型值,若值为空则抛出异常
boolean isPresent() 检查实例是否非空,非空则返回true
boolean isEmpty() 检查实例是否为空,为空则返回true
ifPresent(Consumer) 当实例非空时执行指定的消费操作
ifPresentOrElse(Consumer, Runnable) 两个参数,分别在实例非空和为空时执行相应操作
Optional filter 对实例进行过滤操作
Optional map(Function) 进行转换操作
Optional flatMap(Function) 多层转换操作
Optional or(Supplier) 当实例为空时根据提供的供应函数创建新的Optional实例
T orElse(T) 当实例为空时获取指定的默认值
T orElseThrow() 非空时返回实例值,为空则抛出NoSuchElementException
T orElseThrow(Supplier) 非空时返回实例值,为空则抛出指定异常

4. Stream流概述

4.1.1 Stream流的定义

Stream流可将待处理的元素集合视为一种流动的数据,在流的处理过程中,借助Stream API对流中的元素开展各类操作,例如筛选、排序、聚合等。

4.1.2 Stream流的创建方式及操作分类

Stream流能够由数组或集合来创建,对流的操作可分为两类:

4.1.2.1 中间操作

中间操作会每次返回一个新的流,并且可以有多个中间操作。

4.1.2.2 终端操作

终端操作每一个流仅能执行一次,终端操作完成后流便无法再被使用,终端操作通常会生成一个新的集合或值。

4.1.3 Stream流的特性

  1. Stream流并不存储数据,而是依据特定规则对数据进行运算,通常会输出结果。
  2. Stream流不会对数据源进行修改,一般会生成一个新的集合或值。
  3. Stream流具备延迟执行特性,仅有在调用终端操作时,中间操作才会得以执行。

4.2 Stream流的创建

4.2.1 通过java.util.Collection.stream()方法利用集合创建流

    List<String> list = Arrays.asList("a", "b", "c");        // 创建顺序流       
        Stream<String> stream = list.stream();        // 创建并发流       
        Stream<String> stringStream = list.parallelStream();

4.2.2 使用java.util.Arrays.stream(T[] array)方法利用数组创建流

      //数组创建流        
      int[] array = {1,2,3};        
      IntStream stream1 = Arrays.stream(array);

4.2.3 使用Stream的静态方法:of()、iterate()、generate()

     //stream静态方法创建流       
       Stream<Integer> integerStream = Stream.of(1, 2);        
       Stream<Integer> iterate = Stream.iterate(0, x -> x = 3);        
       Stream<Double> limit = Stream.generate(Math::random).limit(3);

4.2.4 顺序流转换成并发流

      //顺序流转换成并发流        
      Optional<String> first = list.stream().parallel().filter(x -> x > 6).findFirst();

4.3 Stream流的使用

4.3.1 数据准备

class Person {
 private String name;  // 姓名
 private int salary; // 薪资
 private int age; // 年龄
 private String sex; //性别
 private String area;  // 地区
 // 构造方法
 public Person(String name, int salary, int age,String sex,String area) {
  this.name = name;
  this.salary = salary;
  this.age = age;
  this.sex = sex;
  this.area = area;
 }
 // 省略了get和set,请自行添加 
}

4.3.2 Stream流的使用

4.3.2.1 遍历与匹配(foreach/find/match)

Stream流同样支持像集合那样的遍历和元素匹配操作,不过Stream流中的元素是以Optional类型呈现的。Stream流的遍历和匹配操作较为简便。

List<Integer> list = Arrays.asList(1, 2, 3, 4, 7, 6, 5, 8);
            // 遍历输出符合条件的元素
            list.stream().filter(x -> x > 6).forEach(System.out::println);
            // 匹配第一个元素
            Optional<Integer> first = list.stream().filter(x -> x > 6).findFirst();
            // 匹配任意元素(适用于并行流)
            Optional<Integer> any = list.parallelStream().filter(x -> x > 6).findAny();
            // 检查是否存在符合特定条件的元素
            boolean b = list.stream().anyMatch(x -> x < 6);
            System.out.println("匹配到的第一个值:" + first.get());
            System.out.println("匹配到的任意值:" + any.get());
            System.out.println("是否存在小于6的值:" + b);
4.3.2.2 筛选操作

筛选操作是按照一定规则对Stream流中的元素进行校验,将符合条件的元素提取到新流中的操作。

4.3.2.3 聚合操作(max/min/count)
List<Person> personList = new ArrayList<Person>();
            personList.add(new Person("Tom", 8900, 11,"male", "New York"));
            personList.add(new Person("Jack", 7000, 12,"male", "Washington"));
            personList.add(new Person("Lily", 7800, 13,"female", "Washington"));
            personList.add(new Person("Anni", 8200, 14,"female", "New York"));
            personList.add(new Person("Owen", 9500, 15,"male", "New York"));
            personList.add(new Person("Alisa", 7900, 16,"female", "New York"));
            List<Integer> list = Arrays.asList(1,2,3,4,7,6,5,8);

            //筛选出Integer集合中大于7的元素,并打印出来
            list.stream().filter(x->x>7).forEach(System.out::println);
            //筛选员工中工资高于8000的人,并形成新的集合。 形成新集合依赖collect(收集)
            List<String> collect = personList.stream().filter(value -> value.getSalary() > 8000).map(Person::getName).collect(Collectors.toList());
            System.out.println("工资高于8000"+collect);
4.3.2.4 映射操作(map/flatMap)

映射操作可将一个Stream流的元素按照特定映射规则映射到另一个流中,分为map和flatMap:
- map:接收一个函数作为参数,该函数会应用到每个元素上,并将其映射为新元素。
- flatMap:接收一个函数作为参数,将流中的每个值转换成另一个流,然后将所有流连接成一个流。

     List<Person> personList = new ArrayList<Person>();
            personList.add(new Person("Tom", 8900, 11,"male", "New York"));
            personList.add(new Person("Jack", 7000, 12,"male", "Washington"));
            personList.add(new Person("Lily", 7800, 13,"female", "Washington"));
            personList.add(new Person("Anni", 8200, 14,"female", "New York"));
            personList.add(new Person("Owen", 9500, 15,"male", "New York"));
            personList.add(new Person("Alisa", 7900, 16,"female", "New York"));
            List<Integer> list = Arrays.asList(1,2,3,4,7,6,5,8);
            List<String> strList = Arrays.asList("ad,nm", "adm,mt", "p,ot", "xb,angd", "weou,jgsd");
            //英文字符串数组的元素全部改为大写。整数数组每个元素+3
            List<Integer> collect = list.stream().map(x -> x + 3).collect(Collectors.toList());
            List<String> collect1 = strList.stream().map(String::toUpperCase).collect(Collectors.toList());
            //将员工的薪资全部增加1000
            //不改变源集合的方式
            List<Person> collect2 = personList.stream().map(person -> {
                Person person1 = new Person(person.getName(), 0, person.getAge(), person.getSex(), person.getArea());
                person1.setSalary(person.getSalary() + 1000);
                return person1;
            }).collect(Collectors.toList());
            //改变源集合的方式
            List<Person> collect3 = personList.stream().map(person -> {
                person.setSalary(person.getSalary() + 1000);
                return person;
            }).collect(Collectors.toList());
            //将两个字符数组合并成一个新的字符数组
            List<String> collect4 = strList.stream().flatMap(s -> {
                String[] s2 = s.split(",");
                return Arrays.stream(s2);
            }).collect(Collectors.toList());
            System.out.println("每个元素大写:" + collect1);
            System.out.println("每个元素+3:" + collect);
            //注意,执行的时候分开执行,否则看不出来效果
            System.out.println("一次改动前:" + personList.get(0).getName() + "-->" + personList.get(0).getSalary());
            System.out.println("一次改动后:" + collect2.get(0).getName() + "-->" + collect2.get(0).getSalary());
            System.out.println("二次改动前:" + personList.get(0).getName() + "-->" + personList.get(0).getSalary());
            System.out.println("二次改动后:" + collect3.get(0).getName() + "-->" + collect3.get(0).getSalary());
            System.out.println("处理前的集合:" + strList);
            System.out.println("处理后的集合:" + collect4);
4.3.2.5 归约操作(reduce)

归约操作是将一个Stream流缩减为一个值,可实现对集合的求和、求乘积和求最值等操作。

List<Person> personList = new ArrayList<Person>();
            personList.add(new Person("Tom", 8900, 11,"male", "New York"));
            personList.add(new Person("Jack", 7000, 12,"male", "Washington"));
            personList.add(new Person("Lily", 7800, 13,"female", "Washington"));
            personList.add(new Person("Anni", 8200, 14,"female", "New York"));
            personList.add(new Person("Owen", 9500, 15,"male", "New York"));
            personList.add(new Person("Alisa", 7900, 16,"female", "New York"));
            List<Integer> list = Arrays.asList(1,2,3,4,7,6,5,8);
            List<String> strList = Arrays.asList("ad,nm", "adm,mt", "p,ot", "xb,angd", "weou,jgsd");
    //        求Integer集合的元素之和、乘积和最大值
            // 求和方式1
            Optional<Integer> reduce = list.stream().reduce((x, y) -> x + y);
            // 求和方式2
            Optional<Integer> reduce1 = list.stream().reduce(Integer::sum);
            // 求和方式3
            Integer reduce2 = list.stream().reduce(0, Integer::sum);
            // 求乘积
            Optional<Integer> reduce3 = list.stream().reduce((x, y) -> x * y);
            // 求最大值方式1
            Optional<Integer> reduce4 = list.stream().reduce((x, y) -> x > y ? x : y);
            // 求最大值写法2
            Integer reduce5 = list.stream().reduce(1, Integer::max);
    //        求所有员工的工资之和和最高工资
            // 求和方式1
            Optional<Integer> reduce7 = personList.stream().map(Person::getSalary).reduce(Integer::sum);
            // 求和方式2
            Integer reduce6 = personList.stream().reduce(0, (sum, p) -> sum += p.getSalary(),(sum1,sum2)->sum1+sum2);
            // 求和方式3
            Integer reduce8 = personList.stream().reduce(0, (sum, p) -> sum += p.getSalary(), Integer::sum);
            // 求最高工资方式1:
            Integer reduce9 = personList.stream().reduce(0, (max, p) -> max > p.getSalary() ? max : p.getSalary(),Integer::max);
            // 求最高工资方式2:
            Integer reduce10 = personList.stream().reduce(0, (max, p) -> max > p.getSalary() ? max : p.getSalary(), (max1, max2) -> max1 > max2 ? max1 : max2);
            System.out.println("list求和:" + reduce.get() + "," + reduce1.get() + "," + reduce2);
            System.out.println("list求积:" + reduce3.get());
            System.out.println("list求最大值:" + reduce4.get() + "," + reduce5);
            System.out.println("工资之和:" + reduce7.get() + "," + reduce6 + "," + reduce8);
            System.out.println("最高工资:" + reduce9 + "," + reduce10);
4.3.2.6 收集操作(collect)

collect操作可将Stream流中的数据收集起来,最终可收集成一个值或新集合,主要依赖java.util.stream.Collectors类内置的静态方法。

4.3.2.6.1 归集(toList/toSet/toMap)

由于Stream流不存储数据,处理完流中数据后需将其归集到新集合,toList、toSet和toMap较为常用,还有toCollection、toConcurrentMap等复杂用法。
```
List personList = new ArrayList();
personList.add(new Person("Tom", 8900, 11,"male", "New York"));
personList.add(new Person("Jack", 7000, 12,"male", "Washington"));
personList.add(new Person("Lily", 7800, 13,"female", "Washington"));
personList.add(new Person("Anni", 8200, 14,"female", "New York"));
personList.add(new Person("Owen", 9500, 15,"male", "New York"));
personList.add(new Person("Alisa", 7900, 16,"female", "New York"));
List list = Arrays.asList(1,2,3,4,7,6,5,8);
List strList = Arrays.asList("ad,nm", "adm,mt", "p,ot", "xb,angd", "weou,jgsd");
List collect = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
Set collect1 = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toSet());
Map collect2 = personList.stream().filter(p -> p.getSalary() > 8000

文章整理自互联网,只做测试使用。发布者:Lomu,转转请注明出处:https://www.it1024doc.com/12640.html

(0)
LomuLomu
上一篇 2025 年 6 月 25 日
下一篇 2025 年 6 月 25 日

相关推荐

  • 【初阶数据结构与算法】八大排序之非递归系列( 快排(使用栈或队列实现)、归并排序)

    * 文章目录 一、非递归版快排 1.使用栈实现非递归版快排 2.使用队列实现非递归版快排 二、非递归版归并排序 1.非递归版归并排序的实现 一、非递归版快排 1.使用栈实现非递归版快排 在学习非递归版快排前,建议大家先学习递归版的快排,否则非递归版的快排将很难理解,这里附上本人写的快排的博客解析:【初阶数据结构与算法】八大排序算法之交换排序(冒泡排序,快速排…

    2025 年 1 月 11 日
    39800
  • Windows环境下MySQL与Navicat的安装配置攻略

    文章标题:Windows系统中MySQL与Navicat的安装配置详细指南 文章目录 一、 MySQL 的获取 1. 官方网站获取 2. 其他途径 二、 MySQL 的安装流程 三、 MySQL 的验证与配置 四、 NaviCat 的获取 1. 官方网站下载 2. 其他来源 五、 NaviCat 的安装步骤 六、 NaviCat 的逆向工程操作 一、 MyS…

    2025 年 7 月 7 日
    47400
  • 免费下载官方clion激活码,全套clion破解教程收录

    申明:本教程Clion破解补丁、激活码均收集于网络,请勿商用,仅供个人学习使用,如有侵权,请联系作者删除。若条件允许,希望大家购买正版 ! 废话不多说,先上 Clion2025.2.1 版本破解成功的截图,如下图,可以看到已经成功破解到 2099 年辣,舒服的很! 接下来就给大家通过图文的方式分享一下如何破解最新的Clion。 准备工作 注意:如果你之前用过…

    2026 年 1 月 26 日
    15000
  • 无需额外安装最新版webstorm激活码,零门槛破解教程

    申明:本教程 WebStorm破解补丁、激活码均收集于网络,请勿商用,仅供个人学习使用,如有侵权,请联系作者删除。若条件允许,希望大家购买正版 ! 废话不多说,先上 WebStorm 2025.2.1 版本破解成功的截图,如下图,可以看到已经成功破解到 2099 年辣,舒服的很! 接下来就给大家通过图文的方式分享一下如何破解最新的WebStorm。 如果觉得…

    2025 年 12 月 14 日
    27800
  • IntelliJ IDEA 2025.3 永久破解

    IntelliJ IDEA永久破解激活完整指南(2025最新版) 重要声明:本教程所涉及的IDEA破解补丁及激活码均来源于网络收集,仅限个人学习研究使用,严禁用于商业目的。若经济条件允许,强烈建议购买正版软件支持开发者! IntelliJ IDEA是JetBrains公司打造的一款顶级集成开发环境,功能全面且强大,完美兼容Windows、macOS和Linu…

    IDEA破解教程 2026 年 1 月 9 日
    20700

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信