【Java 新特性】常用函数式接口

在现代 Java 开发中,函数式接口无疑是一种强大的工具。它们不仅让代码更简洁,也使开发者能够更灵活地表达逻辑。函数式接口就像电器的插头,为你的代码提供了“标准接口”。想象一下,有了插头,不同的设备都能轻松接入电源。同样,函数式接口让你可以用统一的方式编写逻辑,无论是数据处理、条件判断还是结果生成,都变得更灵活、更简洁。


一、什么是函数式接口?

函数式接口是 仅包含一个抽象方法 的接口。它们是 Java 8 中引入的核心特性,常与 Lambda 表达式 一起使用。Java 提供了 @FunctionalInterface 注解来显式声明一个接口为函数式接口,同时也让编译器帮助我们验证其规范性。

关于 Lambda 表达式的详细讲解可以参考我的另一篇博客

函数式接口的基本规则:

  1. 必须只有一个抽象方法
  2. 可以包含多个默认方法或静态方法。
  3. 使用 @FunctionalInterface 注解并非强制,但推荐使用。

形象比喻

函数式接口就像一张定制的契约(合同),规定只有一个核心任务需要实现。例如,Runnable 的任务是 "做某件事情",具体做什么由你定义,而 Java 会帮你安排如何调用。

定义示例

// 此自定义函数式接口接收两个参数,返回一个 int 类型的值
@FunctionalInterface
interface Calculator {int calculate(int a, int b);
}

实现时:

Calculator addition = (a, b) -> a + b;
System.out.println(addition.calculate(5, 3)); // 输出:8

二、为什么需要函数式接口?

在 Java 8 之前,我们实现逻辑常需要匿名内部类,这既冗长又不直观。函数式接口加上 Lambda 表达式,简直就是如虎添翼。

对比代码:

  • 匿名内部类写法
Runnable task = new Runnable() {@Overridepublic void run() {System.out.println("Hello, World!");}
};
  • Lambda 表达式写法
Runnable task = () -> System.out.println("Hello, World!");

是不是清爽简洁多了?


三、常用的函数式接口

Java 提供了一整套常用的函数式接口,它们就像工具箱中的各种工具,针对不同任务有不同功能。

接口方法签名用途例子类比
Function<T,R>R apply(T t)将一个参数映射为另一个结果就像去买东西,一手交钱(T)一手交货(R)
Consumer<T>void accept(T t)消费一个参数,无返回值就像吃食物(T),吃完就消化了(void)。
Supplier<T>T get()无参数,返回一个结果就像一台免费物品供应机,按下按钮给你物品(T)。
Predicate<T>boolean test(T t)判断条件,返回布尔值就像一台安检机,判断物品(T)是否符合安全标准(boolean 类型)。
BiFunction<T,U,R>R apply(T t, U u)接收两个参数,返回一个结果就像输入两个不同类型的值(T、U),输出操作后的任意结果(R)。
BiConsumer<T,U>void accept(T t, U u)接收两个参数,无返回值两个不同类型的值(T、U)进行操作,不返回结果
UnaryOperator<T>T apply(T t)一元操作,输入和输出类型相同对一个值进行操作,输入(T)和输出(T)的类型没变
BinaryOperator<T>T apply(T t1, T t2)二元操作,输入和输出类型相同两个相同类型的值进行操作,返回操作后相同类型的结果(T)。

四、函数式接口基础用法

1. Function:将输入映射为输出

Function<String, Integer> stringToLength = s -> s.length();
System.out.println(stringToLength.apply("Hello")); // 输出:5

2. Predicate:判断条件是否成立

Predicate<Integer> isEven = n -> n % 2 == 0;
System.out.println(isEven.test(4)); // 输出:true
System.out.println(isEven.test(3)); // 输出:false

3. Supplier:无条件生成结果

Supplier<Double> randomSupplier = () -> Math.random();
System.out.println(randomSupplier.get());

4. Consumer:处理输入,不返回结果

