java高级语法_Java高级语法2:Lambda表达式

Lambda表达式

函数式编程思想概述

面向对象过分强调“必须通过对象的形式来做事情”,而函数式思想则尽量忽略面向对象的复杂语法--强调做什么,而不是以什么形式做

传递一段代码--这才是我们真正的目的。Lambda表达式是JDK1.8中最重要的新特性,它打开了函数式Java开发的大门

使用Lambda表达式实现多线程

new Thread(()->{System.out.println("新线程创建了")};).start();

匿名内部类的好处和弊端

好处:可以帮助我们省去实现类的定义

弊端:匿名内部类的语法太复杂了

Lambda表达式适用的情况

无参数

无返回值

代码块

在这样的情况下,用Lambda表达式更加简单

Lambda表达式的格式

Lambda表达式由参数、箭头、代码三部分组成

(参数类型 参数名称)->{代码语句}

实例

实例一:

题外话:用泛型构造sort函数中的Comparator

ace677e740b68df54ccc30f61c813860.png

这里使用Lambda表达式可以简化:

Arrays.sort(arr,(Person o1,Person o2)->{

return o1.getAge()-o2.getAge();

});

实例二

有参数有返回值的情况

57ea5faf5ab02a2998baa513ac13e0b1.png

Lambda表达式中,凡是可以根据上下文推导得知的信息,都可以省略

小括号内参数的类型可以省略

如果小括号只有一个参数,则小括号和类型可以省略

