3.4 流式操作

2023-10-30

1.简介
(1).概念
Stream是数据渠道,用于操作数据源所生成的元素序列,它可以实现对集合的复杂操作,例如过滤、排序和映射等。
集合是一种静态的数据结构,存储在内存中,而Stream是通过CPU来实现计算的(并不会存储数据)。Stream不会改变源对象,而是返回一个新的持有结果的Stream(不可变)。

(2).为什么要使用Stream
在实际开发中,项目中的很多数据都来源于关系型数据库(例如MySQL、Oracle等),使用SQL的条件语句就可以实现对数据的筛选、过滤等操作。但也有很多数据来源于非关系型数据库(例如Redis、MongoDB等),想要处理这些数据,往往需要在Java层面去操作。
而Stream API就提供了对集合中数据的操作,类似于SQL执行的数据库查询。简单来说,Stream API提供了一种高效且易于使用的数据处理方式。

(3).Stream操作的执行流程

  1. 创建Stream对象:通过一个数据源(例如集合、数组)创建一个流。
  2. 中间操作:一个中间的链式操作,对数据源的数据进行处理(例如过滤、排序等),直到执行终止操作才执行(Stream操作是延迟执行的)。
  3. 终止操作:一旦执行终止操作,就执行中间的链式操作,并产生结果。

(4).涉及到的对象定义

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
class Book {
    public String title;
    public String author;
    public Integer pages;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return Objects.equals(title, book.title) &&
                Objects.equals(author, book.author)
                && Objects.equals(pages,book.pages);
    }

    @Override
    public int hashCode() {
        return Objects.hash(title, author, pages);
    }
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Author {
    public String name;

    public String title;
}

2.创建Stream
(1).返回一个串行流

public class CreateStreamByCollection {
    public static void main(String[] args) {
        List<String> stringList = new ArrayList<>();
        stringList.add("hello");
        stringList.add("world");
        
        //通过集合获取串行Stream
        Stream<String> stream = stringList.stream();
        //打印元素
        stream.forEach(str -> System.out.println(str));
    }
}

(2).返回一个并行流

public class CreateParallelStreamByCollection {
    public static void main(String[] args) {
        List<String> stringList = new ArrayList<>();
        stringList.add("hello");
        stringList.add("world");
        
        //通过集合获取并行Stream
        Stream<String> parallelStream = stringList.parallelStream();
        //打印元素
        parallelStream.forEach(str -> System.out.println(str));
    }
}

串行流和并行流的区别:串行流从集合中取数据是按照集合的顺序取的,而并行流是并行操作的,获取到的数据是无序的。

3.中间操作
(1).简介
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理。在终止操作时会一次性全部处理这些中间操作,称为“惰性求值”。

(2).filter

public class StreamFilter {
    public static void main(String[] args) {
    	//从流中清除某些元素
        //初始化一个包含3个Book对象的数组,并转化为List
        List<Book> bookList = Arrays.asList(
                new Book("C++编程", "张三", 1216),
                new Book("C#编程", "张三", 365),
                new Book("Java编程", "李四", 223)
        );
        
        bookList.stream()
                .filter(book -> book.getPages() >= 500)
                .forEach(System.out::println); //触发终止操作才能执行中间操作,遍历列表中元素并打印
    }
}

(3).distinct

public class StreamFilter {
    public static void main(String[] args) {
    	//通过流生成元素的hashCode和equals()方法去除重复元素
        //初始化一个包含5个Book对象的数组,其中有2个重复的元素,并转化为List
        List<Book> bookList = Arrays.asList(
                new Book("C++编程", "张三", 1216),
                new Book("C#编程", "张三", 365),
                new Book("Java编程", "李四", 223),
                new Book("C++编程", "张三", 1216),
                new Book("C#编程", "张三", 365)
        );
        //创建流
        System.out.println("去重前,集合中的元素为:");
        bookList.stream()
                .forEach(System.out::println);

        System.out.println("去重后,集合中的元素为:");
        //创建一个新流,然后调用distinct()方法去除重复元素,并调用终止操作打印集合中元素
        bookList.stream()
                .distinct()
                .forEach(System.out::println);
    }
}

