开发者社区> 技术小能手> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Java 8 和 Scala 中的 Lambda 表达式

简介:
+关注继续查看
Java8 终于要支持Lambda表达式!自2009年以来Lambda表达式已经在Lambda项目中被支持。在那时候,Lambda表达式仍被称为Java闭包。在我们进入一些代码示例以前,先来解释下为什么Lambda表达式在Java程序员中广受欢迎。
1、为什么使用Lambda表达式
Lambda表达式通常使用在图形用户界面(GUI)的开发中。一般来说,GUI编程将程序行为和事件做连接。比如,当用户按下一个按钮(触发一个事件),你的程序就需要去执行某些行为,可能是将一些数据储存到一个数据存储器中。在Swing中,可以使用ActionListener来实现:
class ButtonHandler implements ActionListener {
	public void actionPerformed(ActionEvent e) {
		//do something
	}
}

class UIBuilder {
	public UIBuilder() {
		button.addActionListener(new ButtonHandler());
	}
}

这个例子表明了 ButtonHandler 类作为一个回调替换的用法。在这里 ButtonHandler 类仅包含 ActionListener 接口定义的 actionPerformed 方法。我们可以使用匿名内部类来简化代码:
class UIBuilder {
	public UIBuilder() {
		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent event) {
				//do something
			}
		})
	}
}

这样代码简洁多了。更仔细的去看代码时,就会发现我们还创建一个只生成一个实例的类,而这个实例也仅仅持有一个独立的方法。这恰好是Lambda表达式所能解决的其中一类问题。
2、Lambda表达式代替函数
一个lambda表达式从字面上讲就是一个函数。它定义了一个函数的输入参数和函数体。Java 8 中的,lambda表达式语法尚未确定,不过大致应该类似这个样子的:
(type parameter) -> function_body

一个具体的例子:
(String s1, String s2) -> s1.length() - s2.length();

这个lambda表达式用来计算两个字符串的长度差。还有一些扩展的语法,比如避免参数的类型定义(我们马上见看到例子)还有使用{和}来支持多行定义。
Collections.sort() 方法是lambda表达的理想例子。它允许我们将字符串按照长度排序:
List<String> list = Array.asList("loooooong", "short", "tiny");
Collections.sort(list, (String s1, String s2) -> s1.length() - s2.length());
> "tiny", "short", "loooooong".

所以,不像现在java必须要求的向sort方法输入一个已经实现的Comparator(比较器)而是传送一个lambda表达式我们就可以得到相同的结果。
3、Lambda表达式代替闭包
lambda表达式有许多有趣的特性。其中之一是,它们是闭包。一个闭包允许函数访问直接词法作用域之外的变量。
String outer = "java 8"
(String s1) -> s1.length() - outer.length()

在例子中,lambda表达式访问了字符串 outer 这个作用域之外定义的变量。对于内联闭包来说这是很难做到的。
4、Lambda表达式也支持类型推论
类型推论是java 7 引入的但它同样适用于lambda表达式。简单来说,类型推论意味着程序员可以在任意一个编译器能够自动推断出类型的地方省略类型定义。
如果类型推论能够应用到前面的排序lambda表达式上,那么它就能写成下面的样子:
List<String> list = Arrays.asList(...);
Collections.sort(list, (s1, s2) -> s1.length()-s2.length());

