147. Java Lambda 表达式 - 调用 Lambda 表达式
让我们回到前面提到的 Predicate 示例,并假设我们已经在方法中定义了这个 Predicate。接下来,如何使用它来测试给定的字符串是否确实是长度为 3 呢?
尽管我们使用了编写 lambda 的语法,但需要记住的是,这个 lambda 实际上是 Predicate 接口的一个实例。这个接口定义了一个名为 test() 的方法,该方法接受一个 String 类型的参数,并返回一个布尔值。
下面是一个方法示例:
List<String> retainStringsOfLength3(List<String> strings) {
// 创建 Predicate 实例,通过 lambda 表达式来判断字符串长度
Predicate<String> predicate = s -> s.length() == 3;
List<String> stringsOfLength3 = new ArrayList<>();
// 遍历输入的字符串列表,使用 test 方法判断字符串长度
for (String s : strings) {
if (predicate.test(s)) { // 调用 lambda 表达式实现的 test 方法
stringsOfLength3.add(s);
}
}
return stringsOfLength3;
}
解析:
Predicate<String> predicate = s -> s.length() == 3;这行代码定义了一个Predicate类型的lambda表达式,用于判断字符串的长度是否为3。lambda表达式本质上是Predicate接口的实现,test方法的实现代码就是s.length() == 3。predicate.test(s)在for循环中,每次我们对strings列表中的字符串进行判断时,都会调用Predicate接口中的test方法,而这个方法的实现实际上就是我们定义的 lambda 表达式。
重点:
调用 lambda 时,实际是在调用接口 Predicate 中的抽象方法 test(),而该方法的实现就是我们提供的 lambda 表达式代码。
更简洁的写法
虽然上面的代码已经可以正常工作,但有更简洁的方式来利用 lambda 和 Java 8 中的新特性,结合流式操作来简化代码:
List<String> retainStringsOfLength3(List<String> strings) {
return strings.stream()
.filter(s -> s.length() == 3) // 使用 lambda 表达式进行过滤
.collect(Collectors.toList());
}
这里我们使用了 Java 8 中的 Stream API,通过 filter 方法直接过滤出符合条件的字符串。filter 方法的参数就是我们之前写的 Predicate 类型的 lambda表达式。
总结:
每次编写 lambda 表达式时,您都可以调用该 lambda 实现的接口中定义的任何方法。调用抽象方法时,实际上会执行 lambda 本身的代码,而调用 default 方法时,执行的是接口中提供的代码。
注意:
lambda无法覆盖接口中的default方法,因为default方法已经有了具体实现,而lambda是用来实现接口的抽象方法的。lambda表达式本质上是对接口抽象方法的实现。
这样,我们就可以清楚地理解 lambda 表达式如何在实际代码中被调用,以及如何简化我们的代码。