【集合】Java 8 - Stream API 17种常用操作与案例详解

文章目录

  • Java8 Stream API 17种常用操作与案例详解
    • 1. collect():将流中的元素收集到集合中
    • 2. filter():根据条件过滤流中的元素
    • 3. map():元素映射为另一个值
    • 4. forEach():对流中的元素执行操作
    • 5. flatMap():将流中的元素展开成一个流
    • 6. reduce():累积操作
    • 7. distinct():去重
    • 8. sorted():排序
    • 9. limit():截断流
    • 10. skip():跳过前 n 个元素
    • 11. anyMatch() / allMatch() / noneMatch():条件匹配
    • 12. findFirst() 和 findAny()
    • 13. max() / min():获取最大值或最小值
    • 14. peek():调试流中的元素
    • 15. count():统计流中的元素个数
    • 16. groupBy():将流中的元素按照指定的条件分组
    • 17. partitioningBy():将流中的元素按照指定的条件分成两个部分。
  • 总结补充

Java8 Stream API 17种常用操作与案例详解

在 Java 8 中,Stream API 提供了一种高效、简洁的数据处理方式,特别适合对集合、数组等数据源进行操作。Stream 通过函数式编程风格,支持链式调用,避免了传统 for 循环中复杂的代码逻辑。本文将详细介绍 17 种常用 Stream 操作方法,并通过示例代码帮助大家理解如何应用于实际开发中。


1. collect():将流中的元素收集到集合中

collect() 方法用于将流中的数据收集到集合、映射等数据结构中,非常常见。

示例

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");// 收集名字长度大于 3 的元素到 List 集合
List<String> filteredNames = names.stream().filter(name -> name.length() > 3).collect(Collectors.toList());
System.out.println(filteredNames); // Output: [Alice, Charlie, David]

理解要点
collect() 是终止操作,它将流中的元素重新汇总到新的集合中。这里的 Collectors.toList() 是一种常见用法,用于收集元素到 List 集合中。


2. filter():根据条件过滤流中的元素

filter() 用于筛选出满足特定条件的元素,它返回一个新的流,流中的元素都满足过滤条件。

示例

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 过滤出偶数
List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());
System.out.println(evenNumbers); // Output: [2, 4]

理解要点
这里 n -> n % 2 == 0 是一个 Lambda 表达式,表示只保留能被 2 整除的元素。filter() 不会修改原数据,而是返回一个新的流。


3. map():元素映射为另一个值

map() 会对流中的每个元素执行操作,并将结果映射成一个新的流。

示例

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 转换为大写
List<String> upperCaseNames = names.stream().map(String::toUpperCase).collect(Collectors.toList());
System.out.println(upperCaseNames); // Output: [ALICE, BOB, CHARLIE]

理解要点

  • map() 接受一个函数作为参数,将流中的每个元素转换为新形式。
  • String::toUpperCase 是方法引用,等同于 name -> name.toUpperCase()

4. forEach():对流中的元素执行操作

forEach() 是终止操作,用于遍历流中的元素并执行指定的操作。

示例

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 输出每个元素
numbers.stream().forEach(System.out::println);
// Output: 1 2 3 4 5

理解要点

  • System.out::println 是方法引用,等同于 n -> System.out.println(n)
  • forEach() 不返回新流,只执行操作。

5. flatMap():将流中的元素展开成一个流

flatMap() 用于处理嵌套集合(比如 List),它将每个元素的流展开,并合并成一个新的流。

示例

List<List<Integer>> listOfLists = Arrays.asList(Arrays.asList(1, 2, 3), Arrays.asList(4, 5), Arrays.asList(6, 7, 8)
);// 合并多个列表为一个流
List<Integer> mergedList = listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
System.out.println(mergedList); // Output: [1, 2, 3, 4, 5, 6, 7, 8]

理解要点

  • flatMap() 的作用是 “摊平” 元素,比如将多个小集合合并成一个大集合。
  • 这里 List::stream 表示将每个子集合转换为流。

