JAVA Stream流

embedded/2024/10/18 16:51:13/

Stream流

是Java 8引入的一种处理数据的强大工具,它提供了一种声明式、高效且易于并行化的编程模型,用于对集合、数组或其他数据源中的元素进行各种计算和操作。Stream API的核心思想是将数据作为一系列元素的序列(流)进行处理,而不是直接操作数据本身。
值得注意的是,流(Stream)是一种基于支持一次性处理数据的数据源的元素序列,流只能使用一次。

以下是对Stream流的详细说明:

核心概念:

数据源(Source): Stream的起点,可以是集合、数组、I/O通道、生成器函数等,任何能够产生数据序列的源头都可以作为Stream的数据源。
中间操作(Intermediate Operations): 一系列惰性求值可链接的无状态操作,如filter(过滤)、map(映射)、sorted(排序)、limit(限制数量)、distinct(去重)等。这些操作不会立即执行,而是构建一个流水线式的操作链。中间操作返回一个新的Stream对象,原Stream保持不变。
终端操作(Terminal Operations): 一个Stream的生命周期以一个终端操作结束,如collect(收集到集合)、forEach(遍历消费)、count(计数)、anyMatch(是否满足条件)、reduce(归约)等。执行终端操作时,会触发中间操作链的执行,从而完成对数据的实际处理。终端操作的结果通常是具体的计算结果或影响(如更新数据库)。
懒加载(Lazy Evaluation): Stream的中间操作仅定义了如何处理数据,直到遇到终端操作时才开始实际遍历数据源并执行计算。这种延迟执行有助于优化性能,避免不必要的计算。
可并行化(Parallelization): Stream支持并行处理,通过调用parallel()方法可以将串行流转换为并行流,利用多核处理器的优势提高大规模数据处理的效率。并行流会自动划分任务,在多个线程上并行执行中间和终端操作。

主要特点:

声明式编程: 使用Stream API编写代码时,关注的是“做什么”而非“怎么做”。通过组合各种操作符(方法)来描述数据处理逻辑,代码更简洁、易于理解。
函数式风格: Stream API鼓励使用lambda表达式和方法引用来定义操作逻辑,符合函数式编程的范式,有利于写出简洁、无副作用的代码。
避免空指针异常: 对于可能为空的集合,Stream API提供了诸如Optional等工具类来优雅地处理空值情况,避免了因空指针引发的运行时异常。
易于优化: Stream的惰性求值和内部优化机制使得JVM和JDK能够在运行时根据具体硬件环境和数据特性进行优化,如减少迭代次数、缓存中间结果等。

典型用法示例:

java">List<String> words = Arrays.asList("apple", "banana", "cherry", "date");

例子1:

java">// 使用Stream API统计单词列表中长度大于5的单词数量
long count = words.stream()//数据源.filter(word -> word.length() > 5)//中间操作,这是一种lambda表达式的写法.count();//终端操作

例子2:

java">// 使用匿名内部类改写Stream API统计单词列表中长度大于5的单词数量
long count = words.stream().filter(new Predicate<String>() {//这是一种匿名内部类(老写法),等同于上面的lambda写法@Overridepublic boolean test(String word) {return word.length() > 5;}}).count();

例子3:

java">// 将单词列表转换为大写并连接成一个字符串
String result = words.stream()//数据源.map(String::toUpperCase)//中间操作(它是Java 8及以后版本引入的lambda表达式的一种简洁表示形式,Java中的方法引用(Method Reference)语法,看例子4).collect(Collectors.joining(", "));//终端操作

例子4:

java">// 将单词列表转换为大写并连接成一个字符串
String result = words.stream()//数据源.map(word -> word.toUpperCase())//中间操作,word是lambda表达式中的参数,word.toUpperCase()则是对参数应用String类的toUpperCase()方法,将其转换为大写。//方法引用String::toUpperCase直接指定了要使用的类(String)和方法名(toUpperCase).collect(Collectors.joining(", "));//终端操作

例子5:

java">// 并行计算单词列表的总长度
int totalLength = words.parallelStream()//数据源(这个是个并行流,下面会讲解,可以理解为将List中的所有String同时进行流处理).mapToInt(String::length)//中间操作.sum();//终端操作

获取流的常用方式(前三种常用)

1.通过集合获取流:可以使用集合类中的stream()方法或parallelStream()方法来获取流
2.通过数组获取流:可以使用Arrays类中的stream()方法来获取流。
3.通过Stream.of()方法获取流:可以使用Stream类中的of()方法来获取流。
4.通过Stream.iterate()方法获取流:可以使用Stream类中的iterate()方法来获取流
Stream<Integer> stream = Stream.iterate(0, n -> n + 2).limit(5); // 获取顺序流
5.通过Stream.generate()方法获取流:可以使用Stream类中的generate()方法来获取流
Stream<Double> stream = Stream.generate(Math::random).limit(5); // 获取顺序流
6.通过Files.lines()方法获取流:可以使用Files类中的lines()方法来获取流。
Stream<String> stream = Files.lines(Paths.get("file.txt")); // 获取顺序流

常用方法用法

Stream API中的中间操作是指对流进行某种变换或筛选,但并不立即执行操作,而是返回一个新的Stream对象供后续操作链继续构建。中间操作是惰性的,只有当遇到终端操作(如collect、forEach等)时才会触发整个流管道的执行,通常会有多个可链接的无状态操作,譬如在筛选后再映射
以下是常用的Stream中间操作:
1、过滤(Filtering): filter(Predicate<? super T> predicate) —— 根据给定的谓词(Predicate)筛选出符合条件的元素。返回一个新的Stream,其中包含原Stream中所有使谓词返回true的元素。
示例:

java">   List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);//筛选所有的偶数List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());

2、映射(Mapping): map(Function<? super T, ? extends R> mapper) —— 将每个元素应用给定的函数(Function),并返回一个新的Stream,其中包含应用函数结果的元素。
示例:

java">   List<String> words = Arrays.asList("hello", "world", "java");List<Integer> wordLengths = words.stream().map(String::length).collect(Collectors.toList());

3、扁平化(Flattening): flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) —— 类似于map,但允许将每个元素转换为一个Stream,然后将所有生成的Stream扁平化为一个单一的Stream。
示例:

java">   List<List<String>> nestedWords = Arrays.asList(Arrays.asList("hello", "world"),Arrays.asList("java", "stream"));List<String> flattenedWords = nestedWords.stream().flatMap(List::stream).collect(Collectors.toList());

4、排序(Sorting0): sorted() 或 sorted(Comparator<? super T> comparator) —— 对流中的元素进行自然排序(对于实现了Comparable接口的类型)或按照指定的比较器(Comparator)进行排序。返回一个新的已排序的Stream。
示例:

java">   List<String> words = Arrays.asList("banana", "apple", "cherry");List<String> sortedWords = words.stream().sorted().collect(Collectors.toList());

5、切片(Slicing): limit(long maxSize) 和 skip(long n) —— 分别限制返回的流最多包含多少个元素(前n个)和跳过前n个元素。这两个操作可以用于分页或取部分数据。
示例:

java">   List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);List<Integer> firstThreeNumbers = numbers.stream().limit(3).collect(Collectors.toList());List<Integer> remainingNumbers = numbers.stream().skip(3).collect(Collectors.toList());

6、去重(Deduplicating): distinct() —— 返回一个新的Stream,其中包含原Stream中唯一的元素,即去除重复项。
示例:

java">   List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5);List<Integer> uniqueNumbers = numbers.stream().distinct().collect(Collectors.toList());

没有给代码注释和结果,上边的例子已经很好的了解了,建议心写出对应的结果后建一个main函数复制代码进去跑一跑。
这些中间操作可以灵活组合,形成复杂的流处理管道,使得代码更加简洁、易于阅读和维护。中间操作的惰性执行特性有助于提高性能,尤其是在处理大量数据或进行并行计算时。


http://www.ppmy.cn/embedded/3990.html

相关文章

BOOT和UBOOT区别与联系

一、定义 1.1 Boot&#xff08;启动&#xff09; 在计算机和嵌入式系统的基本概念中&#xff0c;“boot”是指启动过程&#xff0c;这是一个系统从加电开始直至进入操作系统运行状态的过程。在嵌入式系统中&#xff0c;这个过程通常包括初始化硬件、加载并执行引导加载…

服务器数据恢复—xfs文件系统节点、目录项丢失的数据恢复案例

服务器数据恢复环境&#xff1a; EMC某型号存储&#xff0c;该存储内有一组由12块磁盘组建的raid5阵列&#xff0c;划分了两个lun。 服务器故障&#xff1a; 管理员为服务器重装操作系统后&#xff0c;发现服务器的磁盘分区发生改变&#xff0c;原来的sdc3分区丢失。由于该分区…

英特尔、联想等服务器曝出难以修复的漏洞

文章目录 前言一、漏洞潜伏六年,服务器供应链安全堪忧二、漏洞广泛存在但难以修复前言 近日,英特尔、联想等多个厂商销售的服务器硬件曝出一个难以修复的远程可利用漏洞。该漏洞属于供应链漏洞,源自一个被多家服务器厂商整合到产品中的开源软件包——Lighttpd。 Lighttpd是…

如何利用纯前端技术,实现一个网页版视频编辑器?

纯网页版视频编辑器 一、前言二、功能实现三、所需技术四、部分功能实现4.1 素材预设4.2 多轨道剪辑 一、前言 介绍&#xff1a;本篇文章打算利用纯前端的技术&#xff0c;来实现一个网页版的视频编辑器。为什么突然想做一个这么项目来呢&#xff0c;主要是最近一直在利用手机…

Android之启动优化

不在 Application 初始化非必要的第三方库&#xff0c;尽量在使用的时候初始化&#xff0c;例如地图平台、播放器框架等这些可以在使用的时候再初始化。 启动优化误区&#xff1a; 启动页 Activity 的窗口背景采用透明色&#xff0c;由此来掩盖启动时卡白屏时间较长的问题&am…

【御控物联】物联网数据传输数据格式

随着物联网技术的快速发展&#xff0c;越来越多的系统和设备被接入到了物联网管理中&#xff0c;数据交换与共享成为了一个重要的问题。不同的设备和系统之间存在着各种各样的通信协议和数据格式&#xff0c;这就给数据获取、交换和共享带来了很大的不便利。 MQTT 是机器对机器…

Spring Boot 实现定时任务

前言 在实际开发中,我们经常需要处理一些周期性或定时的任务,比如每天凌晨进行数据统计、报表生成,或者每隔一段时间清理缓存等。Spring Boot 集成了 Quartz 和 Spring 自带的 TaskScheduler 等多种定时任务框架,使得实现定时任务变得非常方便。本文将通过一个详细的示例,…

基于微信小程序投票评选系统的设计与实现(论文+源码)_kaic

摘 要 社会发展日新月异&#xff0c;用计算机应用实现数据管理功能已经算是很完善的了&#xff0c;但是随着移动互联网的到来&#xff0c;处理信息不再受制于地理位置的限制&#xff0c;处理信息及时高效&#xff0c;备受人们的喜爱。所以各大互联网厂商都瞄准移动互联网这个潮…