java中的lambda表达式
来源:互联网 发布:男女合唱网络流行歌曲 编辑:程序博客网 时间:2024/05/29 23:48
lambda表达式在jdk1.8中被加入进来,给古老的java语言注入了新鲜的活力。先说句题外话,我看了一些早期spark(大数据计算框架)的书,当时spark支持scala,java和python,其中,spark的很多api(如map,flatmap,filter等)在scala和python中都可以使用lambda表达式轻松搞定,很简洁,无奈的java使用匿名内部类,冗长的包名,复杂的嵌套,最内侧的方法可能只是一个简单的表达式,看着实在是别扭。自从java8支持了lambda表达式以后,不仅使java增加了新的语言特性,还因此新增了一些其他api库,如并行编程和stram api等。本篇博客主要讨论lambda表达式的语法和使用,关于并行编程和stream api会在以后的博客中专门讨论。
在java中使用lambda表达式的话,需要注意两点:一个是lambda表达式本身的语法,另一个是函数式接口(functional interface)。
labmda语法
java8新增了一个操作符->
,称为lambda操作符或箭头操作符,它将lambda表达式分为两部分,箭头之前的是参数,箭头之后的是动作。例如,
(Integer n1,Integer n2) -> n1 + n2
这个就相当于
Integer method(Integer n1, Integer n2) { return n1 + n2;}
参数的类型可以省略,因为可以推断出来。
(n1,n2) -> n1 + n2
如果只有一个参数的话,圆括号也可以省略,像这样
n1 -> n1 * n1
如果没有参数的话,箭头前面的圆括号是不能省略的,例如:
() -> 5; //固定返回5
箭头符号右侧是动作,除了我们看到的这种单行的形式之外,还可以声明一个代码段作为动作,像下面这样
n -> { return n * n;}
这个代码段可以写的很长很长。如果有返回值的话,需要使用return
语句返回。
functional interface
在java中,lambda表达式一定要结合functional interface来使用,functional interface是指一个只包含一个抽象方法的接口。下面来看一个例子。这是一个functional interface:
public interface MyInterface { int doSomething(int number);}
然后,声明一个此类型的lambda表达式
MyInterface myInterface = n -> n + 1;int number = myInterface.doSomething(5);
可以理解为,lambda表达式从语法上简化了匿名内部类,但底层的实现好像都一样。再来看一个两个参数的例子。
public interface MyInterface2 { int doSomething(int num1, int num2);}
下面来声明一个该类型的lambda表达式
MyInterface2 myInterface2 = (n1, n2) -> n1 + n2;number = myInterface2.doSomething(5, 9);
输出的结果是14。
我还可以使用一个更加复杂的lambda表达式
myInterface2 = (n1, n2) -> { int max = 0; if (n1 > max) { max = n1; } if (n2 > max) { max = n2; } return max;};
这个lambda表达式返回n1,n2和0中较大的一个。
myInterface2.doSomething(10, 20); // return 20myInterface2.doSomething(-10, -20); // return 0
变量捕获
说到lambda表达式,有一个话题是绕不开的,就是闭包。但这个问题在java中被简化了好多。这个问题可以分为两种情况来讨论:
1. lambda表达式可以访问到所在的类中定义的字段(filed),也可以修改这个字段。
2. lambda表达式可以访问到外层代码块(enclosing scope)中定义的本地变量(local varable),但不能修改他们,并且,如果一个本地变量在lambda表达式中被读取的话,这个变量必须是final或事实上final(变量赋值以后就不能再任何地方再修改了)。
看下面的例子
public class App { private int filed1 = 10; void method1() { int varable1 = 10; MyInterface myInterface = n -> { filed1 += 2; //可读取,可修改 int m = varable1; //可读取 //varable1 += 2; //不可修改 return 1; }; //varable1 += 2; //已经在lambda表达式中被读取了,就是final了,不能被修改。 }}
在这个例子中,filed1
是一个字段,所以在lambdda表达式中可读可写,而varable1
是一个本地变量,在lambda表达式中只能被读取而不能被修改,并且,一旦这个变量在lambda表达式中被读取了,那么在任何地方就不能被修改了。
方法引用
lambda表达式的本质是一个匿名方法,但如果有一个方法的签名(参数列表和返回值)和functional interface的签名一样并且逻辑正好是你需要的,那么你可以使用方法引用的方式来将它赋值给你的functional interface,而无需再编写lambda表达式。方法引用是jdk1.8中被引入的新语法,它跟lambda表达式息息相关,从字面意思来看,方法引用指向一个方法,但不调用它。其实这个特性在很多编程语言中都已经支持了,java也终于支持了。像其它编程语言一样,加括号就是调用方法,不加括号就是引用方法。
方法引用可以引用四种类型的方法,分别是:静态方法,实例方法,泛型方法,构造方法,引种每种方法的语法有略有区别。下面分别看个例子。下面这个类包含三个方法,对应前三种类型
public class MyClass { public int instanceMethod(int number) { return number * 2; } public static int staticMethod(int number) { return number * 2; } public <T extends Number> int genericMethod(T param) { return param.intValue() * 2; }}方法引用的操作符是两个冒号`::`,这也是一个新的操作符。
引用静态方法
引用静态方法的语法是ClassName::methodName
myInterface = MyClass::staticMethod;myInterface.doSomething(5);
引用实例方法
应用实例方法的语法是instance::methodName
MyClass myClass = new MyClass();myInterface = myClass::instanceMethod;myInterface.doSomething(5);
应用泛型方法
MyClass myClass = new MyClass();myInterface = myClass::<Integer>genericMethod;myInterface.doSomething(5);
引用构造方法
引用构造方法的语法是ClassName::new
构造方法的返回值是它所在的类的类型。下面编写一个functional interface和一个构造函数。先来一个类和它的构造函数
public class Foo { String msg1, msg2; public Foo(String msg1, String msg2) { this.msg1 = msg1; this.msg2 = msg2; }}
在来一个functional interface
interface FooInterface { Foo fooMethod(String m1, String m2);}
这个里面的fooMethod的返回值是Foo,参数列表是两个String对象,与Foo类的构造函数的签名一致。下面是引用这个构造方法的方式
FooInterface fooInterface = Foo::new;Foo fooObj = fooInterface.fooMethod("hello", "world");
- java中的->:Lambda表达式
- java中的Lambda表达式
- java中的lambda表达式
- Java中的Lambda表达式
- Java中的Lambda表达式
- java中的lambda表达式
- Java 8中的Lambda表达式
- Java 8中的 Lambda表达式
- Java 8 中的 Lambda 表达式
- Java 8中的 Lambda表达式
- Java 8中的 Lambda表达式
- Java 8中的 Lambda表达式
- lambda表达式-java中的应用
- Java SE8 Lambda 基础入门---lambda表达式中的异常处理
- java中的内部类和Lambda表达式
- Java中的集合转换(lambda表达式)
- C#中的Lambda表达式
- C++ 中的 Lambda 表达式
- Mtk WIFI常用调试命令
- Solr之集群安装-yellowcong
- Android7.0 MTK方案 静默安装和卸载
- Audio Codec的必要性
- Redis之key操作
- java中的lambda表达式
- 几张图看懂列式存储&&join 方式
- 全排列
- Android图片加载之Glide使用
- 本地主机与虚拟机连接配置
- Ubuntu 16.04安装有道词典(完全版)
- PAT
- 160个练手CrackMe-033
- Spring MVC 教程,快速入门,深入分析