如果大括号只有一个语句,则无论是否有返回值,大括号、return和语句分句都可以省略(注意这里,要是省略的话,括号、return和分号必须一起省略

举个类似的例子:

47d7626a7ec3ccbe27f847f91da702eb.png

下面举一些省略的例子

8275ff6ad17b8f4c8409365858528301.png

efa3c194abfc1a88673a8ca0d4cbf07c.png

上面那个例子中,参数类型、大括号、return和分号都省略了

lambda表达式的使用前提

cd1a6e5d81dd5ee53b35d0c18ae82a5a.png

这也可以理解,如果接口中的方法不止有一个,编译器在判断lambda表达式对应的到底是哪一个方法时就很困难

有且仅有一个抽象方法的接口,叫做函数式接口

关于Lambda表达式的详细内容,参见https://segmentfault.com/a/1190000009186509

![1568038836654](https://user-images.githubusercontent.com/36098426/67142195-025a4f80-f296-11e9-8401-904c4245f389.png)

>空括号用于表示一组空的参数。例如 `() -> 42`。

>

>当有且仅有一个参数时,如果不显式指明类型,则不必使用小括号。例如 `a -> return a*a`。

Lambda表达式的应用:

>线程可以初始化如下:

>

>

>

>```

>// Old way

>new Thread(new Runnable() {

> @Override

> public void run() {

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

> }

>}).start();

>

>// New way

>new Thread(

> () -> System.out.println("Hello world")

>).start();

>```

>

>事件处理可以用 Java 8 使用 Lambda 表达式来完成。以下代码显示了将 `ActionListener` 添加到 UI 组件的新旧方式:

>

>```

>// Old way

>button.addActionListener(new ActionListener() {

> @Override

> public void actionPerformed(ActionEvent e) {

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

> }

>});

>

>// New way

>button.addActionListener( (e) -> {

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

>});

>```

>

>## 6.3 遍例输出(方法引用)

>

>输出给定数组的所有元素的简单代码。请注意,还有一种使用 Lambda 表达式的方式。

>

>```

>// old way

>List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);

>for (Integer n : list) {

> System.out.println(n);

>}

>

>// 使用 -> 的 Lambda 表达式

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

>

>// 使用 :: 的 Lambda 表达式

>list.forEach(System.out::println);

>```

>

>## 6.4 逻辑操作

>

>输出通过逻辑判断的数据。

>

>```

>package com.wuxianjiezh.demo.lambda;

>

>import java.util.Arrays;

>import java.util.List;

>import java.util.function.Predicate;

>

>public class Main {

>

> public static void main(String[] args) {

> List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);

>

> System.out.print("输出所有数字:");

> evaluate(list, (n) -> true);

>

> System.out.print("不输出:");

> evaluate(list, (n) -> false);

>

> System.out.print("输出偶数:");

> evaluate(list, (n) -> n % 2 == 0);

>

> System.out.print("输出奇数:");

> evaluate(list, (n) -> n % 2 == 1);

>

> System.out.print("输出大于 5 的数字:");

> evaluate(list, (n) -> n > 5);

> }

>

> public static void evaluate(List list, Predicate predicate) {

> for (Integer n : list) {

> if (predicate.test(n)) {

> System.out.print(n + " ");

> }

> }

> System.out.println();

> }

>}

>```

>

>运行结果:

>

>```

>输出所有数字:1 2 3 4 5 6 7

>不输出:

>输出偶数:2 4 6

>输出奇数:1 3 5 7

>输出大于 5 的数字:6 7

>```

>

>## 6.4 Stream API 示例

>

>`java.util.stream.Stream`接口 和 Lambda 表达式一样,都是 Java 8 新引入的。所有 `Stream` 的操作必须以 Lambda 表达式为参数。`Stream` 接口中带有大量有用的方法,比如 `map()` 的作用就是将 input Stream 的每个元素,映射成output Stream 的另外一个元素。

>

>下面的例子,我们将 Lambda 表达式 `x -> x*x` 传递给 `map()` 方法,将其应用于流的所有元素。之后,我们使用 `forEach` 打印列表的所有元素。

>

>```

>// old way

>List list = Arrays.asList(1,2,3,4,5,6,7);

>for(Integer n : list) {

> int x = n * n;

> System.out.println(x);

>}

>

>// new way

>List list = Arrays.asList(1,2,3,4,5,6,7);

>list.stream().map((x) -> x*x).forEach(System.out::println);

>```

>

>下面的示例中,我们给定一个列表,然后求列表中每个元素的平方和。这个例子中,我们使用了 `reduce()` 方法,这个方法的主要作用是把 Stream 元素组合起来。

>

>

>

>```

>// old way

>List list = Arrays.asList(1,2,3,4,5,6,7);

>int sum = 0;

>for(Integer n : list) {

> int x = n * n;

> sum = sum + x;

>}

>System.out.println(sum);

>

>// new way

>List list = Arrays.asList(1,2,3,4,5,6,7);

>int sum = list.stream().map(x -> x*x).reduce((x,y) -> x + y).get();

>System.out.println(sum);

>```

Lambda表达式和匿名类之间的区别

>- `this` 关键字。对于匿名类 `this` 关键字解析为匿名类,而对于 Lambda 表达式,`this` 关键字解析为包含写入 Lambda 的类。

>- 编译方式。Java 编译器编译 Lambda 表达式时,会将其转换为类的私有方法,再进行动态绑定。

双冒号(::)操作符

82a0fd402639192f64e8e8da9b73a14d.png

函数式接口

092154b9695337ad15b6eff7a7f1057b.png

语法糖:使用更加方便但是原理不变,便于使用

Lambda不是匿名内部类的语法糖

注意,函数式接口只限制抽象(abstract)方法只能有一个,对于其他类型的方法,比如静态方法、私有方法等没有限制

@FunctionalInterface:检测接口是否为函数式接口,如果是则可以编译成功,否则就会编译失败

函数式接口可以作为方法的参数和返回值使用

参数使用函数式接口

0d542f1a174fc93952d056537d36189d.png

使用匿名内部类和Lambda表达式进行优化:

f2c0bac6a949d65e7822813f33bf00cd.png

Lambda表达式的延迟执行

1db6238608b36600cde419dde82e2e80.png

b68421cec04ec51baf2ec8c3c3715b96.png

81e1b365cd0a6044dacd9ac5f87d55cb.png

存在的问题:

504d4d8e3b9c2ae1f4ed4c472a743474.png

使用Lambda表达式进行优化:

定义函数式接口

package jd;

/*

*@author JiaDing

*/

@FunctionalInterface

public interface MessageBuilder {

public abstract String builderMessage();

}

调用函数式接口

package jd;

/*

* Lambda表达式的特点:延迟加载

* Lambda表达式的前提:存在函数式接口

*/

public class Jd {

// 定义一个显示日志的方法,方法的参数传递日志的等级和MessageBuilder接口

public static void showLog(int level, MessageBuilder mb) {

if (level == 1) {

System.out.println(mb.builderMessage());

}

}

public static void main(String[] args) {

String msg1 = "Hello";

String msg2 = "World";

String msg3 = "Java";

showLog(1, () -> {

// 返回一个拼接好的字符串

return msg1 + msg2 + msg3;

});

}

}

db37bf4fcf576d7af0371f71e3a841dd.png

这里和直接传递参数相比的区别在于,这里实际上是实现了函数式接口中的方法并在方法的return中返回拼接,如果条件不满足,那么这个方法就不会被调用,字符串自然也不会拼接了

实例1:

bf80ca40ca7ba327b4d1c6e4b681d489.png

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值