Java函数式编程【二】【Stream的装饰】【中间操作】【map映射器】【摊平映射器flatMap】
一、Java的Stream流式编程中的中间操作
Java的Stream流式编程中,中间操作是对数据流进行处理的一种方式,这些操作通常返回流对象本身,以便可以链接更多的操作。以下是一些常见的中间操作:
-
filter(Predicate predicate) - 用于通过设定的条件过滤出元素。
-
sorted() - 对元素进行排序。
-
distinct() - 去除重复的元素。
-
limit(long maxSize) - 获取指定数量的流元素。
-
skip(long n) - 跳过操作,跳过某些元素。
-
peek() - 查看操作。允许你在不影响流的主要处理逻辑的情况下,查看或使用流中的每个元素。这个方法可以用来进行一些调试或日志记录等操作。下面是一个示例:
peek例程
List<String> fruits = Arrays.asList("apple", "banana", "orange", "grape");
fruits.stream().filter(f -> f.length() > 5).peek(System.out::println).collect(Collectors.toList());
中间操作的示例代码:
List<String> items = Arrays.asList("apple", "banana", "orange", "kiwi");// Filtering
List<String> filteredItems = items.stream().filter(item -> item.startsWith("a")).collect(Collectors.toList());// Sorting
List<String> sortedItems = items.stream().sorted().collect(Collectors.toList());// Distinct
List<String> distinctItems = items.stream().distinct().collect(Collectors.toList());// Limiting
List<String> limitedItems = items.stream().limit(2).collect(Collectors.toList());// Skipping
List<String> skippedItems = items.stream().skip(1).collect(Collectors.toList());

函数式编程,在流管道中可以包含0个或n个中间操作,每个中间操作都返回一个新的流。
二、中间操作 映射器map()的用法
映射器map的方法签名(原型):
- map(Function<? super T, ? extends R> mapper) - 它的输入参数是一个类型为函数接口的映射器,可将流中的元素转换成其他类型的元素。映射器map()是把一个对象流变成另一种对象流。
另外三个与映射器map()类似的映射器,它们则可以把一个对象流转换为基本类型流。
- mapToInt(ToIntFunction<? super T> mapper) - 将元素映射为值的整型int流。
- mapToLong(ToLongFunction<? super T> mapper) - 将元素映射为值的长整型long流。
- mapToDouble(ToDoubleFunction<? super T> mapper) - 将元素映射为值的双精度浮点型double流。

用法一:将一种流映射成另一种流
把英文的小写转换为大写的代码片断:
// Mapping
List<String> items = Arrays.asList("apple", "banana", "orange", "grape");
List<String> mappedItems = items.stream().map(String::toUpperCase).collect(Collectors.toList());
下面是来看一个完整的示例。下图是这个流管道的详细分解说明图示:

这个示例完整的程序源码:
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class MapTest {public static void main(String[] args) {List<User> list = Arrays.asList(new User(2001, "Ricky"), new User(2002, "Alex"), new User(2003, "Bob"));list.forEach(System.out::println);List<String> newList = list.stream().map(User::getName).sorted().limit(2).collect(Collectors.toList());newList.forEach(System.out::println);}
}class User {private int id;private String name;public User(int id,String name) {this.id = id;this.name = name;}public String getName() {return name;}@Overridepublic String toString() {return "{User[ID:"+id+" 姓名:"+name+"]}";}
}
例程测试效果图:

映射器map示例: 实现功能:整数列表每个元素+3。分别用对象流和IntStream来实现。
使用的两个映射器的原型如下所示:
//本示例使用的map()方法的签名,其入口参数类型是Function函数,如下:
<Integer> Stream<Integer> java.util.stream.Stream.map(Function<? super Integer, ? extends Integer> mapper)
//本示例使用的mapToInt()方法的签名,其入口参数类型是ToIntFunction函数,如下
IntStream java.util.stream.Stream.mapToInt(ToIntFunction<? super Integer> mapper)
这两个流,尽管入口参数的函数类型不一样,但完全可以用同一个Lambda表达式来代替函数接口的实例作为传入参数。
但后续的处理方式有些不同:映射器map()返回的是对象流,可用收集器collect(Collectors.toList())来收集结果。映射器mapToInt()返回的是IntStream(整型流),不能使用用收集器。因为收集器收集的元素必须是对象,IntStream中的元素是基本数据类型,所以收集器不支持。
List<Integer> intList = Arrays.asList(1, 3, 5, 7, 9, 11);//对象流的实现方式List<Integer> intListNew = intList.stream().map(x -> x + 3).collect(Collectors.toList());System.out.println("每个元素+3:" + intListNew);//用IntStream来实现System.out.println("打印IntStream:");IntStream intStream = intList.stream().mapToInt(x -> x + 3);intStream.forEach(System.out::println);
测试效果图:

mapToDouble基本数据类型流例程
基本数据类型流,比如DoubleStream(双精度浮点型流)不能使用收集器收集结果,但也有很多的终止操作,比如求最大最小值、求和、求平均值:
public static void main(String[] args) {List<Double> doubleList = Arrays.asList(1.0, 22.0, 3.0, 4.0, 32.0);double average = doubleList.stream().mapToDouble(Number::doubleValue).average().getAsDouble();double sum = doubleList.stream().mapToDouble(Number::doubleValue).sum();double max = doubleList.stream().mapToDouble(Number::doubleValue).max().getAsDouble();System.out.println("平均值:" + average + ",总和:" + sum + ",最大值:" + max);
}
测试结果: 平均值:12.4,总和:62.0,最大值:32.0
三、中间操作 摊平映射器flatMap()的用法
- flatMap(Function<? super T, ? extends Stream<? extends R>> mapper) - 将每个元素转换为某种元素类型的流,然后将它们连接成一个流。

摊平映射器flatMap()示例一:
public class StreamTest {public static void main(String[] args) {List<String> list = Arrays.asList("m,k,l,a", "1,3,5,7");List<String> listNew = list.stream().flatMap(s -> {// 将每个元素转换成一个streamString[] split = s.split(",");return Arrays.stream(split);}).collect(Collectors.toList());System.out.println("处理前的集合:" + list);System.out.println("处理后的集合:" + listNew);}
}
在这个例子中,初始时对象流的元素类型是长度为7的字符串:“m,k,l,a"和"1,3,5,7”。[ “m,k,l,a” , “1,3,5,7” ]。通过摊平映射器flatMap()转换后的对象流的元素类型是长度为1的字符串。最终对象流为[ “m” , “k” , “l” , “a” , “1” , “3” , “5” , “7” ]
实际上,上面的示例程序还可以简化,可简化为:
List<String> listNew = list.stream().flatMap(str->Stream.of(str.split(","))).collect(Collectors.toList());
摊平映射器flatMap()示例二:
package stream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class FlatMapTest {public static void test1() {List<String> items = Arrays.asList("glass", "brick","gold", "silver");List<String> flatMappedItems = items.stream().flatMap(item -> Stream.of(item.split(""))).collect(Collectors.toList());flatMappedItems.forEach(System.out::println);}public static void test2() {String songs = "Remember me to one who lives there";String[] words = songs.split(" ");List<String> strList = Arrays.stream(words).map(s -> s.split("e")).flatMap(e -> Arrays.stream(e)).collect(Collectors.toList());strList.forEach(System.out::println);}public static void main(String[] args) {test1();test2();}
}
测试结果图:

流的连接:有两种方式。如果是两个流的连接,可使用 Stream.concat() 方法;
如果是三个及三个以上流的连接,就使用 摊平映射器flatMap() 方法。
摊平映射器flatMap还可以用来实现流的连接,请看例程:
public static void concatStream() {String names[][] = { {"Alice", "Alien", "Bob"},{"Jack", "John", "Jobs"},{"Maria", "Golf", "Korea"} };//两个流的连接Stream<String> concat = Stream.concat(Arrays.stream(names[0]), Arrays.stream(names[1]));concat.forEach(System.out::println);System.out.println("===========");//多个流的连接,例子之一List<String[]> list = Arrays.asList(names);Stream<String> strStream = list.stream().flatMap(e->Arrays.stream(e));strStream.forEach(System.out::println);System.out.println("===========");Stream<String> first = Stream.of("Alice", "Alien", "Bob");Stream<String> second = Stream.of("Jack", "John", "Jobs");Stream<String> third = Stream.of("Maria", "Golf", "Korea");//多个流的连接,例子之二//Stream<String> stringStream = Stream.of(first, second, third).flatMap(s->s);Stream<String> stringStream = Stream.of(first, second, third).flatMap(Function.identity());stringStream.forEach(System.out::println);}
说明: 多个流的连接,“例子之一”和“例子之二”实现相同功能。另外,示例中“flatMap(Function.identity())”等价于“flatMap(s->s)”。
摊平映射器有很多,例如摊平为基本数据类型流的映射器(可由类型T的对象流转换为基本数据类型的流):
- IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper);
- LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper);
- DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper);
映射器map和flatMap的区别
map()操作将每个元素转换成一个新元素,并将所有这些新生成的元素收集到一个新的流中。
flatMap()操作将每个元素转换成一个新的流,并将所有这些新生成的流合并成一个单一的流。
flatMap()和map()之间还有一个重要的区别,那就是flatMap()支持处理包含嵌套数据结构的流。
参考文献:
- Java8 Stream:2万字20个实例,玩转集合的筛选、归约、分组、聚合-CSDN
- 恕我直言你可能真的不会java系列-CSDN
- Java8 Stream流使用-CSDN
- Java 8 Stream API:从基础到高级,掌握流处理的艺术
- JAVA8专题-Stream流操作详解
- Java 8新特性Stream()流
- Java8 特性笔记(四) Stream
第1篇:lambda表达式会用了么?
第2篇:Java Stream API?
第3篇:Stream的Filter与谓词逻辑
第4篇:Stream管道流Map操作
第5篇:Stream的状态与并行操作
第7篇:像使用SQL一样排序集合
第8篇-函数式接口
第9篇-元素的匹配与查找
第10篇-集合元素归约
第11篇-Stream API终端操作
Java Stream函数式编程第三篇:管道流结果处理
相关文章:
Java函数式编程【二】【Stream的装饰】【中间操作】【map映射器】【摊平映射器flatMap】
一、Java的Stream流式编程中的中间操作 Java的Stream流式编程中,中间操作是对数据流进行处理的一种方式,这些操作通常返回流对象本身,以便可以链接更多的操作。以下是一些常见的中间操作: filter(Predicate predicate) - 用于通过…...
树莓派明明安装了opencv和numpy,却找不到
当然不止树莓派,配置python环境都可能存在这个问题 可能是因为安装的 numpy 或者 opencv 版本与 Python 的包路径不匹配。下面是问题的常见原因及解决方法:【方法一和二优先考虑】 原因分析 多版本 Python 环境冲突: 树莓派上可能有多个版本…...
numpy.float8不存在;Python中,实现16位浮点数
目录 python中矩阵的浮点数存储 numpy.float8不存在 Python中,实现16位浮点数 实现 float16 关于 float8 python中矩阵的浮点数存储 在Python中,矩阵通常是通过嵌套列表(list of lists)、NumPy数组(numpy.ndarray)或其他类似的数据结构来表示的。矩阵中存储的数值所…...
Redis集群配置 (不使用docker 部署)
1. Redis集群简介 1.1 什么是Redis集群 Redis集群是一种通过将多个Redis节点连接在一起以实现高可用性、数据分片和负载均衡的技术。它允许Redis在不同节点上同时提供服务,提高整体性能和可靠性。根据搭建的方式和集群的特性,Redis集群主要有三种模式&…...
HTML5系列(7)-- Web Storage 实战指南
前端技术探索系列:HTML5 Web Storage 实战指南 🗄️ 致读者:本地存储的新纪元 👋 前端开发者们, 今天我们将深入探讨 HTML5 中的 Web Storage 技术,这是一个强大的本地存储解决方案,让我们能…...
【在Linux世界中追寻伟大的One Piece】读者写者问题与读写锁
目录 1 -> 读者写者问题 1.1 -> 什么是读者写者问题 1.2 -> 读者写者与生产消费者的区别 1.3 -> 如何理解读者写者问题 2 -> 读写锁 2.1 -> 读写锁接口 3 -> 读者优先(Reader-Preference) 4 -> 写者优先(Writer-Preference) 1 -> 读者写者…...
用到动态库的程序运行过程
当我们写好了一段代码然后编译运行后会生成可执行文件,该文件会存在磁盘的当前目录下,而当我们开始运行这段程序时,操作系统(加载器)需要将其从磁盘加载进内存然后执行相关操作,而对于用到动态库的程序&…...
类型转换与IO流:C++世界的变形与交互之道
文章目录 前言🎄一、类型转换🎈1.1 隐式类型转换🎈1.2 显式类型转换🎁1. C 风格强制类型转换🎁2. C 类型转换操作符 🎈1.3 C 类型转换操作符详解🎁1. static_cast🎁2. dynamic_cast&…...
Pytorch使用手册- TorchVision目标检测微调Tutorial的使用指南(专题十二)
这篇教程的目标是对一个预训练的 Mask R-CNN 模型进行微调,应用于 Penn-Fudan 行人检测与分割数据集。该数据集包含 170 张图像,里面有 345 个行人实例,我们将通过这个教程来演示如何使用 torchvision 中的新特性,训练一个面向自定义数据集的目标检测和实例分割模型。 注意…...
人工智能机器学习算法分类全解析
目录 一、引言 二、机器学习算法分类概述 (一)基于学习方式的分类 1. 监督学习(Supervised Learning) 2. 无监督学习(Unsupervised Learning) 3. 强化学习(Reinforcement Learning…...
Linux 35.6 + JetPack v5.1.4@DeepStream安装
Linux 35.6 JetPack v5.1.4DeepStream安装 1. 源由2. 步骤Step 1 安装Jetpack 5.1.4 L4T 35.6Step 2 安装依赖组件Step 3 安装librdkafkaStep 4 安装 DeepStream SDKStep 5 测试 deepstream-appStep 6 运行 deepstream-app 3. 总结3.1 版本问题3.2 二进制help 4. 参考资料 1. …...
图数据库 | 11、图数据库架构设计——高性能图存储架构(下)
在上篇内容中,老夫着重讲了高性能图存储系统的特点,咱们继续往下讲重点——高性能存储架构的设计思路!! 2.高性能存储架构设计思路 首先呢,存储架构以及核心数据结构的设计思路通常围绕如下4个维度来进行:…...
【HTTP】HTTP协议
一个Web Server就是个服务器软件(程序),或者是运行这个服务器软件的硬件(计算机),其主要功能是通过HTTP协议与客户端进行通信,来接收,存储,处理来自客户端的HTTP请求&…...
大数据新视界 -- Hive 基于 MapReduce 的执行原理(上)(23 / 30)
💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...
SpringBoot源码解析(六):打印Banner
SpringBoot源码系列文章 SpringBoot源码解析(一):SpringApplication构造方法 SpringBoot源码解析(二):引导上下文DefaultBootstrapContext SpringBoot源码解析(三):启动开始阶段 SpringBoot源码解析(四):解析应用参数args Sp…...
【计算机网络】实验6:IPV4地址的构造超网及IP数据报
实验 6:IPV4地址的构造超网及IP数据报 一、 实验目的 加深对IPV4地址的构造超网(无分类编制)的了解。 加深对IP数据包的发送和转发流程的了解。 二、 实验环境 • Cisco Packet Tracer 模拟器 三、 实验内容 1、了解IPV4地址的构造超网…...
easy excel 生成excel 文件
导包 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.3</version> </dependency> 内容 List<类> limspjreport 值; String fileName sdf.format(new Date()) "-…...
Ajax:回忆与节点
一点回忆 面对我的Ajax学习,实现前后端交互,最开始我采用的使用网络寻找intellij IDEA Ultimate破解方法,然后最终成功,然后按照相关教程配置java ee项目,然后中间又去配置了Tomcat服务器,然后又去学习了一…...
Python+OpenCV系列:Python和OpenCV的结合和发展
PythonOpenCV系列:Python和OpenCV的结合和发展 **引言****Python语言的发展****1.1 Python的诞生与发展****1.2 Python的核心特性与优势****1.3 Python的应用领域** **OpenCV的发展****2.1 OpenCV的起源与发展****2.2 OpenCV的功能特性****2.3 OpenCV的应用场景** *…...
Ubuntu20.04 由源码编译安装opencv3.2 OpenCV
Ubuntu20.04 由源码编译安装opencv3.2.0 获取 opencv 及opencv_contrib源代码 创建目录以存放opencv及opencv_contrib源代码 mkdir ~/opencv3.2.0 cd ~/opencv3.2.0获取opencv源代码并切换到对应tag git clone https://github.com/opencv/opencv.git cd opencv git checkou…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...
Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...
用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章
用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章 摘要: 操作系统内核的安全性、稳定性至关重要。传统 Linux 内核模块开发长期依赖于 C 语言,受限于 C 语言本身的内存安全和并发安全问题,开发复杂模块极易引入难以…...
GAN模式奔溃的探讨论文综述(一)
简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...
