[Java基础] Lambda表达式 | 函数式接口

server/2024/11/30 8:12:59/

1. Lambda表达式

先看如下代码: 

java">public class LambdaDemo {public static void main(String[] args) {// 匿名内部类方式完成goSwimming(new Swimming() {@Overridepublic void swim() {System.out.println("铁汁 , 我们去游泳吧....");}});// lambda表达式的方式完成goSwimming(() -> System.out.println("铁汁 , 我们去游泳吧...."));}public static void goSwimming(Swimming swimming) {swimming.swim();}}interface Swimming {public abstract void swim();
}

由上述代码可见使用Lambda表达式代码更少,关注点更加明确

  • lambda表达式可以理解为对匿名内部类的一种简化 , 但是本质是有区别的

  • 面向对象思想 :

    • 强调的是用对象去完成某些功能
  • 函数式编程思想 :

    • 强调的是结果 , 而不是怎么去做

 2. Lambda表达式的使用 

  • 使用前提

    • 必须存在一个接口
    • 接口中有且只有一个抽象方法
  • 格式 : ( 形式参数 ) -> { 代码块 }

    • 形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
    • ->:由英文中画线和大于符号组成,固定写法。代表指向动作
    • 代码块:是我们具体要做的事情,也就是以前我们写的方法体内容

Lambda 表达式的基本语法是: 

java">(parameters) -> expression
  • parameters:输入参数,类似于方法的参数列表,可以有多个参数,且参数类型可以省略,由编译器推断。
  • ->:箭头操作符,用于分隔输入参数和表达式体。
  • expression:Lambda 表达式的实现逻辑,可以是一个简单的表达式或一个代码块。

简化匿名内部类

在没有 Lambda 表达式之前,我们通常使用匿名内部类来实现接口。例如,实现一个没有返回值的 Runnable 接口。

传统的匿名内部类方式

java">Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("Running...");}
};
new Thread(runnable).start();

Lambda 表达式方式

java">Runnable runnable = () -> System.out.println("Running...");
new Thread(runnable).start();

Lambda 表达式的形式

1. 无参数 
java">() -> System.out.println("Hello, World!");

这是一个不接受任何参数且没有返回值的 Lambda 表达式,执行时打印出 "Hello, World!"。

 2. 一个参数
java">x -> x * x;

这是一个接受一个参数 x,并返回其平方的 Lambda 表达式。

3. 多个参数
java">(x, y) -> x + y;
 4. 多个语句

如果 Lambda 表达式包含多个语句,则需要使用大括号 {} 来包含语句,并且可以使用 return 关键字来返回结果。

java">(x, y) -> {int sum = x + y;return sum;
}

 3. 函数式接口

在 Java 中,Lambda 表达式依赖于函数式接口(Functional Interface)来传递行为。

3.1 什么是函数式接口:

  • 只有一个抽象方法需要重写的接口,函数式接口。函数式接口是允许有其他的非抽象方法的存在例如静态方法,默认方法,私有方法。
  • 为了标识接口是一个函数式接口,可以在接口之上加上一个注解: @FunctionalInterface 以示区别
  • 在JDK中 java.util.function 包中的所有接口都是函数式接口

3.2 定义函数式接口

要定义一个函数式接口,你只需要保证接口中有一个抽象方法。你可以使用 @FunctionalInterface 注解来显式标明这是一个函数式接口,虽然这个注解是可选的,但它可以帮助编译器检测是否符合函数式接口的规范。

java">@FunctionalInterface
interface MyFunction {void apply();  // 只包含一个抽象方法
}

 函数式接口的常见应用

Lambda 表达式通常用于函数式接口中。Java 8 提供了许多内置的函数式接口,如:

  • Runnable:用于表示没有输入参数且没有返回值的任务。
  • Consumer<T>:表示接受一个参数并进行处理,没有返回值。
  • Supplier<T>:表示没有参数,返回一个值。
  • Function<T, R>:接受一个参数,返回一个结果。
  • Predicate<T>:接受一个参数,返回一个布尔值结果。
  • UnaryOperator<T>:接受一个参数,返回一个与参数类型相同的结果。
  • BinaryOperator<T>:接受两个相同类型的参数,返回一个与参数类型相同的结果。

3.3 自定义函数式接口

以下是一个简单的函数式接口例子:

java">@FunctionalInterface
interface Greeting {void sayHello(String name);
}public class LambdaExample {public static void main(String[] args) {// 使用 Lambda 表达式实现接口Greeting greet = (name) -> System.out.println("Hello, " + name);greet.sayHello("John");  // 输出:Hello, John}
}

3.4 Java 内置的函数式接口

Consumer 接口

java">import java.util.function.Consumer;public class ConsumerExample {public static void main(String[] args) {// Consumer 接口,接受一个参数并处理Consumer<String> print = (message) -> System.out.println(message);print.accept("Hello, World!");  // 输出:Hello, World!}
}

 Function 接口

