Java 8 Stream API 详解

目录

引言

一、Stream 简介

1.1 什么是 Stream?

1.2 Stream 与集合的区别

1.3 Stream 的操作分类

二、Stream 的创建

2.1 从集合创建

2.2 从数组创建

2.3 使用 Stream.of 创建         

2.4 使用 Stream.generate 或 Stream.iterate 创建

三、Stream 的常用操作

3.1 中间操作

3.1.1 filter:过滤

3.1.2 map:映射

3.1.3 sorted:排序

3.1.4 distinct:去重

3.1.5 limit 和 skip:限制和跳过

3.2 终端操作

3.2.1 forEach:遍历

3.2.2 collect:收集

3.2.3 reduce:归约

3.2.4 count:计数

3.2.5 anyMatch、allMatch、noneMatch:匹配

四、并行流

五、总结


引言

Java 8 引入了 Stream API,它提供了一种高效且声明式的方式来处理集合数据。Stream API 的核心思想是将数据的操作分为中间操作终端操作,并通过流水线(Pipeline)的方式进行处理。Stream API 不仅使代码更加简洁易读,还能充分利用多核处理器的优势,提升数据处理性能。


一、Stream 简介

1.1 什么是 Stream?

Stream 是 Java 8 中处理集合数据的抽象工具。它并不是数据结构,而是一种对数据源(如集合、数组等)进行高效聚合操作的工具。Stream 的特点包括:

  • 声明式编程:通过链式调用方法描述数据处理逻辑。

  • 惰性求值:中间操作不会立即执行,只有在终端操作触发时才会执行。

  • 并行处理:可以轻松实现并行操作,充分利用多核 CPU。

1.2 Stream 与集合的区别

  • 集合:存储和操作数据的容器,关注数据的存储和访问。

  • Stream:对数据进行计算和处理的工具,关注数据的计算和转换。

1.3 Stream 的操作分类

Stream 的操作分为两类:

  1. 中间操作(Intermediate Operations):返回一个新的 Stream,可以链式调用。例如 filtermapsorted 等。

  2. 终端操作(Terminal Operations):触发 Stream 的执行并返回结果。例如 forEachcollectreduce 等。


二、Stream 的创建

Stream 可以从多种数据源创建,例如集合、数组、I/O 资源等。

2.1 从集合创建

List<String> list = Arrays.asList("Java", "Python", "C++");
Stream<String> stream = list.stream(); // 创建顺序流
Stream<String> parallelStream = list.parallelStream(); // 创建并行流

2.2 从数组创建

String[] array = {"Java", "Python", "C++"};
Stream<String> stream = Arrays.stream(array);

2.3 使用 Stream.of 创建         

Stream<String> stream = Stream.of("Java", "Python", "C++");

2.4 使用 Stream.generate 或 Stream.iterate 创建

// 生成无限流
Stream<String> infiniteStream = Stream.generate(() -> "Hello");

// 生成有限流
Stream<Integer> finiteStream = Stream.iterate(0, n -> n + 1).limit(10);

三、Stream 的常用操作

3.1 中间操作

3.1.1 filter:过滤

根据条件过滤元素。

List<String> languages = Arrays.asList("Java", "Python", "C++", "JavaScript");
List<String> result = languages.stream()
                               .filter(s -> s.startsWith("J"))
                               .collect(Collectors.toList());
System.out.println(result); // 输出 [Java, JavaScript]
3.1.2 map:映射

将元素转换为另一种形式。

List<String> languages = Arrays.asList("Java", "Python", "C++");
List<Integer> lengths = languages.stream()
                                 .map(String::length)
                                 .collect(Collectors.toList());
System.out.println(lengths); // 输出 [4, 6, 3]
3.1.3 sorted:排序

对元素进行排序。

List<String> languages = Arrays.asList("Java", "Python", "C++");
List<String> sortedLanguages = languages.stream()
                                       .sorted()
                                       .collect(Collectors.toList());
System.out.println(sortedLanguages); // 输出 [C++, Java, Python]
3.1.4 distinct:去重

去除重复元素。

List<String> languages = Arrays.asList("Java", "Python", "Java", "C++");
List<String> uniqueLanguages = languages.stream()
                                       .distinct()
                                       .collect(Collectors.toList());