6. reduce():累积操作

reduce() 用于将流中的元素进行聚合操作,例如求和、求最大值等。

示例

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 求和
int sum = numbers.stream().reduce(0, Integer::sum);
System.out.println(sum); // Output: 15

理解要点

  • reduce 需要一个初始值(这里是 0),一个二元操作(Integer::sum)。
  • 操作会从初始值开始累加流中的元素。

7. distinct():去重

distinct() 方法用于去掉流中的重复元素,最终返回一个去重后的流。

示例

List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 4);// 去重
List<Integer> distinctNumbers = numbers.stream().distinct().collect(Collectors.toList());
System.out.println(distinctNumbers); // Output: [1, 2, 3, 4]

理解要点
distinct() 会基于元素的 equals()hashCode() 方法判断是否重复。


8. sorted():排序

sorted() 可以对流中的元素进行排序,支持自然排序和自定义排序。

示例

List<Integer> numbers = Arrays.asList(5, 3, 1, 4, 2);// 升序排序
List<Integer> sortedNumbers = numbers.stream().sorted()	//Comparator.comparing().collect(Collectors.toList());
System.out.println(sortedNumbers); // Output: [1, 2, 3, 4, 5]

理解要点

  • 默认情况下,sorted() 使用自然排序(升序)。
  • 如果需要自定义排序,可以传入比较器。

9. limit():截断流

limit() 用于获取流中的前 n 个元素。

示例

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7);// 只获取前 3 个元素
List<Integer> limitedNumbers = numbers.stream().limit(3).collect(Collectors.toList());
System.out.println(limitedNumbers); // Output: [1, 2, 3]

实际场景
例如分页功能中,可以结合 skip() 实现数据的分页查询。


10. skip():跳过前 n 个元素

skip() 用于跳过流中的前 n 个元素,返回剩余元素的流。

示例

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7);// 跳过前 4 个元素
List<Integer> skippedNumbers = numbers.stream().skip(4).collect(Collectors.toList());
System.out.println(skippedNumbers); // Output: [5, 6, 7]

结合 limit()

// 获取第 4 到第 6 个元素
List<Integer> subList = numbers.stream().skip(3).limit(3).collect(Collectors.toList());
System.out.println(subList); // Output: [4, 5, 6]

实际场景
跳过已处理数据,优化批量处理的效率。


11. anyMatch() / allMatch() / noneMatch():条件匹配

这三个方法用于判断流中的元素是否符合条件:

  • anyMatch():是否有任意一个元素满足条件。
  • allMatch():所有元素都满足条件。
  • noneMatch():没有任何元素满足条件。

示例

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 是否存在大于 4 的元素
boolean anyMatch = numbers.stream().anyMatch(n -> n > 4);
System.out.println(anyMatch); // Output: true// 是否所有元素都小于 6
boolean allMatch = numbers.stream().allMatch(n -> n < 6);
System.out.println(allMatch); // Output: true// 是否没有大于 5 的元素
boolean noneMatch = numbers.stream().noneMatch(n -> n > 5);
System.out.println(noneMatch); // Output: true

实际场景

  • 数据校验,例如用户输入是否符合条件。
  • 筛选判断,例如是否存在符合条件的订单。

12. findFirst() 和 findAny()

  • findFirst():返回流中的第一个元素,通常在顺序流中使用。
  • findAny():返回流中的任意一个元素,适合并行流操作,效率更高。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 使用 findFirst 方法查找第一个元素
Optional<Integer> first = numbers.stream().findFirst();// 使用 findAny 方法查找任意一个元素
Optional<Integer> any = numbers.stream().findAny();// 输出结果
System.out.println("First: " + first.orElse(null)); // Output: 1
System.out.println("Any: " + any.orElse(null));     // Output: 1 或其他任意元素

特别说明:

  • 顺序流 中,findAny() 的行为与 findFirst() 相似,通常会返回第一个元素。
  • 并行流 中,findAny() 可能会返回流中任意位置的元素,以提高性能。