就像你所见到的一样,参数s1和s2的类型被省略了。因为编译器知道list是一个字符串集合,它知道被用来作为比较器的lambda表达式必定是相同的类型。因此,这个类型不需要显式地声明,即使你有这么做的自由。
类型推论的主要优势就是减少样板代码,如果编译器可以为我们识别类型,为什么我们必须自己定义它们。
5、珍爱Lambda表达式,远离匿名内部类
我们来体会下,为何lambda表达式和类型推论有助于简化我们前面所提到的回调例子:
class UIBuilder {
	public UIBuilder() {
		button.addActionListener(e -> //process ActionEvent e)
	}
}

我们下载直接传送一个lambda表达式进入 addActionListener 方法来代替前面定义的持有回调方法的类。除了减少模板代码和提高可读性以外,它使我们直接表达我们唯一感兴趣的事情:处理事件。
在我们了解lambda表达式更多优势之前,先来看看在Scala中的lambda表达式副本。
6、Scala中的Lambda表达式
在函数式编程中,函数是基本的构造块。Scala融合了java中的面向对象编程和函数式编程。在Scala中,一个lambda表达式是种叫做“函数”或者“函数文本”。Scala中的函数属于一等公民。它们可以被分配给vals或者vars(最终变量或者非最终变量),它们可以作为其他函数的参数,也可以组合成新的函数。
在Scala中一个函数文本写成如下形式:
(argument) => //funtion body

举例来说,前面提到的java 用来计算两个字符串长度差的 lambda 表达式,在Scala中写作如下:
(s1: String, s2 :String) => s1.length - s2.length

Scala中的函数文本也是闭包。它可以访问在直接词法作用域之外定义的变量。
val outer =10
val myFuncLiteral = (y: Int) => y * outer
val result = myFuncLiteral(2)
> 20

这个例子结果是20.
正如你所见,我们将函数文本分配给了变量 myFuncLiteral。
java 8 的lambda表达式和Scala的函数文本在语法和语义上的相似性是十分明显的。从语义上讲它们是相同的,而语法上的唯一不同就是箭头符号(java8 ->, scala =>)和我们没有提到的简化符号。
本文来自云栖社区合作伙伴“开源中国”
本文作者:散装海盗

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Java基础之lambda表达式(JDK1.8新特性)
Lambda表达式允许把函数作为一个方法的参数(函数作为参数传递进方法中)。函数式接口有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为lambda表达式。
0 0
Java 基础入门 | 第二十章 Java Lambda 表达式
Lambda 表达式,Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。使用 Lambda 表达式可以使代码变的更加简洁紧凑。语法lambda 表达式的语法格式如下:(parameters) -
0 0
Java基础篇 - Lambda表达式
Java基础篇 - Lambda表达式
0 0
【底层原理之旅—带你看透Lambda表达式的本质】|Java 刷题打卡
【底层原理之旅—带你看透Lambda表达式的本质】|Java 刷题打卡
0 0
Java基础深化和提高 ---- 函数式编程 Lambda
Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内 部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作 中,可以极大地优化代码结构。
0 0
java-接口、lambda表达式
接口(interface) 接口是一个不含任何成员变量的抽象类 接口中所有方法必须为public 接口中不能定义成员变量,但是可以定义为一个常量(类型为public static final) 不能用new来实例化一个接口,但是允许定义一个接口变量 接口变量必须引用实现了该接口的类对象 同一个类可以同时实现多个接口 接口可以定义default方法,该方法提供了一个默认的实现,实现该接口时可以按需重写该方法 接口中的默认方法可以调用其他任意方法 java-SE8后允许接口定义静态方法 public class InterfaceTest implements Test{ public
0 0
Java Lambda 解析和使用技巧
lambda 是包着一个函数的对象 lambda 表达式非常简洁优雅。是把动态语言的特性嫁接到静态语言的一个典范。 在 java 中,我更加愿意认为 lambda 实际上是是包着一个函数的对象,我们在使用 lambda 表达式的时候,实际上定义了一个闭包的函数对象,这是 lambda 最大的意义所在。在过去,我们在函数之间传递一个函数,必须手动把它包装成类的对象,并用接口加以规范。现在,我们可以直接用 lambda 自动生成一个这样的对象。 如果你用过 Javascript/Python,你可以把刚刚定义的函数当做对象传给别的函数。现在,你用 lambda 也可以在 java 的里面传参时
0 0
万字长文详解Java lambda表达式
详细介绍java lambda的各种使用方式以及lambda的实行原理和序列化原理
0 0
Java 笔记-基础篇-Lambda表达式方法引用
Java 笔记-基础篇-Lambda表达式方法引用
0 0
+关注
技术小能手
云栖运营小编~
文章
问答
文章排行榜
最热
最新
相关电子书
更多
JAVA 应用排查全景图
立即下载
Java工程师必读手册
立即下载
Java应用提速(速度与激情)
立即下载