System.out.println(uniqueLanguages); // 输出 [Java, Python, C++]
3.1.5 limit 和 skip:限制和跳过
  • limit(n):保留前 n 个元素。

  • skip(n):跳过前 n 个元素。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = numbers.stream()
                              .limit(3)
                              .skip(1)
                              .collect(Collectors.toList());
System.out.println(result); // 输出 [2, 3]

3.2 终端操作

3.2.1 forEach:遍历

对每个元素执行操作。

List<String> languages = Arrays.asList("Java", "Python", "C++");
languages.stream().forEach(System.out::println);
3.2.2 collect:收集

将 Stream 转换为集合或其他数据结构。

List<String> languages = Arrays.asList("Java", "Python", "C++");
Set<String> languageSet = languages.stream()
                                   .collect(Collectors.toSet());
System.out.println(languageSet); // 输出 [Java, Python, C++]
3.2.3 reduce:归约

将 Stream 中的元素组合起来,得到一个值。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
                 .reduce(0, Integer::sum);
System.out.println(sum); // 输出 15
3.2.4 count:计数

返回 Stream 中元素的个数。

List<String> languages = Arrays.asList("Java", "Python", "C++");
long count = languages.stream().count();
System.out.println(count); // 输出 3
3.2.5 anyMatchallMatchnoneMatch:匹配
  • anyMatch:任意一个元素满足条件。

  • allMatch:所有元素都满足条件。

  • noneMatch:没有元素满足条件。

List<String> languages = Arrays.asList("Java", "Python", "C++");
boolean anyMatch = languages.stream().anyMatch(s -> s.startsWith("J"));
boolean allMatch = languages.stream().allMatch(s -> s.length() > 3);
boolean noneMatch = languages.stream().noneMatch(s -> s.isEmpty());
System.out.println(anyMatch); // 输出 true
System.out.println(allMatch); // 输出 false
System.out.println(noneMatch); // 输出 true

四、并行流

Stream API 支持并行处理,只需将 stream() 替换为 parallelStream() 即可。

List<String> languages = Arrays.asList("Java", "Python", "C++");
long count = languages.parallelStream()
                     .filter(s -> s.startsWith("J"))
                     .count();
System.out.println(count); // 输出 1

五、案例

User实体类

public class User {
    private int id;
    private String userName;
    private int age;
    //get、set、有参/无参构造器、toString
 }

Stream算法题

import java.util.Arrays;
 import java.util.List;
 /*
 * 题目:请按照给出数据,找出同时满足以下条件的用户
 *       也即以下条件:
 *          1、全部满足偶数ID
 *          2、年龄大于24
 *          3、用户名转为大写
 *          4、用户名字母倒排序
 *          5、只输出一个用户名字 limit
 **/
 public class StreamDemo {
    public static void main(String[] args) {
        User u1 = new User(11, "a", 23);
        User u2 = new User(12, "b", 24);
        User u3 = new User(13, "c", 22);
        User u4 = new User(14, "d", 28);
        User u5 = new User(16, "e", 26);
        List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
        /*
         * 1. 首先我们需要将 list 转化为stream流
         * 2. 然后将用户过滤出来,这里用到一个函数式接口Predicate<? super T>,我们可
以使用lambda表达式简化
         * 3. 这里面传递的参数,就是Stream流的泛型类型,也就是User,所以,这里可以直接
返回用户id为偶数的用户信息;
         * 4. 通过forEach进行遍历,直接简化输出 System.out::println ,等价于 
System.out.println(u);
         **/
        //list.stream().filter(u -> {return 
//u.getId()%2==0;}).forEach(System.out::println);
        //list.stream().filter(u -> {return u.getId()%2==0;})
            //.filter(u -> {return 
//u.getAge()>24;}).forEach(System.out::println);
        //sorted()  自然排序,正排序 D->E
        list.stream()
                .filter(u -> {return u.getId()%2==0;})
                .filter(u -> {return u.getAge()>24;})
                .map(u -> {return u.getUserName().toUpperCase();})
              //.sorted() //默认正排序  自己用 compareTo 比较
                .sorted((o1,o2)->{return o2.compareTo(o1);})
                .limit(1)
                .forEach(System.out::println);
        /*
            map解释
            List<Integer> list2 = Arrays.asList(1,2,3);
            list2 = list2.stream().map(x -> {return 
            x*2;}).collect(Collectors.toList());
             for (Integer element : list2) {
                 System.out.println(element);
             }
         */
     }
 }


六、总结

