早在2014年oracle发布了jdk 8,在里面增加了lambda模块。于是java程序员们又多了一种新的编程方式:函数式编程,也就是lambda表达式。
一、什么是函数式编程
函数式编程(functional programming)或称函数程序设计,又称泛函编程,是一种编程典范,它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象。函数编程语言最重要的基础是λ演算(lambda calculus)。而且λ演算的函数可以接受函数当作输入(引数)和输出(传出值)。比起指令式编程,函数式编程更加强调程序执行的结果而非执行的过程,倡导利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,而不是设计一个复杂的执行过程。
我个人的理解就是创建一个函数就像是写了一个数学式子,y = f(x)只要输入x不变,y的输出就不会改变
二、 Lambda表达式的组成
Lambda 表达式由三个部分组成:第一部分为一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数;第二部分为一个箭头符号:->;第三部分为方法体,可以是表达式和代码块。语法如下
(parameters) -> expression
(int a,int b) -> return a - b;
(parameters) -> { statements; }
(int a) -> {System.out.println("a = " + a);} //打印,无返回值
(int a) -> {return a * a;} //求平方
方法体为代码块,必须用 {} 来包裹起来,且需要一个 return 返回值,但若函数式接口里面方法返回值是 void,则无需返回值。当调用Lambda表达式时,就相当于会返回一个函数式接口的类,这个结果类似于创建匿名内部类实现的。
//此时没有标记@FunctionalInterface
interface Test{
public void test();
}
public static void main(String[] args) {
Test s = () -> System.out.println("haha");
s.test(); //此时会有结果
}
可以看出函数式接口来说@FunctionalInterface并不是必须的, 只要接口中只定义了唯一的抽象方法的接口那它就是一个实质上的函数式接口,就可以用来实现Lambda表达式。 但是,为了能够让人一眼就看出哪些可以用Lambda表达式,都一个标记上@FunctionalInterface。
注意Lambda和匿名类有不同,使用匿名类与 Lambda 表达式的一大区别在于关键词的使用。对于匿名类,关键词 this 解读为匿名类,而对于 Lambda 表达式,关键词 this 解读为写就 Lambda 的外部类。
Lambda 表达式与匿名类的另一不同在于两者的编译方法。Java 编译器编译 Lambda 表达式并将他们转化为类里面的私有函数,它使用 Java 7 中新加的 invokedynamic 指令动态绑定该方法
应用场景
事实上多数可以用匿名内部类的地方都满足Lambda表达式
//创建线程
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("no use lambda");
}
});
//使用Lambda
Thread t2 = new Thread(() -> System.out.println("use lambda"));
用内部迭代取代外部迭代
//外部迭代
List features = Arrays.asList("Java","C++","Python");
for (String feature : features) {
System.out.println(feature);
}
//内部迭代
List features = Arrays.asList("Java","C++","Python");
features.stream.forEach(n -> System.out.println(n));