Lambda表达式基础
lambda表达式是JDK8中的新特性,其实这个功能并非不可或缺的,只是它可以起到简化代码,锻炼思维的作用。现在很多教程中对lambda表达式介绍过于简单或是结合了高级特性,让很多第一次接触lambda表达式的程序员有些迷茫,在这篇文章中我会尽力用简练的语言,详细的代码分析,让各位了解到lambda表达式的有趣之处。
基础知识
匿名内部类
匿名内部类就是没有名字的内部类
因为没有名字,所以每个匿名内部类只能使用一次
必须继承一个父类或者实现一个接口
匿名内部类不能定义任何静态成员、方法。
匿名内部类中的方法不能是抽象的;
匿名内部类必须实现接口或抽象父类的所有抽象方法。
匿名内部类访问的外部类成员变量或成员方法必须用static修饰;
interface Printer{
void printstring(String str);
}
//以下为通过匿名内部类接口的实现
Printer aPrinter = new Printer() {
@Override
public void printstring(String str) {
// TODO 自动生成的方法存根
System.out.println(s1);
}
};
Lambda表达式
简介
Lambda表达式是 JDK8 新特性,使用它可以取代绝大多数的匿名内部类,使得代码更加简洁。
对接口的要求
Lambda 规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法。
基础语法
interface Printer{
void printstring(String str);
}
Printer bPrinter = (str)->{System.out.println(str);};
我们可以看到,相比于上面使用匿名内部类的直接实现,使用lambda表达式可以极大地减少代码长度。
函数式接口
-
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
-
函数式接口可以被隐式转换为 lambda 表达式。
-
JDK提供了部分函数式接口
-
我们可以使用JDK提供的函数式接口完成lambda表达式以减少我们的工作量。
在JDK8之后,添加了一个包java.util.function。它包含了很多类,用来支持Java的函数式编程。例如:Predicate,使用其函数式接口以及lambda表达式,可以向API方法添加逻辑,用更少的代码支持更多的动态行为。
–Consumer代表了接受一个输入参数并且无返回的操作
–Predicate接受一个输入参数,返回一个布尔值结果。
–Supplier无参数,返回一个结果。
–Function<T,R>接受一个输入参数,返回一个结果。
–BinaryOperator代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果
以下是有两个传入参数的函数式接口
•BiConsumer<T,U>代表了一个接受两个输入参数的操作,并且不返回任何结果
•BiFunction<T,U,R>代表了一个接受两个输入参数的方法,并且返回一个结果
•BiPredicate<T,U>代表了一个两个参数的boolean值方法
在之后的示例中,我们将会演示如何通过提供的函数式接口运用lambda表达式。
使用lambda表达式完成数组迭代
//forEach的接受传参为Consumer,即传入一个参数,无返回值
//以下为函数原型
//public void forEach(Consumer<? super E> action)
List<String> langStrings = Arrays.asList("C++","JAVA","C#","Python");
langStrings.forEach(n->System.out.println(n));
在本例中我们使用lambda表达式实现了数组的全元素迭代。输出了数组中的全部元素。
下一个例子与此相比会有一些复杂,但我会尝试通过详细的说明,帮助各位理解它。
class pickStrings{
//定义静态方法filter,传参是一个字符串列表以及Predicate
public static void filter(List<String>lans,Predicate<String> conditon){
for (String lan : lans) {
//见说明2
if (conditon.test(lan)) {
System.out.println(lan);
}
}
}
}
public class lambdatest {
public static void main(String[] args) {
List<String> langStrings = Arrays.asList("C++","JAVA","C#","Python",
"PHP","C");
//使用String下方法startwith作为传入参数,过滤列表中字符串
pickStrings.filter(langStrings, str->str.startsWith("C"));
}
}
这个代码块的作用是输出List中所有以“C”开头的元素,即使没有lambda表达式,我们通过迭代也可以完成相应的功能,但是通过这个新特性,我们可以通过简单的代码完成复杂的工作。我将在下面对上方代码进行详细说明
-
静态方法filter接受两个参数,前面我们已经给出,*Predicate()*是接受一个参数,返回一个boolean结果的函数式接口,因此我们采用它作为字符串筛选的“过滤器”。
-
test()方法是Predicate接口中的一个布尔型函数,其作用简单地说就是判别括号内的元素是否满足条件(在本例中判断是否满足传入对象condition的条件)。
至此各位应该都对lambda表达式有了一定了理解,在之后的文章中我还会介绍StreamAPI,以及Stream与lambda结合以期达成更高效的数据处理,欢迎各位持续关注。