13. max() / min():获取最大值或最小值

max()min() 用于根据比较器找出流中的最大或最小元素。

示例

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);// 获取最大值
Optional<Integer> max = numbers.stream().max(Integer::compareTo);
System.out.println(max.get()); // Output: 5// 获取最小值
Optional<Integer> min = numbers.stream().min(Integer::compareTo);
System.out.println(min.get()); // Output: 1

理解要点

  • max()min() 返回 Optional 对象,需使用 .get() 获取值。
  • 可以使用自定义比较器实现复杂比较逻辑。

14. peek():调试流中的元素

peek() 用于对流中的每个元素执行操作,但不会中断流的操作。适合用来调试。

示例

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 打印调试信息
List<String> filteredNames = names.stream().peek(name -> System.out.println("Before filter: " + name)).filter(name -> name.length() > 3).peek(name -> System.out.println("After filter: " + name)).collect(Collectors.toList());
System.out.println(filteredNames);

输出

Before filter: Alice  
After filter: Alice  
Before filter: Bob  
Before filter: Charlie  
After filter: Charlie  
[Alice, Charlie]

理解要点
peek() 通常用于调试,打印中间状态,帮助排查问题。


15. count():统计流中的元素个数

count() 是一个终止操作,用于统计流中元素的个数。

示例

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");// 统计名字长度大于 3 的元素个数
long count = names.stream().filter(name -> name.length() > 3).count();
System.out.println(count); // Output: 2

实际场景
数据统计,比如计算符合条件的记录数量。


16. groupBy():将流中的元素按照指定的条件分组

sorted(Comparator) 支持根据自定义逻辑对流中的元素进行排序。

示例

 List<String> words = Arrays.asList("dog", "cat", "elephant", "rat", "ant");// 按字符串长度分组
Map<Integer, List<String>> groupedByLength = words.stream().collect(Collectors.groupingBy(String::length));System.out.println(groupedByLength); 
// 输出: {3=[dog, cat, rat, ant], 8=[elephant]}

理解要点

  • Collectors.groupingBy() 返回值作为键。

17. partitioningBy():将流中的元素按照指定的条件分成两个部分。

sorted(Comparator) 支持根据自定义逻辑对流中的元素进行排序。

示例

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);// 根据是否为偶数进行分区
Map<Boolean, List<Integer>> partitionedByEvenOdd = numbers.stream().collect(Collectors.partitioningBy(num -> num % 2 == 0));System.out.println(partitionedByEvenOdd); 
// 输出: {false=[1, 3, 5, 7, 9], true=[2, 4, 6, 8]}

分区结合统计信息:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);// 分区后统计每组的元素数量
Map<Boolean, Long> countByEvenOdd = numbers.stream()
.collect(Collectors.partitioningBy(num -> num % 2 == 0, Collectors.counting()));System.out.println(countByEvenOdd); 
// 输出: {false=5, true=4}

总结补充

通过以上 17 个常用操作,我们可以看到 Stream API 在数据处理方面提供了强大的功能。总结一些常见的使用场景:

  1. 数据过滤与筛选filter()distinct()limit()
  2. 数据转换与聚合map()flatMap()reduce()
  3. 数据统计与校验count()allMatch()anyMatch()
  4. 调试与排序peek()sorted()max()min()

合理使用 Stream API,能够让代码更加简洁、可读性更强,同时提高开发效率。希望这篇文章对大家有帮助!!👍★(疯狂暗示)


博客主页: 总是学不会.

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java图片拼接

最近遇到一个挺离谱的功能&#xff0c;某个表单只让上传一张图&#xff0c;多图上传会使导出失败。跟开发沟通后表示&#xff0c;这个问题处理不了。我... 遂自己思考&#xff0c;能否以曲线救国的方式拯救一下&#xff0c;即不伤及代码之根本&#xff0c;又能解决燃眉之急。灵…

webGL硬核知识:图形渲染管渲染流程,各个阶段对应的API调用方式

