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
上一篇 8小时前
下一篇 4小时前

相关推荐

  • Mysql

    MySQL 学习整理 MySQL 基础架构 最上层的客户端所包含的服务并不是 MySQL 独有的,大多数基于网络的客户端/服务器工具或服务器都有类似的服务,包括连接处理、身份验证、确保安全性等。 第二层包含了大多数 MySQL 的核心功能,包括查询解析、分析、优化、以及所有的内置函数(例如,日期、时间、数学和加密函数),所有跨存储引擎的功能也都在这一层实现:…

    2025 年 1 月 6 日
    27200
  • java: JDK isn‘t specified for module ‘product-service‘问题解决

    目录 问题 解决方法 1.打开File->Project Structure… 2.将Project SDK修改为17 Oracle OpenJDK 17.0.12,并Apply,OK 问题 添加module后报错:java: JDK isn’t specified for module ‘product-service’ 查看pom.xml文件也添加了…

    2025 年 1 月 21 日
    39300
  • 2025年最新IDEA激活码分享:永久破解IDEA全系列教程(支持2099年)

    本文将详细介绍如何永久激活JetBrains全系列IDE工具(包括IDEA、PyCharm、DataGrip、Goland等),让你的开发工具有效期延长至2099年! 准备工作:下载IDEA安装包 如果你还没有安装IDEA,请先前往官网下载最新版本:https://www.jetbrains.com/idea/download/ 安装过程非常简单:1. 选择…

    2025 年 5 月 10 日
    43100
  • 2025最新PyCharm永久激活码及破解教程(亲测有效2099年)🔥

    本教程适用于JetBrains全家桶(IDEA、PyCharm、DataGrip、Goland等)所有产品!💯 先给大家看看最新PyCharm版本破解成功的实锤截图👇 有效期直接拉到2099年,简直不要太爽! 下面我就手把手教大家如何轻松激活PyCharm,这个方法通杀所有版本,无论你是: 🖥️ Windows用户 🍎 Mac用户 🐧 Linux用户 统统适…

    2025 年 5 月 13 日
    1.2K00
  • 🚀 2025年最新IDEA激活码分享:永久破解IDEA终极教程(附破解补丁)

    💻 教程简介 本教程适用于JetBrains全家桶,包括IDEA、PyCharm、DataGrip、Goland等所有产品!无需繁琐操作,轻松实现永久激活至2099年!✨ 先给大家看看最新IDEA版本破解成功的实锤截图,有效期直达2099年,简直不要太爽! 📥 第一步:下载IDEA安装包 还没安装的小伙伴看这里!访问JetBrains官网:https://w…

    2025 年 6 月 7 日
    19200

发表回复

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

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

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

关注微信