java lambda 好处_Java Lambda表达(一)

Java 8 lambda表达式示例

我个人对Java 8发布非常激动,尤其是lambda表达式和流API。越来越多的了解它们,我能写出更干净的代码。虽然一开始并不是这样。第一次看到用lambda表达式写出来的Java代码时,我对这种神秘的语法感到非常失望,认为它们把Java搞得不可读,但我错了。花了一天时间做了一些lambda表达式和流API示例的练习后,我开心的看到了更清晰的Java代码。这有点像学习泛型,第一次见的时候我很讨厌它。我甚至继续使用老版Java 1.4来处理集合,直到有一天,朋友跟我介绍了使用泛型的好处(才意识到它的好处)。所以基本立场就是,不要畏惧lambda表达式以及方法引用的神秘语法,做几次练习,从集合类中提取、过滤数据之后,你就会喜欢上它。下面让我们开启学习Java 8 lambda表达式的学习之旅吧,首先从简单例子开始。

例1、用lambda表达式实现Runnable

我开始使用Java 8时,首先做的就是使用lambda表达式替换匿名类,而实现Runnable接口是匿名类的最好示例。看一下Java 8之前的runnable实现方法,需要4行代码,而使用lambda表达式只需要一行代码。我们在这里做了什么呢?那就是用() -> {}代码块替代了整个匿名类。

// Java 8之前:

new Thread(new Runnable() {

@Override

public void run() {

System.out.println("Before Java8, too much code for too little to do");

}

}).start();

//Java 8方式:

new Thread( () -> System.out.println("In Java8, Lambda expression rocks !!") ).start();

输出:

too much code, for too little to do

Lambda expression rocks !!

这个例子向我们展示了Java 8 lambda表达式的语法。你可以使用lambda写出如下代码:

(params) -> expression

(params) -> statement

(params) -> { statements }

例如,如果你的方法不对参数进行修改、重写,只是在控制台打印点东西的话,那么可以这样写:

() -> System.out.println("Hello Lambda Expressions");

如果你的方法接收两个参数,那么可以写成如下这样:

(int even, int odd) -> even + odd

顺便提一句,通常都会把lambda表达式内部变量的名字起得短一些。这样能使代码更简短,放在同一行。所以,在上述代码中,变量名选用a、b或者x、y会比even、odd要好。

例2、使用Java 8 lambda表达式进行事件处理

如果你用过Swing API编程,你就会记得怎样写事件监听代码。这又是一个旧版本简单匿名类的经典用例,但现在可以不这样了。你可以用lambda表达式写出更好的事件监听代码,如下所示:

// Java 8之前:

JButton show = new JButton("Show");

show.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

System.out.println("Event handling without lambda expression is boring");

}

});

// Java 8方式:

show.addActionListener((e) -> {

System.out.println("Light, Camera, Action !! Lambda expressions Rocks");

});

Java开发者经常使用匿名类的另一个地方是为 Collections.sort() 定制 Comparator在Java 8中,你可以用更可读的lambda表达式换掉丑陋的匿名类。我把这个留做练习,应该不难,可以按照我在使用lambda表达式实现 Runnable 和 ActionListener 的过程中的套路来做。

例3、使用lambda表达式对列表进行迭代

如果你使过几年Java,你就知道针对集合类,最常见的操作就是进行迭代,并将业务逻辑应用于各个元素,例如处理订单、交易和事件的列表。由于Java是命令式语言,Java 8之前的所有循环代码都是顺序的,即可以对其元素进行并行化处理。如果你想做并行过滤,就需要自己写代码,这并不是那么容易。通过引入lambda表达式和默认方法,将做什么和怎么做的问题分开了,这意味着Java集合现在知道怎样做迭代,并可以在API层面对集合元素进行并行处理。下面的例子里,我将介绍如何在使用lambda或不使用lambda表达式的情况下迭代列表。你可以看到列表现在有了一个 forEach() 方法,它可以迭代所有对象,并将你的lambda代码应用在其中。

// Java 8之前:

List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");

for (String feature : features) {

System.out.println(feature);

}

// Java 8之后:

List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");

features.forEach(n -> System.out.println(n));

// 使用Java 8的方法引用更方便,方法引用由::双冒号操作符标示,

// 看起来像C++的作用域解析运算符

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

输出:

Lambdas

Default Method

Stream API

Date and Time API

列表循环的最后一个例子展示了如何在Java 8中使用方法引用(method reference)。你可以看到C++里面的双冒号、范围解析操作符现在在Java 8中用来表示方法引用。

例4、使用lambda表达式和函数式接口Predicate

除了在语言层面支持函数式编程风格,Java 8也添加了一个包,叫做 java.util.function。它包含了很多类,用来支持Java的函数式编程。其中一个便是Predicate,使用 java.util.function.Predicate 函数式接口以及lambda表达式,可以向API方法添加逻辑,用更少的代码支持更多的动态行为。下面是Java 8 Predicate 的例子,展示了过滤集合数据的多种常用方法。Predicate接口非常适用于做过滤。

public static void main(args[]){

List languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp");

System.out.println("Languages which starts with J :");

filter(languages, (str)->str.startsWith("J"));

System.out.println("Languages which ends with a ");

filter(languages, (str)->str.endsWith("a"));

System.out.println("Print all languages :");

filter(languages, (str)->true);

System.out.println("Print no language : ");

filter(languages, (str)->false);

System.out.println("Print language whose length greater than 4:");

filter(languages, (str)->str.length() > 4);

}

public static void filter(List names, Predicate condition) {

for(String name: names) {

if(condition.test(name)) {

System.out.println(name + " ");

}

}

}

输出:

Languages which starts with J :

Java

Languages which ends with a

Java

Scala

Print all languages :

Java

Scala

C++

Haskell

Lisp

Print no language :

Print language whose length greater than 4:

Scala

Haskell

// 更好的办法

public static void filter(List names, Predicate condition) {

names.stream().filter((name) -> (condition.test(name))).forEach((name) -> {

System.out.println(name + " ");

});

}

可以看到,Stream API的过滤方法也接受一个Predicate,这意味着可以将我们定制的 filter() 方法替换成写在里面的内联代码,这就是lambda表达式的魔力。另外,Predicate接口也允许进行多重条件的测试,下个例子将要讲到。

欢迎加入学习交流群569772982,大家一起学习交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值