Stream API 是 Java 8 中非常强大的工具,它通过声明式的方式简化了集合数据的处理。通过掌握 Stream 的创建、中间操作和终端操作,你可以写出更简洁、高效的代码。以下是本文的核心要点:

  1. Stream 的创建:可以从集合、数组、I/O 资源等创建 Stream。

  2. 中间操作:如 filtermapsorted 等,用于对数据进行处理和转换。

  3. 终端操作:如 forEachcollectreduce 等,用于触发计算并返回结果。

  4. 并行流:通过 parallelStream() 实现并行处理,提升性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/982744.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu20.04本地配置IsaacLab 4.2.0的G1训练环境(一)

Ubuntu20.04本地配置IsaacLab的G1训练环境&#xff08;一&#xff09; 配置Omniverse环境配置IsaacSim配置IsaacLab 写在前面&#xff0c;如果Ubuntu剩余空间低于60G&#xff0c;则空间不足&#xff0c;除非你不需要资产包。但资产包中却包含了G1模型、Go2模型等机器人模型和代…

从厨电模范到数字先锋,看永洪科技如何助力方太集团开启数字新征程

在数字化洪流席卷全球的宏大背景下&#xff0c;企业转型升级的紧迫性与重要性日益凸显&#xff0c;成为驱动行业进步的关键引擎。在这一波澜壮阔的转型浪潮中&#xff0c;方太集团——厨电领域的璀璨明珠&#xff0c;以其前瞻性的战略视野和不懈的创新精神&#xff0c;携手数据…

蓝桥杯4T平台(串口打印电压值)

知识点&#xff1a;串口(单片机发送数据)按键ADC 题目 配置 代码 adc.c uint16_t getadc2(void) {uint16_t adc0;HAL_ADC_Start(&hadc2);adcHAL_ADC_GetValue(&hadc2);return adc; } adc.h uint16_t getadc2(void); main.c #include "lcd.h" #include…

[Computer Vision]实验七:图像检索

目录 一、实验内容 二、实验过程 2.1 准备数据集 2.2 SIFT特征提取 2.3 学习“视觉词典”&#xff08;vision vocabulary&#xff09; 2.4 建立图像索引并保存到数据库中 2.5 用一幅图像查询 三、实验小结 一、实验内容 实现基于颜色直方图、bag of word等方法的以图搜…

利用 ArcGIS Pro 快速统计省域各市道路长度的实操指南

在地理信息分析与处理的工作中&#xff0c;ArcGIS Pro 是一款功能强大的 GIS 软件&#xff0c;它能够帮助我们高效地完成各种复杂的空间数据分析任务。 现在&#xff0c;就让我们一起深入学习如何借助 ArcGIS Pro 来统计省下面各市的道路长度&#xff0c;这一技能在城市规划、…

关于后端接口的返回值问题

1、后端接口中&#xff0c;get请求能返回给前端一个整数么&#xff1f; 问题说明&#xff1a; 解释&#xff1a; 在 Spring MVC 项目中&#xff0c;GET 请求的后端接口可以返回一个整数给前端。因为我们在controller层中&#xff0c;设置了RestController注解&#xff0c;这表明…

React Native 实现滑一点点内容区块指示器也滑一点点

效果图如上&#xff0c;内容滑一点点&#xff0c;指示器也按比例话一点点&#xff0c;列表宽度跟数据有关。 实现思路如下&#xff1a; 1.监听列表滑动事件&#xff0c;获取列表横向滑动距离&#xff0c;假设为A&#xff1b; 2.获取列表的宽度&#xff0c;及列表可滑动的宽度…

Cursor + IDEA 双开极速交互

相信很多开发者朋友应该和我一样吧&#xff0c;都是Cursor和IDEA双开的开发模式:在Cursor中快速编写和生成代码&#xff0c;然后在IDEA中进行调试和优化 在这个双开模式的开发过程中&#xff0c;我就遇到一个说大不大说小不小的问题&#xff1a; 得在两个编辑器之间来回切换查…

JS一些小知识点