一、图形渲染管线基础流程概述 WebGL 的图形渲染管线大致可分为以下几个主要阶段&#xff0c;每个阶段都有其特定的任务&#xff0c;协同工作将 3D 场景中的物体最终转换为屏幕上呈现的 2D 图像&#xff1a; 顶点处理&#xff08;Vertex Processing&#xff09;阶段&#xff1…

大数据面试题--企业面试真题

大数据面试题--企业面试真题 PlanHub 点击访问获取&#xff1a; 大数据面试体系专栏_酷兜科技​www.kudoumh.top/hlwai/85.html 点击访问获取&#xff1a; 大数据面试体系专栏_酷兜科技​www.kudoumh.top/hlwai/85.html 大数据面试题汇总 HDFS 1、 HDFS 读写流程。 2、HDF…

lambda初探(一)

发生捕获时&#xff0c;拿到x,y的值 退出lambda表达式后&#xff0c;foo外层的值不变化。foo内部的x&#xff0c;值是持续的&#xff0c;像static。即使退出foo函数后&#xff0c;值的状态依然保持。 外层x的值变化&#xff0c;并不影响foo内部。 foo运行了两次&#xff0c;内…

【D3.js in Action 3 精译_046】DIY 实战:在 Observable 平台利用饼图布局函数实现 D3 多个环形图的绘制

当前内容所在位置&#xff1a; 第五章 饼图布局与堆叠布局 ✔️ 5.1 饼图和环形图的创建 ✔️ 5.1.1 准备阶段&#xff08;一&#xff09;5.1.2 饼图布局生成器&#xff08;二&#xff09;5.1.3 圆弧的绘制&#xff08;三&#xff09;5.1.4 数据标签的添加&#xff08;四&#…

基于Spring Boot的智慧农业专家远程指导系统

一、系统背景与意义 随着科技的不断进步&#xff0c;农业领域也在积极寻求创新与发展。然而&#xff0c;传统农业生产中农民往往依靠经验进行种植和养殖&#xff0c;缺乏科学的指导和技术支持。同时&#xff0c;农业专家资源有限&#xff0c;难以覆盖广大的农村地区&#xff0…

【JavaEE初阶】线程 和 thread

本节⽬标 认识多线程 掌握多线程程序的编写 掌握多线程的状态 一. 认识线程&#xff08;Thread&#xff09; 1概念 1) 线程是什么 ⼀个线程就是⼀个 "执⾏流". 每个线程之间都可以按照顺序执⾏⾃⼰的代码. 多个线程之间 "同时" 执⾏着多份代码. 还…

练习题 最小栈

