JDK 8 新增特性:Lambda 表达式

一、

什么是 Lambda 表达式?

        Lambda 表达式是 JDK 8 引入的一种新的语法特性,它允许我们将函数作为参数传递给方法,或者将代码视为数据。Lambda 表达式的基本形式是:

(parameters) -> expression

//或者

(parameters) -> { statements; }

为什么要用Lambda 表达式

  1. 简化代码:Lambda 表达式可以替代匿名内部类,使代码更加简洁。
  2. 函数式编程:Lambda 表达式支持函数式编程,使得 Java 可以更好地处理集合数据。
  3. 提高可读性:通过 Lambda 表达式,代码的可读性得到了显著提升。

 示例:

        假设我们有一个 Person 类,包含 name 和 age 两个属性。我们希望对一个 Person 列表进行排序,并打印出排序后的结果。

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Person {
    String name;
    int age;

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return name + " (" + age + ")";
    }
}

public class LambdaExample {
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
            new Person("Alice", 30),
            new Person("Bob", 25),
            new Person("Charlie", 35)
        );

        // 使用 Lambda 表达式进行排序
        Collections.sort(people, (p1, p2) -> p1.name.compareTo(p2.name));

        // 打印排序后的结果
        people.forEach(System.out::println);
    }
}

        在这个例子中,我们使用 Lambda 表达式 

(p1, p2) -> p1.name.compareTo(p2.name) 作为 Comparator 传递给 Collections.sort 方法,实现了对 Person 列表按名字排序的功能。

二、

使用 Lambda 表达式的前提条件:

        Lambda 表达式只能用于函数式接口(Functional Interface),即只有一个抽象方法的接口。常见的函数式接口包括 RunnableComparatorPredicate 等。

 

Lambda 表达式的书写规则:

  1. 参数列表:如果只有一个参数,可以省略括号 ()。如果没有参数,必须使用空括号 ()
  2. 箭头:使用 -> 将参数列表与 Lambda 体分隔开。
  3. Lambda 体:如果 Lambda 体只有一条语句,可以省略大括号 {} 和 return 关键字。如果有多条语句,必须使用大括号 {} 并明确使用 return 关键字。

Lambda 表达式省略书写的规则:

  1. 类型推断:编译器可以根据上下文推断参数类型,因此可以省略参数类型。
  2. 单个参数省略括号:如果只有一个参数,可以省略括号 ()
  3. 单条语句省略大括号:如果 Lambda 体只有一条语句,可以省略大括号 {} 和 return 关键字。 

 

示例代码:

有参数的 Lambda 表达式:
// 正常书写
Comparator<Person> comparator1 = (Person p1, Person p2) -> {
    return p1.name.compareTo(p2.name);
};

// 省略书写
Comparator<Person> comparator2 = (p1, p2) -> p1.name.compareTo(p2.name);
 无参数的 Lambda 表达式:
// 正常书写
Runnable runnable1 = () -> {
    System.out.println("Hello, Lambda!");
};

// 省略书写
Runnable runnable2 = () -> System.out.println("Hello, Lambda!");

三、

Lambda 表达式底层实现原理(了解即可)

        Lambda 表达式的底层实现依赖于 Java 的 invokedynamic 指令和 MethodHandle 机制。编译器会将 Lambda 表达式转换为一个私有的静态方法,并通过 invokedynamic 指令在运行时动态绑定该方法。

解释:

  1. invokedynamic 指令:这是 Java 7 引入的一种新的字节码指令,用于支持动态语言的运行时绑定。Lambda 表达式利用这个指令在运行时动态绑定方法。
  2. MethodHandle:这是一个类似于反射的机制,但它更加高效和灵活。Lambda 表达式在底层会使用 MethodHandle 来调用生成的静态方法。

        Lambda 表达式在编译时会被转换为一个静态方法,并在运行时通过 invokedynamic 指令动态绑定这个方法,从而实现高效的函数式编程。

四、

Lambda 表达式与匿名内部类的区别

底层实现原理的区别:
  • 匿名内部类:编译器会为每个匿名内部类生成一个新的类文件,并在运行时加载这些类文件。这会导致额外的类加载开销和内存占用。
  • Lambda 表达式:编译器会将 Lambda 表达式转换为一个私有的静态方法,并通过 invokedynamic 指令在运行时动态绑定该方法,避免了生成额外的类文件,从而提高了性能。
书写区别:
  • 匿名内部类:需要显式地实现接口或继承类,代码较为冗长。
  • Lambda 表达式:代码简洁,省略了接口名称和方法名称。
使用条件的区别:
  • 匿名内部类可以用于任何接口或类,不限于函数式接口。
  • Lambda 表达式只能用于函数式接口,即只有一个抽象方法的接口
示例1: 
// 使用匿名内部类实现 Runnable 接口
Runnable runnable1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello, Anonymous Inner Class!");
    }
};
runnable1.run();

// 使用 Lambda 表达式实现 Runnable 接口
Runnable runnable2 = () -> System.out.println("Hello, Lambda!");
runnable2.run();
示例2:

        假设我们有一个 Calculator 接口,包含一个 int calculate(int a, int b) 方法。我们可以使用匿名内部类和 Lambda 表达式分别实现这个接口。

interface Calculator {
    int calculate(int a, int b);
}

public class LambdaVsAnonymous {
    public static void main(String[] args) {
        // 使用匿名内部类实现 Calculator 接口
        Calculator calculator1 = new Calculator() {
            @Override
            public int calculate(int a, int b) {
                return a + b;
            }
        };
        System.out.println("Anonymous Inner Class: " + calculator1.calculate(10, 20));

        // 使用 Lambda 表达式实现 Calculator 接口
        Calculator calculator2 = (a, b) -> a + b;
        System.out.println("Lambda Expression: " + calculator2.calculate(10, 20));
    }
}

总结:       

        看到这里我相信你肯定能感受到,Lambda 表达式在代码简洁性和可读性方面具有明显优势。

掌握jdk8的一些新增特性,对我们是很加分的也能提升技术,提高编程效率,希望对你有帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值