java

位置:IT落伍者 >> java >> 浏览文章

Java8和Scala中的Lambda表达式


发布日期:2024年03月13日
 
Java8和Scala中的Lambda表达式
Java 终于要支持Lambda表达式!自年以来Lambda表达式已经在Lambda项目中被支持在那时候Lambda表达式仍被称为Java闭包在我们进入一些代码示例以前先来解释下为什么Lambda表达式在Java程序员中广受欢迎

为什么使用Lambda表达式

Lambda表达式通常使用在图形用户界面(GUI)的开发中一般来说GUI编程将程序行为和事件做连接比如当用户按下一个按钮(触发一个事件)你的程序就需要去执行某些行为可能是将一些数据储存到一个数据存储器中在Swing中可以使用ActionListener来实现

class ButtonHandler implements ActionListener {

public void actionPerformed(ActionEvent e)

{

//do something

}

}

class UIBuilder {

public UIBuilder() {

buttonaddActionListener(new ButtonHandler())

}

}

这个例子表明了 ButtonHandler 类作为一个回调替换的用法在这里 ButtonHandler 类仅包含 ActionListener 接口定义的 actionPerformed 方法我们可以使用匿名内部类来简化代码

class UIBuilder {

public UIBuilder() {

buttonaddActionListener(new ActionListener() {

public void actionPerformed(ActionEvent event) {

//do something

}

})

}

}

这样代码简洁多了更仔细的去看代码时就会发现我们还创建一个只生成一个实例的类而这个实例也仅仅持有一个独立的方法这恰好是Lambda表达式所能解决的其中一类问题

Lambda表达式代替函数

一个lambda表达式从字面上讲就是一个函数它定义了一个函数的输入参数和函数体Java 中的lambda表达式语法尚未确定不过大致应该类似这个样子的

(type parameter) > function_body 一个具体的例子

(String s String s> slength() slength()

这个lambda表达式用来计算两个字符串的长度差还有一些扩展的语法比如避免参数的类型定义(我们马上见看到例子)还有使用{和}来支持多行定义

Collectionssort()

方法是lambda表达的理想例子它允许我们将字符串按照长度排序

List<String> list = ArrayasList(loooooong short tiny

Collectionssort(list (String s String s> slength() slength())

> tiny short loooooong

所以不像现在java必须要求的向sort方法输入一个已经实现的Comparator(比较器)而是传送一个lambda表达式我们就可以得到相同的结果

Lambda表达式代替闭包

lambda表达式有许多有趣的特性其中之一是它们是闭包一个闭包允许函数访问直接词法作用域之外的变量

String outer = java (String s> slength() outerlength()

在例子中lambda表达式访问了字符串 outer 这个作用域之外定义的变量对于内联闭包来说这是很难做到的

Lambda表达式也支持类型推论

类型推论是java 引入的但它同样适用于lambda表达式简单来说类型推论意味着程序员可以在任意一个编译器能够自动推断出类型的地方省略类型定义如果类型推论能够应用到前面的排序lambda表达式上那么它就能写成下面的样子

List<String> list = ArraysasList(…)

Collectionssort(list (s s> slength()slength())

就像你所见到的一样参数s和s的类型被省略了因为编译器知道list是一个字符串集合它知道被用来作为比较器的lambda表达式必定是相同的类型因此这个类型不需要显式地声明即使你有这么做的自由

类型推论的主要优势就是减少样板代码如果编译器可以为我们识别类型为什么我们必须自己定义它们

珍爱Lambda表达式远离匿名内部类

我们来体会下为何lambda表达式和类型推论有助于简化我们前面所提到的回调例子

class UIBuilder {

public UIBuilder() {

buttonaddActionListener(e > //process ActionEvent e)

}

}

我们下载直接传送一个lambda表达式进入 addActionListener 方法来代替前面定义的持有回调方法的类除了减少模板代码和提高可读性以外它使我们直接表达我们唯一感兴趣的事情处理事件

在我们了解lambda表达式更多优势之前先来看看在Scala中的lambda表达式副本

Scala中的Lambda表达式

在函数式编程中函数是基本的构造块Scala融合了java中的面向对象编程和函数式编程在Scala中一个lambda表达式是种叫做函数或者函数文本Scala中的函数属于一等公民它们可以被分配给vals或者vars(最终变量或者非最终变量)它们可以作为其他函数的参数也可以组合成新的函数

在Scala中一个函数文本写成如下形式

(argument) => //funtion body

举例来说前面提到的java 用来计算两个字符串长度差的 lambda 表达式在Scala中写作如下

(s: String s :String) => slength s

length Scala中的函数文本也是闭包它可以访问在直接词法作用域之外定义的变量

val outer = val myFuncLiteral = (y: Int) => y * outer val result = myFuncLiteral() > 这个例子结果是

正如你所见我们将函数文本分配给了变量 myFuncLiteral

java 的lambda表达式和Scala的函数文本在语法和语义上的相似性是十分明显的从语义上讲它们是相同的而语法上的唯一不同就是箭头符号(java > scala =>)和我们没有提到的简化符号

上一篇:Java并发编程:守护线程

下一篇:Java对话框获取目录、文件路径