java表达式特点_再来看看Java8的新特征——lambda表达式

fb6ade6eef3dc96538dafd7565043169.png

什么是lambda表达式?

可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。

比如说new一个Thread的传统写法如下

Thread t = new Thread(new Runnable() {

public void run(){

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

}

});

那么利用lambda表达式的写法就是

Thread t = new Thread(() -> System.out.println("Hello world"));

->左边的就是参数列表,->右边的就是函数主体

函数式接口

为什么@FunctionalInterface注解修饰的类只能有一个抽象函数

查看Java8的源码,被@FunctionalInterface修饰的函数叫做函数式接口,例如Predicate,这些类往往只有一个抽象函数,那是因为“Lambda表达式理解为简洁地表示可传递的匿名函数”,直接使用的匿名函数的时候没有指定函数名称,所以,如果有两个及以上抽象函数的时候,虚拟机就不知道你要执行哪个方法了,如上例中Runnable的run()方法,我们参数列表部分只使用了(),并没有声明调用的函数名。

JDK自带的函数式接口都在java.util.function路径下,常用的有

public interface Predicate{

boolean test (T t);

}

public interface Consumer {

void accept(T t);

}

public interface Function {

R apply(T t);

}

...

函数式接口使用示例

//源码部分

@FunctionalInterface

public interface Predicate{

boolean test(T t);

}

//方法构建

public static List filter(List list, Predicate p) {

List results = new ArrayList<>();

for(T s: list){

if(p.test(s)){

results.add(s);

}

}

return results;

}

//使用示例,通过filter方法,筛选出String不为空的数据

Predicate nonEmptyStringPredicate = (String s) -> !s.isEmpty();

List nonEmpty = filter(listOfStrings, nonEmptyStringPredicate);

其他函数式接口使用示例

d573ead0555180de979e445e1a87a4ea.png

为什么lambda表达式使用局部变量必须是final的?

lambda表达式主体部分除了使用参数列表的数据,还可以使用lambda表达式外部的局部变量,但是这些局部变量只能声明一次,否则就会报错。

int portNumber = 1337;

//此时会报错,portNumber必须被final修饰

Runnable r = () -> System.out.println(portNumber);

portNumber = 31337;

因为lambda表达式主体可看作是匿名内部类,访问外部局部变量是需要final的。从线程的角度来说,就是局部变量是一个线程(假设叫线程A),lambda表达式主体是另外一个线程(线程B),当线程A结束的时候,线程B还要访问线程A的数据,肯定是不行的,所以线程B中的变量实质上不是指向线程A中的变量,而是拷贝了一份出来,所以必须保证拷贝出来的数据是不可以改变的。

方法引用

lambda表达式还有一个非常方便的地方,就是方法引用,可以通过类名::方法名的形式直接使用方法。

例如

//静态方法

Integer::parseInt

//对象的普通方法

String::length

//构造方法

Apple::new

复合lambda表达式的用法

lambda表达式还可以链式调用,同时拥有与或非(negate、and和or)的逻辑判断

//链式调用

inventory.sort(comparing(Apple::getWeight)

.reversed()

.thenComparing(Apple::getCountry));

//非

Predicate notRedApple = redApple.negate();

//与

Predicate redAndHeavyApple =

redApple.and(a -> a.getWeight() > 150);

//或

Predicate redAndHeavyAppleOrGreen =

redApple.and(a -> a.getWeight() > 150)

.or(a -> "green".equals(a.getColor()));

函数复合

Function函数接口提供了两个方法对数据做连续操作,andThen和compose方法。

Function f = x -> x + 1;

Function g = x -> x * 2;

Function h = f.compose(g);

int result = h.apply(1);

//输出3 ==> )(1*2)+1

andThen方法相当于先执行f函数,再执行g函数。

Function f = x -> x + 1;

Function g = x -> x * 2;

Function h = f.andThen(g);

int result = h.apply(1);

//输出4 ==> (1+1)*2

compose方法相当于先执行g函数,再执行f函数。

接下来

接下来会梳理流的相关知识点、和其他(注入Optionnal、新的时间工具、默认方法等知识)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值