当前位置: 首页 > 图灵资讯 > 技术篇> Java语法的双刃剑—Lambda表达式

Java语法的双刃剑—Lambda表达式

来源:图灵教育
时间:2023-04-07 10:22:37

Lambda表达式作为Java SE 8中一个重要的新特征,它允许传输函数作为参数(函数编程),可以大大简洁代码Java SE8扮演着重要的角色,扮演着独特的角色。本文详细介绍了java 8家新成员—Lambda表达式。

lambda表达式允许您通过表达式替换功能接口。 lambda表达式与方法相同,它提供了正常的参数列表和使用这些参数的主体(body,可以是表达式或代码块)。lambda表达式也增强了集合库。Java SE 8添加了两个批量操作集合数据的包: java.util.function 包以及 java.util.stream 包。流(stream)就像迭代器一样(iterator),但是附加了许多额外的功能。一般来说,lambda表达式和stream是从Java语言中添加泛型的(Generics)和注解(annotation)以来最大的变化。

Lambda表达式允许您包装行为的单个单元并将其传输给其他代码。如果您想在收集的每个元素上执行特定操作,则可以使用Lambda表达式,当流程完成或过程出现错误。以下功能支持Lambda表达式:

1.方法引用紧凑,易于阅读的lambda表达式,用于有名字的方法。

2.默认方法允许您向库的接口添加新功能,并确保它与为这些接口的早期版本编写的代码二进制兼容。它们是接口方法,default在方法签名的开头有实现和关键字。此外,您还可以在接口中定义静态方法。

使用Java SE Lambda表达式和流的新增强API描述了利用Lambda表达式和流的新增强类别。

最常见的使用以Runnable创建线程为例。

使用匿名内部类创建:

Thread thread = new Thread(new Runnable() {

@Override

public void run() {

System.out.println("do something here");

}

},"thread");

使用创建lambda表达形式:

Thread thread = new Thread(() -> System.out.println("do something here"), "thread");

很容易看出代码的锐减程度很大,看起来也很简单,大大提高了代码的效率。

Lambda表达式语法

基本语法:

参数 -> 表达式

(parameters) -> expression

(parameters) ->{ statements; }

下面是Java lambda表达式的简单例子:

// 1. 不需要参数,返回值为 5

() -> 5

// 2. 接收参数(数字类型)并返回其2倍

x -> 2 * x

// 3. 接受两个参数(数字)并返回它们的差值

(x, y) -> x – y

// 4. 接收两个int型整数,返回他们的和

(int x, int y) -> x + y

// 5. 接受一个 string 对象打印在控制台上,不返回任何值(看起来像返回void)

(String s) -> System.out.print(s)

现在,我们已经知道什么是lambda表达式了。让我们从一些基本的例子开始。我们将看到lambda表达式如何影响我们的编码。 假设有一个玩家Listt ,程序员可以使用 for 语句 ("for 循环")来遍历,在Java SE 8可以转换为另一种形式:

String[] atp = {"Rafael Nadal", "Novak Djokovic",

"Stanislas Wawrinka",

"David Ferrer","Roger Federer",

"Andy Murray","Tomas Berdych",

"Juan Martin Del Potro"};

List players = Arrays.asList(atp);

// 以前的循环方式

for (String player : players) {

System.out.print(player + "; ");

}

// 使用 lambda 表达式和函数操作(functional operation)

players.forEach((player) -> System.out.print(player + "; "));

// 在 Java 8 使用双冒号操作符(double colon operator)

players.forEach(System.out::println);

正如你所看到的,lambda表达式可以将我们的代码缩减到一行。 另一个例子是,在图形用户界面程序中,匿名类别可以用lambda表达式代替。 同样,在实现Runnable接口时也可以这样使用:

// 使用匿名内部类

btn.setOnAction(new EventHandler() {

@Override

public void handle(ActionEvent event) {

System.out.println("Hello World!");

}

});

// 或者使用 lambda expression

btn.setOnAction(event -> System.out.println("Hello World!"));

下面是使用lambdas 来实现 Runnable接口 的示例:

// 1.1使用匿名内部类

new Thread(new Runnable() {

@Override

public void run() {

System.out.println("Hello world !");

}

}).start();

// 1.2使用 lambda expression

new Thread(() -> System.out.println("Hello world !")).start();

// 2.1使用匿名内部类

Runnable race1 = new Runnable() {

@Override

public void run() {

System.out.println("Hello world !");

}

};

// 2.2使用 lambda expression

Runnable race2 = () -> System.out.println("Hello world !");

// 直接调用 run 方法(没有开新线程哦!)

race1.run();

race2.run();

Runnable 的 lambda表达式,使用块格式,将五行代码转换为单行语句。接下来,我们将使用lambdas在下一节对集合进行排序。

使用Lambdas排序集合

Java中,Comparator 类别用于排序和集合。在下面的例子中,我们将根据球员 name, surname, name 长度 还有最后一个字母。和之前的例子一样,我们先用匿名内部类来排序,然后用lambda表达式来简化我们的代码。

第一个例子,我们将根据name对list进行排序。使用旧方法,代码如下:

String[] players = {"Rafael Nadal", "Novak Djokovic",

"Stanislas Wawrinka", "David Ferrer",

"Roger Federer", "Andy Murray",

"Tomas Berdych", "Juan Martin Del Potro",

"Richard Gasquet", "John Isner"};

// 1.1 使用匿名内部基础 name 排序 players

Arrays.sort(players, new Comparator() {

@Override

public int compare(String s1, String s2) {

return (s1.compareTo(s2));

}

});

使用lambdas,同样的功能可以通过以下代码实现:

// 1.2 使用 lambda expression 排序 players

Comparator sortByName = (String s1, String s2) -> (s1.compareTo(s2));

Arrays.sort(players, sortByName);

// 1.3 也可采用以下形式:

Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));

从上面的例子中不难看出Lambda表达式的几个特点:

1.可选类型声明:编译器可以通过上下文推到类型。

2.可选参数括号:如果只有一个参数,则不能定义括号。

3.可选大括号:如果函数体只有一个句子,可以省略大括号。

4.可选返回关键字:如果主体只有一个表达式返回值,编译器将自动返回值。

lambda最重要的是延迟执行。毕竟,如果要立即执行代码,就没有必要在lambda表达式中写作。Lambda表达式不适用于超过3行的逻辑。Lambda表达式的本质虽然看起来很先进,但其实只是一个"语法糖",编译器推断并帮助您将包装转换为常规代码,因此您可以使用更少的代码来实现相同的功能。但建议不要乱用lambda,因为它和一些高级黑客写的代码一样简单,难以理解,难以调试,会给维修人员带来很多工作量。

所以说lambda表达式是java语法中的一把双刃剑,可以使用更少的代码来实现相同的功能,同时也会给代码的维护带来麻烦。这个java家族的新成员合理规范地使用,“千里马常有,伯乐不常有。”,java有很多好的语法,我们想做它们‘伯乐’,要打好java语法的基础,不断求知进取,成为一名人java大师而努力奋斗!