Lambda表达式和函数式接口

Lambda表达式和函数式接口

Lambda简介

Lambda表达式是Java 8中引入的一项重要新特性,相当于一个语法糖。它允许将函数作为参数传递给方法或作为返回值返回。Lambda表达式可以简化代码并提高效率,尤其是在处理集合数据时。

语法糖(Syntactic sugar)是指在编程语言中引入的一种语法,它可以使代码更易读、更简洁,但并没有引入新的功能或改变语言的底层机制。语法糖并不会改变语言的语义,只是提供了一种更方便的编写方式。

Lambda表达式的基本语法

Java中的Lambda表达式由以下三个部分组成:

  • 参数列表:用于接收函数的参数。参数列表可以用逗号分隔多个参数,也可以不指定参数。
  • 箭头符号:,用于将参数列表与函数体分隔开来。
  • 函数体:用于定义函数的具体逻辑。

例如,以下代码定义了一个Lambda表达式,用于计算两个数字的平方和:

1
2
3
4
5
6
7
8
9
10
11
12
13

(int x, int y) -> x * x + y * y

//该Lambda表达式可以等效地写成以下形式:

new Interface1() {
@Override
public int test(int x, int y) {
return x * x + y * y;
}
};


函数式接口

函数式接口是一个包含 只有一个抽象方法的接口。

函数式接口:接口中有且只有一个未实现的方法,这个接口就叫函数式接口

如下图:在jdk中提供的检查注解@FunctionalInterface来检查该接口是否为函数式接口

ccf817dbe60b122d35005.png

Lambda表达式与函数式接口的结合

Lambda 表达式可以实现函数式接口,为其提供该抽象方法的具体实现。Java 8 预定义了一些常用的函数式接口,例如:

Predicate:用于测试布尔值
Function:用于将一个值转换为另一个值
Consumer:用于对值执行操作
Supplier:用于生成值

**使用条件:只要是函数式接口就可以用Lambda表达式简化,使代码更加简洁易读。

有一个函数式接口MyInterface,里面有一个方法sum()

1
2
3
4
5
6
7
8
9
10
11
12
13
//一个接口
interface MyInterface {
int sum(int a, int b);
}

//实现
class MyInterfaceImpl implements MyInterface {
@Override
public int sum(int a, int b) {
return a + b;
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//自己创建实现类对象并调用
MyInterface myInterface = new MyInterfaceImpl();
int result = myInterface.sum(1, 2);
System.out.println("自己创建实现对象并调用:" + result);
//创建匿名实现类并调用
MyInterface myInterface1 = new MyInterface() {
@Override
public int sum(int a, int b) {
return a*a + b*b;
}
};
int result1 = myInterface1.sum(1, 2);
System.out.println("创建匿名实现类并调用:" + result1);
//Lambda表达式实现接口并调用 参数列表 + 箭头 + 方法体
MyInterface myInterface2 = (int a, int b) -> {
return a * a + b * b;
};
int result2 = myInterface2.sum(1, 2);
System.out.println("Lambda表达式实现接口并调用:" + result2);


Lambda表达式使用

未来使用函数时接口会比较频繁,当调用某个方法传入参数,这个参数实例是一个接口对象,且只定义了一个方法,就可以直接用Lambda简化写法

比较器的使用

  1. 使用 Lambda 表达式过滤集合
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

    List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

    // 使用匿名内部类过滤包含 "e" 的姓名
    List<String> filteredNames1 = names.stream()
    .filter(new Predicate<String>() {
    @Override
    public boolean test(String name) {
    return name.contains("e");
    }
    })
    .collect(Collectors.toList());

    // 使用 Lambda 表达式过滤包含 "e" 的姓名
    List<String> filteredNames2 = names.stream()
    .filter(name -> name.contains("e"))
    .collect(Collectors.toList());


  2. 使用 Lambda 表达式将字符串转换为大写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

String inputString = "hello";

// 使用匿名内部类将字符串转换为大写
String upperCaseString1 = inputString.toUpperCase(new Function<String, String>() {
@Override
public String apply(String s) {
return s.toUpperCase();
}
});

// 使用 Lambda 表达式将字符串转换为大写
String upperCaseString2 = inputString.toUpperCase(s -> s.toUpperCase());


  1. 使用 Lambda 表达式比较
    当我们使用比较器的时候,可以使用Lambda表达式简化写法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) {
ArrayList<String> names = new ArrayList<String>();
names.add("a");
names.add("b");
names.add("c");
names.add("d");

// 使用匿名内部类将比较
Collections.sort(names,new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});

// 使用 Lambda 表达式比较
Collections.sort(names,(o1,o2)->o1.compareTo(o2));
}

Lambda表达式与普通写法相比,简洁了非常多。 除了Lambda表达式之外,还可以用方法引用来简化写法。如:

1
Collections.sort(names, String::compareTo);