Consumer<String> logger = message -> System.out.println("Log: " + message);
logger.accept("Application started"); // 输出:Log: Application started

5. UnaryOperator:对输入进行一元操作

UnaryOperator<Integer> increment = n -> n + 1;
System.out.println(increment.apply(5)); // 输出:6

6. BinaryOperator:对两个输入进行二元操作

BinaryOperator<Integer> max = (a, b) -> a > b ? a : b;
System.out.println(max.apply(5, 10)); // 输出:10

五、开发中常用场景

1. 使用 Function 进行 map 转换

List<Integer> integersList = List.of(1, 2, 3);
List<Integer> mapList = integersList.stream().map(i -> (i * 2)).toList();

2. 使用 Function 实现多步转换

就像流水线上的加工流程,一个任务接着另一个任务:

Function<Integer, Integer> multiplyBy2 = x -> x * 2;
Function<Integer, Integer> add3 = x -> x + 3;Function<Integer, Integer> combined = multiplyBy2.andThen(add3);
System.out.println(combined.apply(5)); // 输出:13

3. 使用 Predicate 实现复杂条件判断

类比:安检门,多个条件逐步筛选。

Predicate<String> startsWithA = s -> s.startsWith("A");
Predicate<String> endsWithZ = s -> s.endsWith("Z");Predicate<String> complexCondition = startsWithA.and(endsWithZ);System.out.println(complexCondition.test("AZ")); // 输出:true
System.out.println(complexCondition.test("BZ")); // 输出:false

4. 使用 Predicate 进行过滤

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().filter(name -> name.startsWith("A")).forEach(System.out::println); // 输出:Alice

5. 使用 Supplier 延迟加载资源

Supplier<String> configSupplier = () -> {System.out.println("Fetching configuration...");return "Default Config";
};// 只有在调用 get() 时才会执行逻辑
System.out.println(configSupplier.get()); // 输出:Fetching configuration...

6. 使用 Consumer 记录日志

专注于记录,但不返回结果。

Consumer<String> logger = message -> System.out.println("Log: " + message);
logger.accept("User logged in"); // 输出:Log: User logged in

7. 使用 BiConsumer 处理键值对

BiConsumer<String, Integer> printOrder = (item, quantity) -> System.out.println("Ordered " + quantity + "x " + item);printOrder.accept("Apple", 3); // 输出:Ordered 3x Apple

8. 使用 UnaryOperator 实现批量自增

每个商品都增加同样的数量。

UnaryOperator<Integer> incrementBy10 = x -> x + 10;
List<Integer> numbers = List.of(1, 2, 3, 4);
List<Integer> incrementedNumbers = numbers.stream().map(incrementBy10).toList();System.out.println(incrementedNumbers); // 输出:[11, 12, 13, 14]

9. 使用 BinaryOperator 处理累积运算(聚合数据)

像汇总账单,每次合并两个部分,直到得出总数。

BinaryOperator<Integer> sumOperator = (a, b) -> a + b;
List<Integer> nums = List.of(1, 2, 3, 4, 5);
int total = nums.stream().reduce(0, sumOperator);System.out.println(total); // 输出:15

六、总结

函数式接口让代码更简洁、更灵活,不再是过去冗长的匿名类实现。通过以下这张表格,你可以快速回忆常用的几个函数式接口的用途:

接口方法签名主要用途
Function<T,R>R apply(T t)接受一个输入,返回一个输出,常用于映射操作
Consumer<T>void accept(T t)消费输入,无返回值,常用于执行操作
Supplier<T>T get()无输入,生成结果,常用于延迟加载
Predicate<T>boolean test(T t)判断条件,返回布尔值,用于过滤操作
UnaryOperator<T>T apply(T t)对输入执行一元操作,返回同类型结果
BinaryOperator<T>T apply(T t1, T t2)对两个输入执行二元操作,返回同类型结果
BiFunction<T,U,R>R apply(T t, U u)接收两个不同类型输入,返回一个输出
BiConsumer<T,U>void accept(T t, U u)消费两个不同类型输入,无返回值

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/498748.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pyinstaller打包exe可执行文件