java">import java.util.function.Function;public class FunctionExample {public static void main(String[] args) {// Function 接口,接受一个参数并返回一个结果Function<Integer, Integer> square = (x) -> x * x;System.out.println(square.apply(5));  // 输出:25}
}

 Predicate 接口

java">import java.util.function.Predicate;public class PredicateExample {public static void main(String[] args) {// Predicate 接口,接受一个参数并返回一个布尔值Predicate<Integer> isEven = (x) -> x % 2 == 0;System.out.println(isEven.test(4));  // 输出:trueSystem.out.println(isEven.test(5));  // 输出:false}
}

 Supplier 接口

java">import java.util.function.Supplier;public class SupplierExample {public static void main(String[] args) {// Supplier 接口,返回一个结果Supplier<Double> randomValue = () -> Math.random();System.out.println(randomValue.get());  // 输出:一个随机数}
}

3.5 函数式接口的优点

  1. 简洁性:Lambda 表达式允许你使用简单的方式实现函数式接口的抽象方法,避免了冗长的匿名类写法。
  2. 更高效的代码复用:你可以在方法或函数中直接传递行为,而不需要为每个行为编写一个实现类。
  3. 支持函数式编程:Java 引入 Lambda 表达式后,使得 Java 更加支持函数式编程,能够更加灵活地处理数据和逻辑。

函数式接口的常见应用场景

  1. 事件处理:可以使用函数式接口来表示事件处理器或回调函数。
  2. 流处理(Stream API):许多操作(如 map, filter, reduce)都依赖于函数式接口。
  3. 并行计算:可以在并行流处理中使用函数式接口来实现并发任务。
  4. 回调机制:可以使用函数式接口将回调函数作为参数传递给方法。

http://www.ppmy.cn/server/146116.html

相关文章

音视频基础扫盲之视频码率控制策略(CBR、VBR还是ABR)

视频码率控制策略 CBR&#xff08;Constant Bit Rate&#xff09;、VBR&#xff08;Variable Bit Rate&#xff09;和ABR&#xff08;Average Bit Rate&#xff09;是三种常见的比特率控制方式&#xff0c;以视频码率控制为例&#xff0c;视频码率控制策略主要是在保证视频质量…

容器第二天(day039)

1.jq处理json格式数据 使用场景&#xff1a;docker inspect出来的结果是json格式数据 安装&#xff1a;yum install -y jq 用法&#xff1a;docker inspect nginx:alpine |jq .[].GraphDriver.Data.WorkDir 遇到[]&#xff0c;则.[]。 2.容器管理 运行起来的镜像可以成为容…

SQL进阶技巧:非等值连接--单向近距离匹配

目录 0 场景描述 1 数据准备 2 问题分析 ​编辑 ​编辑 3 小结 数字化建设通关指南 0 场景描述 表 t_1 和表 t_2 通过 a 和 b 关联时&#xff0c;有相等的取相等的值匹配&#xff0c;不相等时每一 个 a 的值在 b 中找差值最小的来匹。 表 t_1&#xff1a;a 中无重复值…

Ubuntu-20.04安装 terminator

Ubuntu-20.04安装 terminator sudo apt install terminator 安装成功之后&#xff0c;在ubuntu终端里执行命令 terminator & terminator 窗口分割 基本操作 1. 创建新终端 水平分割&#xff1a;按下 Ctrl Shift E 创建一个新的水平分屏。 垂直分割&#xff1a;按下 Ct…

智能驾驶,车联网,传感器,车载电子集中展示|2025北京自动驾驶展

在这个充满创新与变革的时代&#xff0c;自动驾驶技术已经成为全球汽车产业的焦点之一。“2025北京国际自动驾驶技术展览会”正式开启预定&#xff0c;无疑为全球自动驾驶技术领域的专业人士、企业以及爱好者们提供了一个交流与展示的绝佳平台。此次展览会不仅将展示自动驾驶技…

Mac启动服务慢问题解决,InetAddress.getLocalHost().getHostAddress()慢问题。

项目启动5分钟&#xff0c;很明显有问题。像网上其他的提高jvm参数就不说了&#xff0c;应该不是这个问题&#xff0c;也就快一点。 首先找到自己的电脑名称&#xff08;用命令行也行&#xff0c;只要能找到自己电脑名称就行&#xff0c;这里直接在共享里看&#xff09;。 复制…

VUE3中defineExpose的使用方法

使用 <script setup> 的组件是默认关闭的——即通过模板引用或者 $parent 链获取到的组件的公开实例&#xff0c;不会暴露任何在<script setup>中声明的绑定。 可以通过 defineExpose 编译器宏来显式指定在 <script setup> 组件中要暴露出去的属性 官网传送…

技术总结(四十一)

一、MySQL 索引概述 索引的概念&#xff1a;索引就好比一本书的目录&#xff0c;它能帮助 MySQL 快速定位到表中的数据行&#xff0c;而不用全表扫描。通过创建合适的索引&#xff0c;可以大大提高查询的效率。例如&#xff0c;在一个存储了大量员工信息的表中&#xff0c;如果…