最小栈 最小栈 class MinStack {private Stack<Integer> stack;private Stack<Integer> minstack;public MinStack() {stacknew Stack<>();minstacknew Stack<>();}public void push(int val) {stack.push(val);if(minstack.empty()){minstack.push(…

全志H618 Android12修改doucmentsui鼠标单击图片、文件夹选中区域

背景: 由于当前的文件管理器在我们的产品定义当中,某些界面有改动的需求,所以需要在Android12 rom中进行定制以符合当前产品定义。 需求: 在进入File文件管理器后,鼠标左击整个图片、整个文件夹可以选中该类型,进行操作,故代码分析以及客制化如下: 主要涉及的代码:…

堆【Lecode_HOT100】

文章目录 1.数组中的第&#xff2b;个最大元素No.2152.前K个高频元素347 1.数组中的第&#xff2b;个最大元素No.215 方法一&#xff1a;NlogN不能满足时间复杂度的要求 public int findKthLargest(int[] nums, int k) {Arrays.sort(nums);return nums[nums.length-k];}方法二&…

Android 搭建AIDL Client和Server端,双向通信

一、背景 使用AIDL,搭建Client和Server端,实现跨进程通讯,即两个应用之间可以相互通讯。这里列举AIDL实现的方式和需注意的细节&#xff0c;并附上源码。 二、实现方式 2.1 定义AIDL需要的接口,名字为xxx.aidl,Client和Server端 AIDL接口的包名和aidl文件必须一致&#xff0c…

HIPT论文阅读

题目《Scaling Vision Transformers to Gigapixel Images via Hierarchical Self-Supervised Learning》 论文地址&#xff1a;[2206.02647] Scaling Vision Transformers to Gigapixel Images via Hierarchical Self-Supervised Learning 项目地址&#xff1a;mahmoodlab/HI…

[ESP]从零开始的Arduino IDE安装与ESP环境配置教程

一、前言 最近也是在比赛方面比较忙&#xff0c;没有更多的时间和精力去更新长文章了。这几周都更倾向于环境搭建的教程&#xff0c;这类教程写起来确实方便&#xff0c;也不怎么费时间&#xff0c;一个下午基本可以搞定&#xff0c;哈哈&#xff0c;我保证不是在为自己想摆烂找…

投标心态:如何在“标海战术”中保持清醒的头脑?

在竞争激烈的市场环境下&#xff0c;“标海战术”——即大规模参与投标——已经成为许多企业争取市场份额的重要策略。然而&#xff0c;盲目追求投标数量可能导致资源浪费、团队疲劳以及战略目标的模糊化。在这种高强度的竞争模式中&#xff0c;如何保持清醒的头脑&#xff0c;…

wxWidgets使用wxStyledTextCtrl(Scintilla编辑器)的正确姿势

开发CuteMySQL/CuteSqlite开源客户端的时候&#xff0c;需要使用Scintilla编辑器&#xff0c;来高亮显示SQL语句&#xff0c;作为C/C领域最成熟稳定又小巧的开源编辑器&#xff0c;Scintilla提供了强大的功能&#xff0c;wxWidgets对Scintilla进行包装后的是控件类&#xff1a;…

【原生js案例】让你的移动页面实现自定义的上拉加载和下拉刷新

目前很多前端UI都是自带有上拉加载和下拉刷新功能,按照官网配置去实现即可,比如原生小程序,vantUI等UI框架,都替我们实现了内部功能。 那如何自己来实现一个上拉加载和下拉刷新的功能? 实现效果 不用浏览器的css滚动条,自定义实现滚动效果 自定义实现滚动,添加上拉加载…

批处理理解

初识批处理 如何批处理&#xff1a; 命名&#xff1a;.bat 方法&#xff1a;创建一个记事本文件&#xff0c;然后将其扩展改为.bat 批处理作用&#xff1a;自上而下成批处理每一条DOS命令&#xff0c;直到执行到最后一条。运行环境&#xff1a;当然是我们cmd了 回归我学过的…

APM32F411使用IIS外设驱动es8388实现自录自播

前言&#xff1a; 从零开始学习I2s外设&#xff0c;配置Es8288寄存器实现录音播放。本文章使用主控芯片是APM32F411系类。音频相关的概念比较多&#xff0c;就不再次做过多的介绍&#xff0c;本文章只是简单实现边录边播功能。APM系类兼容st的芯片&#xff0c;所以用st的hal库来…

OB删除1.5亿数据耗费2小时

目录 回顾&#xff1a;mysql是怎么删除数据的&#xff1f; 删除方案 代码实现 执行结果 结论 本篇是实际操作 批量处理数据以及线程池线程数设置 记录学习 背景&#xff1a;有一张用户标签表&#xff0c;存储数据量达4个亿&#xff0c;使用OceanBase存储&#xff0c;由于…

20241217使用M6000显卡在WIN10下跑whisper来识别中英文字幕

20241217使用M6000显卡在WIN10下跑whisper来识别中英文字幕 2024/12/17 17:21 缘起&#xff0c;最近需要识别法国电影《地下铁》的法语字幕&#xff0c;使用 字幕小工具V1.2【whisper套壳/GUI封装了】 无效。 那就是直接使用最原始的whisper来干了。 当你重装WIN10的时候&#…