cd命令符进入要打包文件路径下&#xff0c;执行&#xff1a; 1.打包单个py文件&#xff0c;在控制台执行;dist下会生成2个文件&#xff0c;一个是exe文件 pyinstaller -D happy.py (cd命令符进入要打包文件路径下&#xff0c;执行) 打包单个py文件&#xff0c;在控制台执行;…

PDF怎么压缩得又小又清晰?5种PDF压缩方法

PDF 文件在日常办公与学习中使用极为频繁&#xff0c;可想要把它压缩得又小又清晰却困难重重。一方面&#xff0c;PDF 格式本身具有高度兼容性&#xff0c;集成了文字、图像、矢量图等多样元素&#xff0c;压缩时难以兼顾不同元素特性&#xff0c;稍不注意&#xff0c;文字就会…

【C++】B2083 画矩形

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述题目详情输入示例&#xff1a;输出示例&#xff1a; &#x1f4af;学生初始作品分析学生代码分析此代码主要思路&#xff1a;代码之优缺 &#x1f4af;老师初始解法…

记录第一次跑YOLOV8做目标检测

今天是24年的最后一天&#xff0c;终于要向新世界开始破门了&#xff0c;开始深度学习&#xff0c;YOLO来敲门~ 最近做了一些皮肤检测的功能&#xff0c;在传统的处理中经历了反复挣扎&#xff0c;终于要上YOLO了。听过、看过&#xff0c;不如上手体会过~ 1、YOLO是什么&#x…

动手做计算机网络仿真实验入门学习

打开软件 work1 添加串行接口模块&#xff0c;先关电源&#xff0c;添加之后再开电源 自动选择连接 所有传输介质 自动连接 串行线 绿色是通的&#xff0c;红色是不通的。 显示接口。se是serial串行的简写。 Fa是fast ethernet的简写。 为计算机配置ip地址&#xff1a; 为服…

ROS2软件架构全面解析-学习如何设计通信中间件框架

前言 ROS&#xff08;Robot Operating System&#xff09; 2 是一个用于开发机器人应用的软件平台&#xff0c;也称为机器人软件开发工具包 (SDK)。 ROS2是ROS1的迭代升级版本 &#xff0c;最主要的升级点是引入DDS&#xff08;Data Distribution Service&#xff09;为基础的…

Java基础知识(五) -- 枚举、注解和异常

1.枚举(enum) 1.1 概述 枚举对应英文(enumeration, 简写 enum), 枚举是一组常量的集合。枚举属于一种特殊的类&#xff0c;里面只包含一组有限的特定的对象。 1.2 枚举实现方式 自定义类实现枚举 使用 enum 关键字实现枚举 1.3 自定义类实现枚举 1.3.1 概述 ① 不需要提供…

《HelloGitHub》第 105 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 Python、…

MAC系统QT图标踩坑记录

MAC系统QT图标踩坑记录 1. 准备图标1.1 方法一&#xff1a;下载准备好的图标1.2 方法二&#xff1a;自己生成图标1.2.1 准备一个png文件1.2.2 用sips生成不同大小的图片1.2.3 用iconutil生成图标文件 2. 配置图标2.1. 把图标改命成自己想要的名字&#xff0c;如icon.icns&#…

XML解析

一、XML概述 1&#xff0c;什么是XML&#xff1f; XML即为可扩展的标记语言(eXtensible Markup Language)XML是一套定义语义标记的规则&#xff0c;这些标记将文档分为许多部件并对这些部件加以标识 2.XML和HTML不同之处 XML主要用于说明文档的主题&#xff0c;而HTML侧重描…

人工智能知识分享第四天-线性回归

线性回归 线性回归介绍 线性回归概念 线性回归(Linear regression)是利用 回归方程(函数) 对 一个或多个自变量(特征值)和因变量(目标值)之间 关系进行建模的一种分析方式。 注意事项&#xff1a; 1 为什么叫线性模型&#xff1f;因为求解的w&#xff0c;都是w的零次幂&am…

