java8 Lambda表达式以及Stream 流
Lambda表达式
Lambda表达式规则
-
Lambda表达式可以看作是一段可以传递的代码,
-
Lambda表达式只能用于函数式接口,而函数式接口只有一个抽象方法,所以可以省略方法名,参数类型等
-
Lambda格式:(形参列表) -> Lambda体 ; 在java中Lambda表达式本质是函数式接口的实现
Runnable runnable = () -> System.out.println("执行任务") ;
- 形参列表是接口中的抽象方法的形参列表
- Lambda体 是重写的抽象方法的方法体
-
Lambda语法:
- 形参列表 中 参数类型可以省略,如果只有一个参数,小括号可以省略
- lambda体如果只有一行语句,return和 {} 都可以省略
java常见的函数式接口,可以根据自己的业务需求重新这些方法简化代码
-
Consumer,消费型接口,有参数无返回,对参数进行某种操作
void accept(T t);
-
Supplier,供给型接口,无参有返回,返回某个对象
T get();
-
Function,函数型接口,有参有返回,对 T类型的参数进行操作返回 R类型的结果
R apply(T t);private static void extracted() {// Function<T, R> T为入参,R为返回结果Function<Integer,String> function = (in)->{return in+"123";};String apply = function.apply(12);System.out.println(apply); //12123}
-
Predicate,断定型接口,有参有返回,输入参数T,返回boolean值,用于判断对象是否满足某个条件
boolean test(T t);
-
其他函数式接口
- BiConsumer,功能和Consumer类似,只是多一个参数
- BiPredicate,功能和Predicate类似,同样只是多了一个参数
- BiFunction,功能和Function类似,同样只是多了一个参数
- IntFunction、LongFunction、DobleFunction、ToIntFunction、ToLongFunction、ToDobleFunction 返回对应类型的数据
方法引用
-
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用
-
方法引用是对Lambda的进一步简化,本质上就是Lambda表达式,而 Lambda 是函数式接口的实例,所以方法引用也是函数式接口的实例
-
语法为: 类(对象): : 方法名
-
方法引用 不需要方法的参数,调用可分为三种情况
- 情况1,对象 : : 非静态方法
-
情况2,类 : : 非静态方法 (在面向对象oop中是不允许的)
- 情况3,类 : : 静态方法
- 情况1和情况2 方法引用的要求:接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型完全相同
如下三种写法,从直接new到方法引用,代码的逻辑是完全一致的
private static void extracted1() {Consumer<String> consumer =new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}};consumer.accept("写法1");}private static void extracted2() {Consumer<String> consumer= (s)->System.out.println(s);consumer.accept("写法2");}private static void extracted3() {//方法引用是对Lambda的进一步简化,用来替换Lambda表达式,因为System.out对象的println方法已经实现过了,所以只需要直接调用就好了,不需要重新实现//接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型完全相同,如下参数都是一个字符串,返回值都是void,所以可以使用参数引用Consumer<String> consumer= System.out::println;consumer.accept("写法3");}
构造器引用
类似与方法应用,参数列表和返回值匹配就可以使用构造器引用,因为构造器也是方法
类名::new
同理,数组引用,可以把数组看作一个类
private static void extracted5() {//下面两种写法都是创建一个 10个长的数组Function<Integer,String[]> function = in-> new String[in];String[] apply = function.apply(10);Function<Integer,String[]> function1 = String[]::new;String[] apply1 = function1.apply(10);}
stream
Java8 Stream
- 与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。
- Java 8 中的 Stream 是对集合(Collection)对象功能的增强,使用的是函数式编程模式,它可以被用来对集合进行链状流式的操作
- 专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。
- Stream 不会存储数据,也不会改变原对象,每次操作都回返回一个新的stream
- Stream 分为顺序流和并行流
一个流式处理可以分为三个部分:
- 获取一个数据源→ 数据转换 → 执行操作获取想要的结果,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道。
转换成流
- 创建流的五种方式:
- 通过 stream 方法把 集合 或数组 (Arrays.stream())转换为流
- 通过 Stream.of 方法直接传入多个元素构成一个流;( 例如:Stream.of(10,20,30); )
- 通过 IntStream 或 DoubleStream 构造基本类型的流。( 例如:IntStream.of(10,20,30); )
- 创建无限流,无限流的使用较少
- 通过 Stream.iterate 方法使用迭代的方式构造一个无限流,然后使用 limit 限制流元素个数,
- 通过 Stream.generate 方法从外部传入一个提供元素的 供应商来构造无限流,然后使用 limit 限制流元素个数
中间操作
-
过滤:
-
filter,根据条件过滤
-
limit,操作也类似于SQL语句中的LIMIT关键字,不过相对功能较弱,limit返回包含前n个元素的流,当集合大小小于n时,则返回实际长度,
-
skip,操作与limit操作相反,如同其字面意思一样,是跳过前n个元素
-
distinct,操作类似于我们在写SQL语句时,添加的DISTINCT关键字,用于去重处理
public class StreamEntity {private String name;private Integer age;private String high; }public static void test() {//向集合中初始化了一些 StreamEntity 对象,以供操作List<StreamEntity> list = getList();//过滤 年龄大于25的对象 ,后续使用lambda打印list.stream().filter(a -> a.getAge() > 25).forEach(a -> System.out.println(a));//截取 集合中前两条数据 ,后续使用方法引用打印list.stream().limit(2).forEach(System.out::println);//跳过前两条数据list.stream().skip(2).forEach(System.out::println);//筛选,通过对象的hashcode和equals对集合中的数据进行去重list.stream().distinct().forEach(System.out::println);}
-
-
映射,包含两类映射操作:map和flatMap,就像sql可以仅输出我们需要的字段数据一样
- map可以在filter筛选的基础之上,通过map将实体映射成为我们需要的字符串
- flatMap与map的区别在于 flatMap是将一个流中的每个值都转成一个个流(流中的元素也有可能是流),然后再将这些流扁平化成为一个流,有点类似与集合的addAll,调用addAll向集合中添加集合,会把集合中的每一个参数都加到目标集合,而不是把集合对象加入到目标集合中
//将元素中转换为其他形式或者提取信息 ,如下:提取对象中的年龄,并加1list.stream().map(a->a.getAge()+1).forEach(System.out::println);//flatMapList<List<StreamEntity>> res =new ArrayList<>();res.add(list);res.add(list);//这里已经把集合中的集合全部拆出来了Stream<String> objectStream = res.stream().flatMap(a -> a.stream().map(b->b.getName()));objectStream.forEach(System.out::println);
-
排序
-
sorted(),进行自然排序,如果排序的对象没有实现 Comparator ,也就是没有排序规则,会报错
-
sorted(Comparator<? super T> comparator),如果排序的对象没有实现 Comparator ,也可以传入一个比较器
//按照年龄自然排序 list.stream().map(a->a.getAge()).sorted().forEach(System.out::println);//传入比较器 list.stream().sorted((a, b) -> a.getAge() - b.getAge()).forEach(System.out::println); //使用方法引用为: list.stream().sorted(Comparator.comparingInt(StreamEntity::getAge)).forEach(System.out::println);
-
终止操作(终端操作)
-
不调用终止操作,中间操作是不会执行的,调用终止操作产生结果后,stream就不能再被使用了
-
查找
- allMatch用于检测是否全部都满足指定的参数行为,如果全部满足则返回true
- anyMatch则是检测是否存在一个或多个满足指定的参数行为,如果满足则返回true
- noneMatch用于检测是否不存在满足指定行为的元素,如果不存在则返回true
- findFirst用于返回满足条件的第一个元素,findFirst不携带参数,具体的查找条件可以通过filter设置
- findAny相对于findFirst的区别在于,findAny不一定返回第一个,而是返回任意一个
// boolean b = list.stream().map(a -> a.getAge()).allMatch(a -> a > 30); // 用于返回满足条件的第一个元素,查找条件可以通过filter设置 Optional<Integer> first = list.stream().map(a -> a.getAge()).filter(a -> a > 30).findFirst(); Integer integer = first.get()
- count 返回流中的元素个数
- max 返回流中的最大值
- min 返回流中的最小值
- forEach 内部迭代
long count = list.stream().count(); //根据自定义比较器求最大 StreamEntity s1 = list.stream().max((a, b) -> a.getAge() - b.getAge()).get(); //根据自定义比较器求最小 StreamEntity s2 = list.stream().min((a, b) -> a.getAge() - b.getAge()).get(); //迭代 list.stream().forEach(a-> System.out.println(a.getAge()+1));
-
归约
- reduce 可以将流中的元素反复结合起来,得到一个值
// 获取年龄的总和 Integer s1 = list.stream().map(a -> a.getAge()).reduce((b, d) -> b + d).get(); // reduce 的一个参数是初始值 Integer s2 = list.stream().map(a -> a.getAge()).reduce(0, (b, d) -> b + d);
-
收集
- 归约 ,收集器也提供了相应的归约操作
- collect 收集,需要用过Collectors中返回的Collector,将结果收集到指定的结果集中,例如 list、map、set 等
//转换为 list List<StreamEntity> collect = list.stream().collect(Collectors.toList()); //转化为 map Map<Integer, StreamEntity> collect1 = list.stream().collect(Collectors.toMap(a -> a.getAge(), a -> a)); //转换为 set Set<String> collect2 = list.stream().map(a -> a.getName()).collect(Collectors.toSet());
-
分组,在数据库操作中,我们可以通过GROUP BY关键字对查询到的数据进行分组,java8的流式处理也为我们提供了这样的功能,Collectors.groupingBy来操作集合
- 分区,可以看做是分组的一种特殊情况,在分区中key只有两种情况:true或false,目的是将待分区集合按照条件一分为二
Optional
- 参考 Google 的 Guava,用于尽量避免空指针异常
- Optional 是一个容器类,用于保存任意类型的值,代表这个值存在,或者保存null,代表值不存在,
常见方法:
-
创建Optional 对象
-
empty() 创建空的实例
-
of(T t),t不能为空
-
ofNullable(T t)
-
-
获取Optional 对象的值
- get方法会在值为null的时候抛出异常,可以用ifPresent()方法验证值是否为空
- orElse()方法可以在创建实例时就指定返回的默认值
相关文章:
java8 Lambda表达式以及Stream 流
Lambda表达式 Lambda表达式规则 Lambda表达式可以看作是一段可以传递的代码, Lambda表达式只能用于函数式接口,而函数式接口只有一个抽象方法,所以可以省略方法名,参数类型等 Lambda格式:(形参列表&…...

基于Java的音乐网站管理系统设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding) 代码参考数据库参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…...

【蓝桥】小蓝的疑问
1、题目 问题描述 小蓝和小桥上完课后,小桥回顾了课上教的树形数据结构,他在地上画了一棵根节点为 1 的树,并且对每个节点都赋上了一个权值 w i w_i wi。 小蓝对小桥多次询问,每次询问包含两个整数 x , k x,k x,kÿ…...

漏洞复现-海康威视综合安防管理平台信息泄露【附Poc】
目录 【产品介绍】 【产品系统UI】 【漏洞说明】 【指纹】 【Nuclei Poc】 【验证】 【产品介绍】 海康威视(Hikvision)是一家总部位于中国杭州的公司,是全球最大的视频监控产品供应商。除了传统的CCTV摄像机和网络摄像机,海…...

【完美世界】被骂国漫之耻,石昊人设战力全崩,现在真成恋爱世界了
【侵权联系删除】【文/郑尔巴金】 深度爆料,《完美世界》动漫第135集预告片已经更新了,但是网友们对此却是一脸槽点。从预告中可以看出,石昊在和战王战天歌的大战中被打成重伤,最后云曦也被战天歌抓住。在云曦面临生死危机的时候…...

34二叉树-BFS和DFS求树的深度
目录 LeetCode之路——104. 二叉树的最大深度 分析 解法一:广度优先遍历 解法二:深度优先遍历 总结 深度优先搜索 (DFS) 广度优先搜索 (BFS LeetCode之路——104. 二叉树的最大深度 给定一个二叉树 root ,返回其最大深度。 二叉树的…...
Android Glide判断图像资源是否缓存onlyRetrieveFromCache,使用缓存数据,Kotlin
Android Glide判断图像资源是否缓存onlyRetrieveFromCache,使用缓存数据,Kotlin import android.graphics.Bitmap import android.os.Bundle import android.util.Log import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity…...
设计模式之创建型模式
创建型模式与对象的创建有关。 创建型模式抽象了对象实例化的过程,这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。创建型模式有以下 工厂模式(Factory Method) 意图…...

使用jdbc技术连接数据库
连接数据库 <dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version><scope>compile</scope></dependency> </dependencies> g…...
OpenLayers入门,快速搭建vue+OpenLayers地图脚手架项目
专栏目录: OpenLayers入门教程汇总目录 前言 本章针对Vue初学者,对Vue不熟悉,甚至还不会Vue的入门学生读者。 本章会详细讲解从NodeJS环境到npm环境的各个步骤,再到使用vue-cli脚手架快速生成项目,以及添加OpenLayers地图库依赖,编写简单的xyz高德地图显示页面的完整教…...
完成比写得好更重要,先完成初稿再说
我发现自己有个毛病,总想着满意了才动手。于是,经常做到一半跑去看文献,然后陷入文献中觉得这个比自己好,那个比自己好。于是,暂时中断手边工作,最后进度被推迟,甚至啥也没做出来。 今晚再次听…...
Spring boot 处理复杂json接收,同种类型、不同场景处理
场景: json大体格式一致,但是 ext_info 扩展字段对象,场景不同字段不同根据某字段类型,不同值,对应不同实现的 Component,处理不同场景这里根据 event,来做不同处理 {"data": {"event"…...
排列置换环上构造:1025T3
http://cplusoj.com/d/senior/p/SS231025C 排列构造的新知识:上置换环! 我们发现朴素做法是 n 2 n^2 n2 级别的,但数据范围希望我们是 n 2 2 \frac {n^2}2 2n2 级别的。我们发现我们暴力复制序列显得非常蠢,因为很多序列前后…...
Stable diffusion的一些参数意义及常规设置
在线stabel Diffusion模型 https://huggingface.co/spaces/stabilityai/stable-diffusion 随机种子 seed 如果想要同一个文本提示,生成多次都是同一图像,可以设置一个随机种子,类似于random.seed()的原理,并将生成器传递给管道。…...
成员变量、静态成员变量、局部变量、常量的内存区域
一、Java中没有全局变量的概念,变量分为类的成员变量、静态成员变量和方法中的局部变量 1、局部变量,基本类型的局部变量变量名和值都存放在虚拟机栈中,引用类型的局部变量变量名存放在栈中,而变量指向的对象存放在堆中。记也很好…...

网络协议--IGMP:Internet组管理协议
13.1 引言 12.4节概述了IP多播给出,并介绍了D类IP地址到以太网地址的映射方式。也简要说明了在单个物理网络中的多播过程,但当涉及多个网络并且多播数据必须通过路由器转发时,情况会复杂得多。 本章将介绍用于支持主机和路由器进行多播的In…...

网络安全https
http是明文的,相当于在网上裸奔,引出了https,大多数网站都转为了https,连非法的赌博网站有的都是https的。 1.https的网站是不是必须让用户装数字证书? 答:分两种,一种是单向认证,像…...
xcode Simulator 手动安装
xcode Simulator 手动安装 参考文档 xcode又又又升级了,升级完成之后不下载最新的 iOS 17 Simulator就不能编译运行了,只能静静的等他下载。但是离谱的是这个居然没有断点续下,每次都要重新下载,眼睁睁的看着下载了4个G然后断掉…...

Unity中国、Cocos为OpenHarmony游戏生态插上腾飞的翅膀
2023年是OpenHarmony游戏生态百花齐放的一年!为了扩展OpenHarmony游戏生态,OpenHarmony在基金会成立了游戏SIG小组,游戏SIG小组联合cocos,从cocos2dx入手一周内快速适配了cocos2.2.6的MVP版本,随后又分别适配了cocos2d…...
Monaco Editor编辑器
monaco-editor Monaco Editor 是一个基于浏览器的代码编辑器,由微软开发。它提供了丰富的功能,包括语法高亮、智能代码补全、代码折叠、多光标编辑等。Monaco Editor 是 Visual Studio Code 的核心编辑器,也被广泛用于其他开发工具和在线代码…...

什么是VR全景相机?如何选择VR全景相机?
VR全景相机的定义、原理及特点 定义:VR全景相机是利用特殊镜头设计和图像处理技术,能够捕捉到360度全方位、无死角的高清影像,并通过虚拟现实技术将用户带入沉浸式全景环境的相机设备。 原理:VR全景相机通过集成多个鱼眼镜头&am…...

基于cornerstone3D的dicom影像浏览器 第二十七章 设置vr相机,复位视图
文章目录 前言一、VR视图设置相机位置1. 相机位置参数2. 修改mprvr.js3. 调用流程1) 修改Toolbar3D.vue2) 修改View3d.vue3) 修改DisplayerArea3D.vue 二、所有视图复位1.复位流程说明2. 调用流程1) Toolbar3D中添加"复位"按钮,发送reset事件2) View3d.vu…...
专业课复习笔记 11
从今天开始每天下午复习专业课。慢慢复习专业课。目标至少考一个一百分吧。毕竟专业课还是比较难的。要是考不到一百分,我感觉自己就废掉了呢。下面稍微复习一下计组。 复习指令格式和数据通路设计。完全看不懂,真是可恶啊。计组感觉就是死记硬背&#…...
JS入门——三种输入方式
JS入门——三种输入方式 一、方式一:直接在警告框弹出(window可以省略) <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body><script><!-- 方式一直接在警告框弹…...
MySQL 的 super_read_only 和 read_only 参数
MySQL 的 super_read_only 和 read_only 参数 一、参数基本概念 1. read_only 参数 作用:控制普通用户是否只能读取数据影响范围:所有非SUPER权限的用户默认值:OFF(可读写) 2. super_read_only 参数 作用…...
C语言操作Kafka
Kafka服务 Kafka的快速入门 文档很详细,基本上几步就可以搭建一个Kafka测试环境。 下载Kafka的二进制包,然后解压。 wget https://www.apache.org/dyn/closer.cgi?path/kafka/4.0.0/kafka_2.13-4.0.0.tgz tar -xzf kafka_2.13-4.0.0.tgz cd kafka_2.…...
每日算法 -【Swift 算法】字符串转整数算法题详解:myAtoi 实现与正则表达式对比
Swift 字符串转整数算法题详解:myAtoi 实现与正则表达式对比 🧩 题目背景 LeetCode 上的经典算法题 8. String to Integer (atoi) 是一道考察字符串解析与边界处理的题目。这道题虽看似简单,但处理细节相当复杂。我们将使用 Swift 语言实现…...

【C++ Qt】容器类(GroupBox、TabWidget)内附思维导图 通俗易懂
每日激励:“不设限和自我肯定的心态:I can do all things。 — Stephen Curry” ✍️绪论: 本章主要介绍了 Qt 中 QGroupBox 与 QTabWidget 控件。QGroupBox 是带标题的分组框,能容纳其他控件,有标题、对齐方式、是否…...
小表驱动大表更快吗,不是
背景 head头表(5000),line行表(15万),导出数据包含头和行,一对多。 以行表为维度导出15万数据。 sql 如下两个sql查询,有如下差异 驱动方式:第一个大表驱动小表&…...

报错SvelteKitError: Not found: /.well-known/appspecific/com.chrome.devtools.json
报错信息 SvelteKitError: Not found: /.well-known/appspecific/com.chrome.devtools.json 解决方案一 更新所有依赖 npm update解决方案二(不一定成功) src\lib\hooks.server.ts,每次请求服务器时执行 import type { Handle } from &…...