(4).limit

public class StreamLimit {
    public static void main(String[] args) {
    	//截取流的前几个元素
        //初始化一个包含3个Book对象的数组,并转化为List
        List<Book> bookList = Arrays.asList(
                new Book("C++编程", "张三", 1216),
                new Book("C#编程", "张三", 365),
                new Book("Java编程", "李四", 223)
        );
        //创建一个流,通过limit()方法截取前2个元素,最后遍历列表中元素并打印
        bookList.stream()
                .limit(2)
                .forEach(System.out::println);
    }
}

(5).skip

public class StreamSkip {
    public static void main(String[] args) {
    	//返回一个扔掉了前n个元素的流,与limit互补。若流中元素不足n个,则返回一个空流
        //初始化一个包含3个Book对象的数组,并转化为List
        List<Book> bookList = Arrays.asList(
                new Book("C++编程", "张三", 1216),
                new Book("C#编程", "张三", 365),
                new Book("Java编程", "李四", 223)
        );
        //创建一个流,通过skip()方法扔掉前2个元素,最后遍历列表中元素并打印
        bookList.stream()
                .skip(2)
                .forEach(System.out::println);
    }
}

(6).map

public class StreamMapping {
    public static void main(String[] args) {
    	//接收一个方法作为参数,该方法会被应用到每个元素上,并将其映射成一个新的元素
        //初始化一个包含3个Book对象的数组,并转化为List
        List<Book> bookList = Arrays.asList(
                new Book("C++编程", "张三", 1216),
                new Book("C#编程", "张三", 365),
                new Book("Java编程", "李四", 223)
        );

        //将bookList中name为张三的元素,转化为Author对象,并最终转化为authorList
        List<Author> authorList = bookList.stream()
                .map(book -> {
                    Author author = new Author();
                    if ("张三".equals(book.getAuthor())) {
                        author.setName(book.getAuthor());
                        author.setTitle(book.getTitle());
                    }
                    return author;
                }).collect(Collectors.toList());
        //过滤掉name为null的元素并打印name为张三的元素
        authorList.stream()
                .filter(author -> Objects.nonNull(author.getName()))
                .forEach(System.out::println);
}
public class StreamMapping {
    public static void main(String[] args) {
        //初始化一个包含3个Book对象的数组,并转化为List
        List<Book> bookList = Arrays.asList(
                new Book("C++编程", "张三", 1216),
                new Book("C#编程", "张三", 365),
                new Book("Java编程", "李四", 223)
        );
        //将book元素的author字段收集为一个字符串数组
        List<String> authorStrings = bookList.stream()
                .map(b -> b.getAuthor())
                .collect(Collectors.toList());
        //打印元素
        System.out.println(authorStrings);
    }
}
public class StreamMapping {
    public static void main(String[] args) {
        //创建一个包含小写字母元素的字符串列表
        List<String> stringList = Arrays.asList("php", "js", "python", "java");
        /*
         * 调用map()方法,将String的toUpperCase()方法作为参数
         * 这个方法会被应用到每个元素上,映射成一个新元素,最后打印映射后的元素
         */
        stringList.stream()
                .map(String::toUpperCase)
                .forEach(System.out::println);
    }
}

(7).sorted

public class SortedByComparator {
    public static void main(String[] args) {
    	//按照从大到小顺序排序
        //初始化一个包含3个Book对象的数组,并转化为List
        List<Book> bookList= Arrays.asList(
                new Book("C++编程", "张三", 1216),
                new Book("C#编程", "张三", 365),
                new Book("Java编程", "李四", 223)
        );
        //定制排序,并打印每个元素
        bookList.stream()
                .sorted((b1, b2) -> -Integer.compare(b1.getPages(), b2.getPages()))
                .forEach(System.out::println);
    }
}
public class SortedByComparator {
    public static void main(String[] args) {
        //初始化一个包含6个乱序值的Integer型数组,并转化为List
        List<Integer> integers = Arrays.asList(10, 12, 9, 8, 20, 1);
        //定制排序,并打印每个元素
        integers.stream()
        .sorted((i1, i2) -> -Integer.compare(i1, i2))
        .forEach(System.out::println);
    }
}
public class Sorted {
    public static void main(String[] args) {
    	//按照自然顺序排序
        //初始化一个包含6个乱序值的Integer型数组,并转化为List
        List<Integer> integers = Arrays.asList(10, 12, 9, 8, 20, 1);
        //调用sorted()方法自然排序,并打印每个元素
        integers.stream()
                .sorted()
                .forEach(System.out::println);
    }
}

4.终止操作
(1).简介
执行终止操作会从流的流水线上生成结果,其结果可以是任何不是流的值,例如List、String或者void等。

(2).匹配

public class StreamMatch {
    public static void main(String[] args) {
        //初始化一个包含5个Book对象的数组,其中有2个重复的元素,并转化为List
        List<Book> bookList = Arrays.asList(
                new Book("C++编程", "张三", 1216),
                new Book("C#编程", "张三", 365),
                new Book("Java编程", "李四", 223),
                new Book("C++编程", "张三", 1216),
                new Book("C#编程", "张三", 365)
        );
        //使用allMatch()检查是否所有元素匹配已知条件,如果匹配,则返回true,否则返回false
        boolean b1 = bookList.stream().allMatch(book -> book.getPages() > 300);
        if (b1) {//预计输出
            System.out.println("列表中所有元素的页码数都大于300");
        } else {
            System.out.println("列表中有元素的页码数小于等于300");
        }

        //使用anyMatch()检查是否至少有一个元素匹配已知条件,如果匹配,则返回true,否则返回false
        boolean b2 = bookList.stream().anyMatch(book -> book.getPages() > 1200);
        if (b2) {//预计输出
            System.out.println("列表中至少存在一个的元素的页码数大于1200");
        } else {
            System.out.println("列表中不存在元素页码数大于1200");
        }

        //使用noneMath()检查是否没元素匹配已知条件的,如果匹配,则返回true,否则返回false
        boolean b3 = bookList.stream().noneMatch(book -> book.getPages() > 1200);
        if (b3) {
            System.out.println("列表中不存在元素页码数大于1200");
        } else {//预计输出
            System.out.println("列表中至少存在一个的元素的页码数大于1200");
        }
    }
}

(3).查找

public class StreamFind {
    public static void main(String[] args) {
        //初始化一个包含5个Book对象的数组,其中有2个重复的元素,并转化为List
        List<Book> bookList = Arrays.asList(
                new Book("C++编程", "张三", 1216),
                new Book("C#编程", "张三", 365),
                new Book("Java编程", "李四", 223),
                new Book("C++编程", "张三", 1216),
                new Book("C#编程", "张三", 365)
        );
        //使用findFirst()获取当前流中的第一个元素
        Optional<Book> first = bookList.stream().findFirst();
        System.out.println("列表中第一个元素为:" + first);

        //使用findAny()获取当前流中的任意一个元素
        Optional<Book> any = bookList.stream().findAny();
        System.out.println("列表中任意一个元素为:" + any);

        //使用count()获取当前流中的元素总数
        long count = bookList.stream().count();
        System.out.println("列表中元素总数为" + count);

        //使用max(Comparator c)获取流中最大值
        Optional<Book> max = bookList.stream().max(Comparator.comparingInt(Book::getPages));
        System.out.println("列表中元素页码最大值为" + max.get().getPages());

        //使用min(Comparator c)获取流中最小值
        Optional<Book> min = bookList.stream().min(Comparator.comparingInt(Book::getPages));
        System.out.println("列表中元素页码最小值为" + min.get().getPages());
    }
}

(4).收集

@Slf4j
public class StreamCollect {
    public static void main(String[] args) {
        //创建一个包含7个Integer型的数据,并转为List
        List<Integer> integerList = Arrays.asList(10, 12, 9, 8, 20, 1, 10);
        //将List流转换为其他Set集合
        Set<Integer> collect = integerList.stream().collect(Collectors.toSet());
        System.out.println(collect);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

3.4 流式操作 的相关文章

  • 使用 Guice 注入类集合

    我正在尝试用 Google Guice 2 0 注入东西 我有以下结构 FooAction implements Action BarAction implements Action 然后我有一个带有以下构造函数的 ActionLibrar
  • 将一种类型的对象声明为另一种类型的实例有什么好处? [复制]

    这个问题在这里已经有答案了 可能的重复 Base b2 new Child 是什么意思 表示 https stackoverflow com questions 4447924 what does base b2 new child sig
  • 如何使用 Maven Failsafe 插件运行 JUnit 5 集成测试?

    当我运行命令时 Maven Failsafe 插件找不到我的 JUnit 5 集成测试mvn clean failsafe integration test 尽管它可以找到文件 我有junit jupiter api and junit j
  • 如何配置 Spring-WS 以使用 JAXB Marshaller?

    感谢您到目前为止对此的帮助 我正在更新问题 因为我没有显示我需要的所有内容 并显示了建议的更改 肥皂输出仍然不是我想要的 servlet xml
  • OpenNLP 与斯坦福 CoreNLP

    我一直在对这两个包进行一些比较 但不确定该往哪个方向走 我简单地寻找的是 命名实体识别 人 地点 组织等 性别识别 一个不错的训练 API 据我所知 OpenNLP 和斯坦福 CoreNLP 提供了非常相似的功能 然而 Stanford C
  • 在 Junit 测试中使用 ReflectionTestUtils.setField()

    我是 JUnittesting 的新手 所以我有一个问题 谁能告诉我为什么我们使用ReflectionTestUtils setField 在我们的 Junit 测试示例中 正如评论中提到的 java 文档很好地解释了用法 但我还想给你们举
  • Java 中的 ExecuteUpdate sql 语句不起作用

    我正在学习如何将 SQL 与 Java 结合使用 我已成功安装 JDBC 驱动程序 并且能够从数据库读取记录并将其打印在屏幕上 我的问题发生在尝试执行更新或插入语句时 没有任何反应 这是我的代码 问题所在的方法 public static
  • 从 HttpClient 3 转换为 4

    我已经成功地对所有内容进行了更改 但以下内容除外 HttpClient client HttpPost method client new DefaultHttpClient method new HttpPost url InputStr
  • Cucumber DataTable 错误 - io.cucumber.datatable.UndefinedDataTableTypeException:无法将 DataTable 转换为 cucumber.api.DataTable

    尝试使用 cucumber selenium java intelliJ 运行场景 但在其中一个步骤中出现有关 DataTable 的错误 在我开始使用测试运行程序并更改周围的一些内容之前 数据表工作正常并正确转换该步骤的参数 但我就是无法
  • 查找数组中的组合

    我在java中有一个像这样的二维数组 transmission communication tv television approach memorycode methodact 我需要获得所有组合 例如 transmission appr
  • 如何使用 swagger-codegen-plugin (maven) 生成客户端代码?

    我需要使用 swagger codegen plugin for maven 在 eclipse 中生成服务器存根代码 你能帮忙怎么做吗 以及需要什么配置 在 pom xml 中 我找到了这个答案 您只需要像下面这样更改 pom xml 即
  • 从 Android 访问云存储

    我一直无法找到任何有关如何从 Android 应用程序使用云存储的具体文档 我确实遇到过这个客户端库 https cloud google com storage docs reference libraries然而 Google Clou
  • Android 解析 JSON 卡在 get 任务上

    我正在尝试解析一些 JSON 数据 我的代码工作了一段时间 我不确定我改变了什么突然破坏了代码 当我运行代码时 我没有收到任何运行时错误或警告 我创建一个新的 AsyncTask 并执行它 当我打电话时 get 在这个新任务中 调试器在此行
  • 多线程——更快的方法?

    我有一堂有吸气剂的课程getInt 和一个二传手setInt 在某个领域 比如说领域 Integer Int 一个类的一个对象 比如说SomeClass The setInt 这里是同步的 getInt isn t 我正在更新的值Int来自
  • 改变 Java 中凯撒移位的方向

    用户可以通过选择 1 向左或 2 向右移动字母来选择向左或向右移动 左边工作正常 右边不行 现在它显示了完全相同的循环 但我已经改变了所有 and 以不同的方式进行标记 最终我总是得到奇怪的字符 如何让程序将字符向相反方向移动 如果用户输入
  • MongoDB java 驱动程序 3.0 在身份验证时无法捕获异常

    我超级卡住o 0 在尝试通过 Java 驱动程序进行身份验证时 存在捕获异常的问题 正如你可能会看到的Throwable类不工作 private MongoClient mongoClient private MongoDatabase m
  • 在循环中按名称访问变量

    我正在开发一个 Android 项目 并且有很多可绘制对象 这些绘图的名称都类似于icon 0 png icon 1 png icon 100 png 我想将这些可绘制对象的所有资源 ID 添加到整数 ArrayList 中 对于那些不了解
  • Java String ReplaceAll 方法给出非法重复错误?

    我有一个字符串 当我尝试运行时replaceAll方法 我收到这个奇怪的错误 String str something op str str replaceAll o n it works fine str str replaceAll n
  • CXF:通过 SOAP 发送对象时如何排除某些属性?

    我使用 Apache CXF 2 4 2 当我将数据库中的某个对象返回给用户时 我想排除一些属性 例如密码 我怎样才能做到这一点无需创建临时的班级 有这方面的注释吗 根据 tomasz nurkiewicz 评论我应该使用 XmlTrans
  • 如何使用 Jest 从 ElasticSearch 获取索引列表

    我正在尝试使用 Jest 检索索引列表 但我只得到 Stats statistics new Stats Builder build result client execute statistics 如何从结果中检索索引列表 除了统计之外

随机推荐

  • Mac os 安装homebrew

    Mac os 不会自带homebrew工具 而很多需要的工具需要用brew命令下载和安装 但是因为homebrew是国外网站 如果没有VPN 就无法下载 下面记录一下如何解决这个问题 1 国内安装的命令如下 bin zsh c curl f
  • centos或Ubuntu机器出现 pycharm.desktop文件出现 未信任的应用程序启动器的情况,怎么解决?

    桌面图标启动编辑 vi pycharm desktop usr bin env xdg open Desktop Entry Version 1 0 Type Application Name Pycharm 根据自己的安装位置灵活修改 I
  • centOs7 安装docker 镜像

    Step1 检查是否安装过 docker yum list installed grep docker 如果出现如下图所示的情况 说明安装过 如果重新安装需要先卸载 使用命令 yum y remove docker ce x86 64 卸载
  • TensorRT -- github

    此存储库包含 NVIDIA TensorRT 的开源软件 OSS 组件 它包括 TensorRT 插件和解析器 Caffe 和 ONNX 的源代码 以及演示 TensorRT 平台用法和功能的示例应用程序 这些开源软件组件是 TensorR
  • Python 预测股票价格,竟然这么简单

    作为一种技术手段 预测在金融 证券领域的应用非常广泛 尤其是对股票价格的预测 我们介绍一下获得股票数据的方法 并基于此对数据进行预处理 接着使用数据分析方法 建立基础特征 进一步构建预测模型 且基于新数据验证模型效果 拟使用 VAR 及LS
  • Oracle数据库精讲与疑难解析(第2版)

    Oracle数据库精讲与疑难解析 第2版 赵振平编著 ISBN978 7 121 20021 2 2013年4月出版 定价 148 00元 1100页 16开 编辑推荐 耗时3年 作者曾为本书辞职在家专心写作 754个实务 件件源自实际工作
  • 可视化Docker管理工具-DockerUI

    DockerUI 产品介绍 DockerUI是一个易用且轻量化的 Docker 管理工具 透过 Web 界面的操作 更方便对于 Docker 指令不熟悉的用户更快进入 Docker 的世界 DockerUI拥有易操作化化界面 不须记忆Doc
  • cmake(13):构建时设置预处理宏定义以及add_compile_definitions命令详解

    目录 1 说明 1 1 无参宏 1 2 有参宏 2 使用示例 3 命令解析 add compile definitions 命令 add definitions 命令 参考链接 1 说明 宏定义在程序设计中几乎是不可避免会用到的 在控制程序
  • linux上从github下载代码缓慢解决办法

    因为github服务器在国外 所以国内用户下载代码较慢 解决办法如下 修改hosts文件 crtl alt t打开终端 在终端中输入 gedit etc hosts 其中gedit是一个带图形界面的文本编辑器 操作如下 在hosts文件添加
  • 适合宝妈做的副业有哪些?

    选择成为一位全职妈妈 需要巨大的勇气和决心 一方面是带宝宝非常的辛苦 还要操持家务 另一方面是放弃赖以生存的工作 把自身的抗风险能力降到很低的水平线 我个人的观点是作为一个全职妈妈是很危险的 所以我比较赞成 作为全职妈妈的同时 尽可能用闲暇
  • html中浮动和定位(练习+知识点)

    目录 定位 1 什么是脱离文档流 2 position定位 2 1 static定位 2 2 relative定位 2 3 absolute定位 2 4 fixed定位 2 5 sticky定位 存在兼容性问题 层级属性z index 浮动
  • java ssh1_[置顶] java SSH1/SSH2远程连接实例

    看到网上有很多通过telnet实现远程登录的例子 就是找不到关于ssh远程登录的例子 ssh2的可能会有一些 但是目前开发项目遇到了比较底层的东西 这个需要通过ssh1连接的 于是就有了这个实例 今天要给大家带来的就是 java通过ssh1
  • 【数据结构】邻接矩阵法

    邻接矩阵 不带权 define MaxVertexNum 100 顶点的最大数目 typedef struct char Vex MaxVertexNum 顶点表 存放下标 复杂信息 int Edge MaxVertexNum MaxVer
  • 云计算虚拟化技术未来发展的趋势及应用(来源: 比特网)

    近两年 随着一些国际知名的虚拟化软件厂商在中国市场的大力开拓 虚拟化及云计算的概念越来越热 虚拟化软件市场大幅升温 同时也带动了一批国内的虚拟化软件企业迅速的发展起来 虚拟化技术从早期的企业应用 逐步过渡到公有云应用 应用范围越来越广泛 那
  • 刷题day22:逆波兰表达式求值

    题意描述 给你一个字符串数组 tokens 表示一个根据 逆波兰表示法 表示的算术表达式 请你计算该表达式 返回一个表示表达式值的整数 类似于二叉树 可以将运算符号看做二叉树的中间节点 遇到运算符之后计算前两个数字与该运算符的运算结果 C
  • 电阻的精度和温漂

    转载自 http blog sina com cn s blog 68b345970100jc2h html 电阻的精度和温漂 1 电阻温度系数 TCR 表示电阻当温度改变1度时 电阻值的相对变化 当温度每升高1 时 导体电阻的增加值与原来
  • python 字符串去除 等等转义空格换行字符

    python去除html特殊转义字符 下面这些是一些我在网上找的一些 好像都不管用 网络上面的一些方法好像都不管用 比如 str text replace str text replace u xa0 等等一些 我使用的时候好像都不管用 下
  • 匿名内部类方式实现线程创建的三种方式

    小demo package demo04 author wh date 2021年08月30日15 57 匿名内部类方式实现线程创建的三种方式 public class demo02 public static void main Stri
  • 企业级springboot项目架构模板V4.0,开箱即用

    此次 4 0 更新点 1 添加线程池的使用 2 Springboot版本更新2 7 0 解决部分冲突的依赖 3 所有表结构去除 ID 字段 不在使用ID作为主键 主键直接使用算法生成 4 解决过滤器 引起Druid监控无法访问的问题 5 F
  • 3.4 流式操作

    1 简介 1 概念 Stream是数据渠道 用于操作数据源所生成的元素序列 它可以实现对集合的复杂操作 例如过滤 排序和映射等 集合是一种静态的数据结构 存储在内存中 而Stream是通过CPU来实现计算的 并不会存储数据 Stream不会