一、|| 运算符 plain this.ctx.body { type: type || 0, // ||在此处用法用于默认值填充&#xff0c;判断是否传参或该值是否存在&#xff0c;如果不存在就使用||后买你的值作为默认值 code: code || 0, msg: msg || SUCCESS, data: data || {}, ...others }; 二、trim() 方…

【孟德尔随机化】PhenoScanner不能用的,替代方法

https://ldlink.nih.gov/?tabldtrait 目前PhenoScanner数据库限制使用&#xff0c;可选择LDlink数据库替代。 可以在网页下载变异数据 还有就是library(gwasrapidd)包提取 # remotes::install_github("ramiromagno/gwasrapidd") library(gwasrapidd)# 官方文档写单…

ALG(Alloy+Loki+Grafana)轻量级日志系统

ALG(AlloyLokiGrafana)轻量级日志系统 前提要求 GrafanaMinioNginxPrometheus Grafana日志收集系统旧版是PLG(ProtailLokiGrafana), Protail收集日志, Loki存储, Grafana展示, 后续的Protail不维护了, Grafana推出了Alloy代替Pritial, 除了收集日志外, 还集成管理Prometheus各种…

捣鼓180天,我写了一个相册小程序

&#x1f64b;为什么要做土著相册这样一个产品&#xff1f; ➡️在高压工作之余&#xff0c;我喜欢浏览B站上的熊猫幼崽视频来放松心情。有天在家族群里看到了大嫂分享的侄女卖萌照片&#xff0c;同样感到非常解压。于是开始翻阅过去的聊天记录&#xff0c;却发现部分图片和视…

JDK ZOOKEEPER KAFKA安装

JDK17下载安装 mkdir -p /usr/local/develop cd /usr/local/develop 将下载的包上传服务器指定路径 解压文件 tar -zxvf jdk-17.0.14_linux-x64_bin.tar.gz -C /usr/local/develop/ 修改文件夹名 mv /usr/local/develop/jdk-17.0.14 /usr/local/develop/java17 配置环境变量…

5c/c++内存管理

1. C/C内存分布 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] { 1, 2, 3, 4 };char char2[] "abcd";const char* pChar3 "abcd";int* ptr1 (int*)malloc(sizeof(int) * 4);i…

Tomcat-web服务器介绍以及安装部署

一、Tomcat简介 Tomcat是Apache软件基金会&#xff08;Apache Software Foundation&#xff09;的Jakarta 项目中的一个核心项目&#xff0c;由Apache、Sun和其他一些公司及个人共同开发而成。 Tomcat服务器是一个免费的开放源代码的Web应用服务器&#xff0c;属于轻量级应用…

国产编辑器EverEdit - 超多样式设置

1 设置-编辑-样式 1.1 设置说明 1.1.1 折叠样式 默认为箭头&#xff0c;折叠样式选项如下&#xff1a; 箭头&#xff1a; 矩形和线条 五边形 圆形图标 1.1.2 光标样式 光标用于指示当前用户输入位置&#xff0c;光标样式选项如下&#xff1a; 默认 纤细 字宽 …

【DeepSeek】5分钟快速实现本地化部署教程

一、快捷部署 &#xff08;1&#xff09;下载ds大模型安装助手&#xff0c;下载后直接点击快速安装即可。 https://file-cdn-deepseek.fanqiesoft.cn/deepseek/deepseek_28348_st.exe &#xff08;2&#xff09;打开软件&#xff0c;点击立即激活 &#xff08;3&#xff09;选…

2025系统架构师(一考就过):(2016-2017)案例+论文历年真题及解析系列二

24、管道-过滤器风格 和 数据仓库风格 对比(2016真题) 比较因素管道-过滤器风格数据仓储风格交互方式顺序结构或有限的循环结构星型数据结构数据流文件或模型控制结构数据流驱动业务功能驱动扩展方法接口适配模型适配25、用例及其关系、类及其关系(2016真题) 用例是对系统…

Artec Leo+Ray II 三维扫描仪成功为VR展数字化30吨重设备-沪敖3D

挑战&#xff1a;在贸易展上展示重达30吨的机械设备&#xff0c;同时克服设备搬运和展示的难题&#xff0c;减轻物流负担。。 解决方案&#xff1a;Artec Leo、Artec Ray II、Artec Studio、Blender、Unity、Microsoft HoloLens、HTC VIVE PRO 效果&#xff1a;在虚拟展厅中&am…

Flink深入浅出之01:应用场景、基本架构、部署模式

Flink 1️⃣ 一 、知识要点 &#x1f4d6; 1. Flink简介 Apache Flink — Stateful Computations over Data StreamsApache Flink 是一个分布式大数据处理引擎&#xff0c;可对有界数据流和无界数据流进行有状态的计算。Flink 能在所有常见集群环境中运行&#xff0c;并能以…