从零开始采用命令行创建uniapp vue3 ts springboot项目

文章目录 1&#xff0c;通过命令行创建uniapp vue3 ts项目2, 创建springboot后台项目3&#xff0c; 联调测试 1&#xff0c;通过命令行创建uniapp vue3 ts项目 ​ 官方通过命令行创建项目的地址&#xff1a;https://zh.uniapp.dcloud.io/quickstart-cli.html ​ 在执行下面操…

ArcGIS JSAPI 高级教程 - 通过RenderNode实现视频融合效果(不借助三方工具)

ArcGIS JSAPI 高级教程 - 通过RenderNode实现视频融合效果&#xff08;不借助三方工具&#xff09; 核心代码完整代码在线示例 地球中展示视频可以通过替换纹理的方式实现&#xff0c;但是随着摄像头和无人机的流行&#xff0c;需要视频和场景深度融合&#xff0c;简单的实现方…

Tabby设计架构介绍

Tabby设计架构介绍 总体架构 tabby是一个开源的代码编写助手&#xff0c;其功能还是比较强大。本文分析了一下它的架构组成。 架构说明 分成3层&#xff1a; 大模型层&#xff1a;主要提供各种类型的大模型。不同时刻需要使用的不同大模型。 服务层&#xff1a;基于大模型提…

EasyExcel(读取操作和填充操作)

文章目录 1.准备Read.xlsx&#xff08;具有两个sheet&#xff09;2.读取第一个sheet中的数据1.模板2.方法3.结果 3.读取所有sheet中的数据1.模板2.方法3.结果 EasyExcel填充1.简单填充1.准备 Fill01.xlsx2.无模版3.方法4.结果 2.列表填充1.准备 Fill02.xlsx2.模板3.方法4.结果 …

“进制转换”公式大集合

咱们都知道十进制是“逢10进1 ”&#xff0c;同理&#xff0c;N进制就是 “逢N进1”。进制其实就这么简单。它的麻烦之处在于各种进制之间的转换。 一、十进制整数转N进制 1&#xff0e;十进制转二进制 除2取余法&#xff1a;连续除以2&#xff0c;直到商为0&#xff0c;逆序…

STM32 高级 物联网通讯之LoRa通讯

目录 LoRa通讯基础知识 常见的3种通讯协议 远距离高速率的传输协议 近距离高速率传输技术 近距离低功耗传输技术 低功耗广域网 采用授权频段技术 非授权频段 LoRa简介 LoRa的特点 远距离 低功耗 安全 标准化 地理定位 移动性 高性能 低成本 LoRa应用 LoRa组…

基于51单片机的教学用自动光学演示装置设计

视频演示效果&#xff1a; 基于51单片机的教学用自动光学演示装置设计 目录&#xff1a; 目录 视频演示效果&#xff1a; 目录&#xff1a; 前言&#xff1a; 一、项目介绍 1.1 项目背景 1.2 项目研究内容 二、相关光学实验理论 2.1 光的反射 2.2 光的折射 2.3 光的漫反射 三、…

YK人工智能(三)——万字长文学会torch深度学习

2.1 张量 本节主要内容&#xff1a; 张量的简介PyTorch如何创建张量PyTorch中张量的操作PyTorch中张量的广播机制 2.1.1 简介 几何代数中定义的张量是基于向量和矩阵的推广&#xff0c;比如我们可以将标量视为零阶张量&#xff0c;矢量可以视为一阶张量&#xff0c;矩阵就是…

百度热力图数据获取,原理,处理及论文应用

目录 0、示例数据1、百度热力图数据日期如何选择1.1、看日历1.2、看天气 2、百度热力图几天够研究&#xff1f;部分文章统计3、数据原理3.1.1 定位都包含哪些数据&#xff1f;3.1.2 ** 这个比较重要&#xff0c;后面还会再次出现。核密度的值怎么理解&#xff1f;**3.1.3 Csv-&…