Java8新特性1——函数式接口lambda表达式
Java8新特性1——函数式接口&lambda表达式
注:以下内容基于Java 8,所有代码都已在Java 8环境下测试通过
目录:
- Java8新特性1——函数式接口&lambda表达式
- 方法引用
- Stream
1. 函数式接口
如果在一个接口中,有且只有一个抽象方法,则该接口被称为函数式接口。如:
interface Test {void test();
}
注:
可以在接口前使用 @FunctionalInterface
注解,判断这个接口是否是⼀个函数式接口。如:
@FunctionalInterface
interface Test1 {//有且仅有一个抽象方法,是函数式接口void test();
}@FunctionalInterface
interface Test2 {//有且仅有一个抽象方法,是函数式接口void test();default void f() {}
}@FunctionalInterface
interface Test3 {//没有抽象方法,不是函数式接口,编译器报错
}@FunctionalInterface
interface Test4 {//有多个抽象方法,不是函数式接口,编译器报错void test1();void test2();
}
2. lambda表达式
2.1 lambda表达式作用
lambda表达式是一个匿名函数,用于简化函数式接口的实现。
在Java中,接口不能实例化,但接口对象可以指向实现类对象。当没有实现类对象时,可以通过匿名类的方式,如:
public class Main {public static void main(String[] args) {Test test = new Test() {@Overridepublic void f() {System.out.println("使用匿名函数的方式实现了函数式接口");}};test.f();}
}@FunctionalInterface
interface Test {void f();
}
使用匿名类的方式代码不是很简洁,因此引入了lambda表达式,如:
public class Main {public static void main(String[] args) {Test test = () -> System.out.println("使用lambda表达式的方式实现了函数式接口");test.f();}
}@FunctionalInterface
interface Test {void f();
}
在使用lambda表达式之后,代码变得简洁了很多,因此可以说lambda表达式是和函数式接口相辅相成的。在上面的代码中,lambda表达式实际做了以下三个工作:
-
自动实现接口
Test test = new Test();
-
将
->
前的参数自动添加到抽象函数里面(上面代码中抽象函数没有参数)void f();
-
将
->
后的语句作为抽象函数的方法体void f(){System.out.println("使用lambda表达式的方式实现了函数式接口"); }
2.2 lambda表达式语法格式
lambda表达式的格式如下:
(参数1, 参数2, ……) -> {方法体;
}
其中:
- 参数要求和函数式接口中抽象方法的参数一致(包括数量和类型以及顺序)
- 如果函数式接口中抽象方法有返回值,则实现的时候也需要返回值
public class Main {public static void main(String[] args) {Test test = (int x, int y) -> {//参数、返回值与函数式接口中抽象方法一致return x + y;};test.add(1, 2);}
}@FunctionalInterface
interface Test {int add(int x, int y);
}
2.3 lambda表达式的精简
-
参数精简
- 参数类型可以省略,若省略一个类型参数,则所有的类型参数都要省略
- 若只有一个参数,则小括号可以省略
- 若参数为0或者多于1个,则小括号不可以省略
-
方法体精简
- 若方法体中只有一行代码,则花括号可以省略
- 若方法体中只有一行代码且是return语句,则在省略大括号的时候还需要去掉return关键字
- 若方法体中有多行代码或者使用了return语句,则大括号不可以省略
public class Main {public static void main(String[] args) {//只有一个参数,省略了小括号//只有一条return语句,省略了花括号即return关键字Test test = x -> Math.exp(x);test.exp(1);} }@FunctionalInterface interface Test {double exp(double x); }
2.4 变量作用域
- lambda表达式只可以访问外部变量,但不能修改外部变量
- lambda表达式访问的外部变量一般都是声明为 final 的,但也可以不用声明为 final ,但该变量在声明后不能被修改
- lambda表达式中不允许声明一个与局部变量同名的参数或局部变量
public class Main {static final int a = 0;public static void main(String[] args) {final int num1 = 10;int num2 = 20;//num2 = 40; //声明后不能被修改Test test1 = x -> {System.out.println(num1);//可以访问外部被声明为 final 的变量System.out.println(num2);//可以访问外部的普通变量//num1 = 20;//只能访问,不能修改//num2 = 20;//只能访问,不能修改//int num1 = 20;//不允许声明一个与局部变量同名的局部变量return Math.exp(x);};//num2 = 40; //声明后不能被修改test1.exp(1);//不允许声明一个与局部变量同名的参数//Test test2 = num1 -> Math.exp(num1);} }@FunctionalInterface interface Test {double exp(double x); }
3. 四大函数式接口
为了让开发者高效地使用函数式接口,Java 8 在 java.util.function
包下提供了许多函数式接口,以下四种是最为常见的:
接口原型 | 抽象方法 | 备注 |
---|---|---|
Consumer< T > | accept(T t) | 消费型接口 |
Supplier< T > | T get() | 供给型接口 |
Function<T, R> | R apply(T t) | 函数型接口 |
Predicate< T > | boolean test(T t) | 断言型接口 |
3.1 Consumer< T >:消费型接口
该接口只接收输入参数但不输出返回值,消费对象,只进不出。
-
接口原型:
@FunctionalInterface public interface Consumer<T> {void accept(T t); }
-
使用示例:
import java.util.function.Consumer;public class Main {public static void main(String[] args) {Consumer<Integer> acc = (t) -> System.out.println(t);//实现 Consumer 接口acc.accept(10);} }
3.2 Supplier< T >:供给型接口
该接口只输出返回值但不接收输入参数,生成对象,只出不进。
-
接口原型:
public interface Supplier<T> {T get(); }
-
使用示例:
import java.util.function.Supplier;public class Main {public static void main(String[] args) {Supplier<Integer> sup = () -> 10;//实现 Supplier 接口System.out.println(sup.get());} }
3.3 Function<T, R>:函数型接口
该接口既接收输入参数又输出返回值,用于指定特定功能,有进有出。
-
接口原型:
@FunctionalInterface public interface Function<T, R> {R apply(T t); }
-
使用示例:
import java.util.function.Function;public class Main {public static void main(String[] args) {Function<Integer, String> fun = (x) -> {//实现 Function 接口String out = "输入的整数是" + x;return out;};System.out.println(fun.apply(10));} }
3.4 Predicate< T >:断言型接口
该接口既接收输入参数又输出返回值,且返回值只能是布尔值,用于条件判断,有进有出。
-
函数原型:
public interface Predicate<T> {boolean test(T t); }
-
使用示例:
import java.util.function.Predicate;public class Main {public static void main(String[] args) {Predicate<Integer> pre = (x) -> x % 2 == 0;//实现 Predicate 接口int a = 10;if (pre.test(10)) {System.out.println(a + "是偶数");} else {System.out.println(a + "是奇数");}} }
相关文章:
Java8新特性1——函数式接口lambda表达式
Java8新特性1——函数式接口&lambda表达式 注:以下内容基于Java 8,所有代码都已在Java 8环境下测试通过 目录: Java8新特性1——函数式接口&lambda表达式方法引用Stream 1. 函数式接口 如果在一个接口中,有且只有一个抽…...

文本标注技术方案(NLP标注工具)
Doccano doccano 是一个面向人类的开源文本注释工具。它为文本分类、序列标记和序列到序列任务提供注释功能。您可以创建用于情感分析、命名实体识别、文本摘要等的标记数据。只需创建一个项目,上传数据,然后开始注释。您可以在数小时内构建数据集。 支持…...
03-使用一个不可变对象作为key,红黑树怎么比较大小?
使用一个不可变对象作为key,红黑树怎么比较大小? 答:Java 中的红黑树是通过左旋、右旋的方式来维护树的平衡性,而左旋、右旋又依赖于节点大小的比较。对于使用不可变对象作为key实际上是可以的,因为比较key的大小本身…...
2021江苏省赛热身赛 C Magic Rabbit(数形结合)
2021江苏省赛热身赛 C Magic Rabbit(数形结合) Magic Rabbit 非常好且巧妙地一道题。 大意:给出三种溶液 , 三种溶液分别含有不同浓度的 x ,y 两种物质。 溶液x (mg/ml)y (mg/ml)溶液1x1y1溶液2x2y2溶液3x3y3 给出 Q 组询问 ,…...
AES加密(2):AES代码实现解析
在我的上一篇文章AES基础知识和计算过程中,大概介绍了AES(Rijndael)加密的整个过程。那么在这一篇文章中,就来看一下AES在代码中是如何实现的,也有助于我们理解其中的一些细节。 本篇文章所用的AES代码来源于Szymon Stefanek的开源C代码 文章…...

SpringBoot项目通过分词器生成词云
目录 前言一、词云是什么?二、使用步骤1.引入依赖2.application.yml3.Controller4.分词工具类4.词云生成工具类、支持输出文件和字节流 注意 前言 公司项目涉及到员工任务管理,需要从员工任务中获取任务信息生成个人词云图,可以把员工任务中…...

Nacos 配置管理及相关使用
文章目录 Nacos 配置管理一、统一配置管理1、在Nacos 中添加配置文件2、从微服务拉取配置3、配置实现步骤(1)引入 nacos-config 依赖(2)添加 bootstrap.yml(4)在 nacos 中添加配置 二、配置热更新1、配置热…...
重发布与路由策略
华子目录 重发布重发布条件重发布配置规则重发布名词配置命令ospf往rip重发布(重发布动态)静态往rip重发布(重发布静态)直连往rip重发布(重发布直连)rip往ospf重发布(重发布动态)静态…...
57. 插入区间(C++题解)
57. 插入区间 插入区间 给你一个无重叠的 ,按照区间起始端点排序的区间列表。 在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。 示例 1: 输入&#x…...

【数据结构Java版】 初识泛型和包装类
目录 1.包装类 1.1基本数据类型以及它们所对应的包装类 1.2装箱和拆箱 1.3自动装箱和自动拆箱 2.什么是泛型 3.引出泛型 4.泛型类的使用 4.1语法 4.2示例 4.3类型推导 5.泛型是如何编译的 5.1擦除机制 5.2正确的写法 6.泛型的上届 6.1语法 6.2示例 …...
Spring中如何解决循环依赖问题的三种方法
什么是循环依赖问题 在 Spring 中,循环依赖问题指的是两个或多个 bean 之间相互依赖形成的闭环。具体而言,当 bean A 依赖于 bean B,同时 bean B 也依赖于 bean A,就形成了循环依赖。 循环依赖问题在 Spring 容器中是一个非常常…...

【ArcGIS Pro二次开发】(65):进出平衡SHP转TXT、TXT转SHP
最近一个小伙伴提了这么一个需求,需要把TXT和SHP进行互转。 这种TXT文件其实遇到了好几个版本,都有一点小差异。之前已经做过一个TXT转SHP的工具,但好像不适用。于是针对这个版本,做了互转的2个工具。 【SHP转TXT】 一、要实现的…...

Shell开发实践:服务器的磁盘、CPU、内存的占用监控
🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年6月CSDN上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师…...
超详细 async和await 项目实战运用(附加文字解答+源码)
文章目录 问题描述async什么是 asyncasync 的作用async 的应用场景async 优点 await什么是 awaitawait 的作用await 的应用场景await 的优点async和 await结合使用 结束语 大家好!又到了愉快的周末假期,今天是2023年9月3日|农历七月十九,我最…...

Maven入门教程(三):Maven语法
视频教程:Maven保姆级教程 Maven入门教程(一):安装Maven环境 Maven入门教程(二):idea/Eclipse使用Maven Maven入门教程(三):Maven语法 Maven入门教程(四):Nexus私服 Maven入门教程(五):自定义脚手架 6.Mav…...
C++技术点,故事解析
语言的魅力 从人类诞生开始 ,南方古猿到现代人类经历了非常多变化; 南方古猿到能人 有什么变化? 能人会使用工具,由于会使用工具 就可以获得肉类食物,当然只能吃一些动物腐肉 直到进化成直立人的晚期,在东…...

数据结构(Java实现)-字符串常量池与通配符
字符串常量池 在Java程序中,类似于:1, 2, 3,3.14,“hello”等字面类型的常量经常频繁使用,为了使程序的运行速度更快、更节省内存,Java为8种基本数据类型和String类都提供了常量池。…...
python强化学习--gym安装与使用
最近开始学习强化学习,第一步肯定是要学会安装和使用pym,原本以为很简单,事实上确实很简单,但是遇到一个小问题,就是安装gym之后,在应用的过程中,游戏界面没有显示出来,了解后才知道…...

105. 从前序与中序遍历序列构造二叉树
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。 思路:题目给出了先序遍历和中序遍历的结果,因为先序遍历遵循根–>左–>…...

(第六天)初识Spring框架-SSM框架的学习与应用(Spring + Spring MVC + MyBatis)-Java EE企业级应用开发学习记录
SSM框架的学习与应用(Spring Spring MVC MyBatis)-Java EE企业级应用开发学习记录(第六天)初识Spring框架 昨天我们已经把Mybatis框架的基本知识全部学完,内容有Mybatis是一个半自动化的持久层ORM框架,深入学习编写动态SQL&a…...

C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错
出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...

网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
【Go语言基础【12】】指针:声明、取地址、解引用
文章目录 零、概述:指针 vs. 引用(类比其他语言)一、指针基础概念二、指针声明与初始化三、指针操作符1. &:取地址(拿到内存地址)2. *:解引用(拿到值) 四、空指针&am…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...