java 函数式编程 详解_Lambda表达式详解(java8新特性,函数式编程)

在JDK1.8中引入了一个重要的新特性:Lambda表达式。

Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

使用 Lambda 表达式可以使代码变的更加简洁紧凑,在学习Lambda表达式前我们先来思考一下为什么会出现它。

1.为什么会出现Lambda表达式

首先我们思考下在java中如何表示一个值?很简单,定义一个变量,然后赋值

364a40d07402a1c989b0ddf5a2af77a5.png

那么如何表示一段代码块的执行逻辑呢?也很简单,定义一个函数,函数方法体写上对应的执行逻辑

6b07b94c070904753c0b4520e63b63d6.png

可如果我想把这个函数赋予某个变量(aBlockOfCode)并当做入参传递呢?

比如说如此:

6d2e6d7896cb2a0b4b182ca92cba8e4a.png

在Java 8之前,这么做是不合法的。但是Java 8问世之后,利用Lambda特性,就可以做到了,并且Lambda的设计者还很贴心的帮我们简化了这一定义:

22905f904213dd98c54531ccf0044255.png

可以看到,我们非常优雅的把“一块代码”赋给了一个变量。而“这块代码”,或者说“这个被赋给一个变量的函数”,就是一个Lambda表达式。

而这个变量的类型是什么呢?

Java8中,定义了一种新的接口类型: 函数式接口,一个接口函数需要被实现的接口类型,我们叫它”函数式接口“ ,并且还为这个接口定义了一个专属声明 @FunctionalInterface ,在接口上加上该声明代表该接口内只有一个函数需要被实现

0a0aec87414aef895eb7bdc6bff783ac.png

其实我们发现,上述表达式其实通过定义一个借口的实现类,然后实例化也能达到同样的目的,但是代码量上却多了很多。

8fc7a5fde5e366c6048b57af13a2477f.png

这也是Lambda表达式的最直观的作用: 使得代码变得异常简洁。

而且Lambda结合Java8的众多新特性:FunctionalInterface Lib, forEach, stream(),method reference等你会看到这一优势会被无限放大!

2.Lambda表达式的基础语法

Lambda 表达式的2种语法格式如下:

(parameters) -> expression

(parameters) -> {statements;}

以下是lambda表达式的重要特征:

1.可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。

2.可选的参数圆括号:一个参数无需定义圆括号,但0或多个参数需要定义圆括号。

3.可选的大括号: 如果表达式只有一行,那么表达式两边的花括号可以省略 。

4.可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

Lambda 表达式的简单例子

1.多参数的情况

(1). lambda表达式的基本格式为(x1,x2)->{表达式…};

(2).在上式中,lambda表达式带有两个参数,此时参数类型可以省略,但两边的括号不能省

(3)…如果表达式只有一行,那么表达式两边的花括号可以省略 //接受2个带参参数,并返回他们的差值

(int x, String y) -> String.valueOf(x) + y

// 4. 接收2无参参数,返回他们的和

(x, y) -> x – y

2.无参数的情况

参数的括号不能省略, 其他语法同多参数

//创建并启动一个线程

new Thread(()-> System.out.println("hello, i am thread!")).start();

3.一个参数的情况

可以省略参数的括号和类型, 其他语法同多参数

// 接收一个参数,可以省略参数的括号和类型

x -> 2 * x

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

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

3.Java8中提供的常用函数式接口

前面我们说了,为了配合Lambda表达式的使用,Java8中定义了一种新的接口类型: 函数式接口,即一个接口函数需要被实现的接口类型,由 @FunctionalInterface 声明。其实Java为了方便我们的使用,还提供了很多常用函数式接口。

利用函数式接口包:java.util.function

b06cc23fe32277e6228bb07034fbde33.png

常见的有

Function:提供任意一种类型的参数,返回另外一个任意类型返回值。 R apply(T t);

Consumer:提供任意一种类型的参数,返回空值。 void accept(T t);

Supplier:参数为空,得到任意一种类型的返回值。T get();

Predicate:提供任意一种类型的参数,返回boolean返回值。boolean test(T t);

a4810f0ea3e26696c05d5d15ceb557af.png

4.方法引用

Java 8 中还新增了一个关键字“ :: ”我们可以通过 " :: " 关键字来访问类的构造方法,对象方法,静态方法。

演示如下:

1.先自定义一个类

class Demo {

//无参构造

Demo() {}

//有参构造

Demo(String something) {

System.out.println(something);

}

//多参构造

Demo(String something,Integer num) {

System.out.println(something+num);

}

//静态方法

static String startsMethod(String s) {

return String.valueOf(s.charAt(0));

}

//

String methodOne(String s) {

return String.valueOf(s.charAt(s.length()-1));

}

void methodTwo() {

System.out.println();

}

}

2.先定义一个函数式接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tEDdjg5i-1606478057603)(Lambda表达式详解,java8新特性.assets/1606463685803.png)]

接口 IConvert, 传参为类型 F,返回类型 T。

接下来让我们演示通过 ::关键字来进行方法访问。

访问静态方法 IConvert ic1 = Demo::startsMethod;

ic1.convert("静态方法访问");

访问对象方法 IConvert ic2 = new Demo()::methodOne;

ic2.convert("对象方法访问");

访问构造方法 IConvert ic3 = Demo::new;

ic3.convert("构造方法访问");

我们可以这样认为,将接口IConvert当做一个定义好的模板, Demo类中的各个方法当做这个模板的实现,只要Demo中的方法符合 IConvert接口的入参与出参定义,就可以直接将方法赋予模板。

引用于参考:

https://www.zhihu.com/question/20125256/answer/324121308

本文地址:https://blog.csdn.net/weixin_43828467/article/details/110244897

希望与广大网友互动??

点此进行留言吧!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值