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

1. Lambda表达式

先看如下代码: 

public class LambdaDemo {
    public static void main(String[] args) {
        // 匿名内部类方式完成
        goSwimming(new Swimming() {
            @Override
            public 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 表达式的基本语法是: 

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

简化匿名内部类

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

传统的匿名内部类方式

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

Lambda 表达式方式

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

Lambda 表达式的形式

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

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

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

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

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

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

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

 3. 函数式接口

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

3.1 什么是函数式接口:

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

3.2 定义函数式接口

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

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

 函数式接口的常见应用

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

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

3.3 自定义函数式接口

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

@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 接口

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 接口

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 接口

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));  // 输出:true
        System.out.println(isEven.test(5));  // 输出:false
    }
}

 Supplier 接口

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. 回调机制:可以使用函数式接口将回调函数作为参数传递给方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值