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 的核心编辑器,也被广泛用于其他开发工具和在线代码…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...
