java+lambda+本质_Java8 Lambda本质论

Lambda的本质

需求1. 按照产品的重量进行升序排序

此处使用「匿名内部类」的设计,但掺杂了较多的语法噪声,引入了不必要的复杂度。

Collections.sort(repo, new Comparator() {

@Override

public int compare(Product p1, Product p2) {

return p1.getWeight().compareTo(p2.getWeight());

}

});

使用Lambda表达式,可以进一步消除语法噪声,简化设计。

Collections.sort(repo, (Product p1, Product p2) ->

p1.getWeight().compareTo(p2.getWeight()));

也就是说,Lambda其本质是「匿名内部类」的一种「语法糖」表示,存在如下3个方面的特征:

Anonymous Function:匿名的函数

Passed Around:可作为参数或返回值进行传递,甚至可以自由地存储在变量中

Concise:相对于匿名内部类的样板代码(Boilerplate),Lambda更加简洁漂亮

类型推演

借助编译器「类型推演」的能力,可以进一步简化Lambda表达式。

Collections.sort(repo, (p1, p2) ->

p1.getWeight().compareTo(p2.getWeight()));

Lambda的形式

形式1:(parameters) -> expression

Collections.sort(repo, (p1, p2) ->

p1.getWeight().compareTo(p2.getWeight()));

形式2:(parameters) -> { statements; }

Collections.sort(repo, (p1, p2) -> {

return p1.getWeight().compareTo(p2.getWeight());

});

默认方法

先看看java.util.Collections.sort的实现,其中java.util.Collections是一个典型的「工具类」。

public final class Collectins {

private Collectins() {

}

public static void sort(List extends T> l, Comparator super T> c) {

l.sort(c);

}

}

这样的设计是反OO,为此可以将其sort搬迁至List接口中去。

public interface List extends Collection {

default void sort(Comparator super E> c) {

...

}

...

}

default方法类似于C++的虚函数。从某种意义上看,default的引入使得Java又重新回到了「多重继承」的怀抱,为设计带来了更大的弹性。

为此,设计可重构为更加符合OO的风格。

repo.sort((p1, p2) -> p1.getWeight().compareTo(p2.getWeight()));

方法引用

借助Comparator.comparing的工厂方法,结合「方法引用」可进一步提高代码的可读性。

import static java.util.Comparator.comparing;

repo.sort(comparing(Product::getWeight));

方法引用其本质是具有单一方法调用的lambda表达式的「语法糖」表示。

级联方法

需求2. 按照产品的重量降序排序

repo.sort(comparing(Product::getWeight)

.reversed());

.thenComparing(Product::getCountry));

需求3. 如果重量相同,则按照出厂国的自然序排序

repo.sort(comparing(Product::getWeight)

.reversed()

.thenComparing(Product::getCountry));

深入理解Comparator

有且仅有一个抽象方法的接口,称为「函数式接口」,使用@FunctionalInterface的注解标识。函数式接口中「抽象方法」描述了Lambda表达式的「原型」。

() -> {}也是一个合法的Lambda表达式,与Runnable接口相匹配。

也就是说,一个「函数式接口」可包含如下元素:

Abstract Method:有且仅有一个抽象方法

Default Methods:0个或多个默认方法

Static Methods: 0个或多个静态方法

对照前面的列子,可洞悉Comparator设计的巧妙。

repo.sort(comparing(Product::getWeight)

.reversed());

其中,Comparator就是一个典型的函数式接口。通过「方法级联」设计了一套简单的Comparator的DSL,增强了用户的表达力。

@FunctionalInterface

public interface Comparator {

int compare(T o1, T o2);

default Comparator reversed() {

return Collections.reverseOrder(this);

}

static >

Comparator comparing(

Function super T, ? extends U> extractor) {

return (c1, c2) -> extractor.apply(c1)

.compareTo(extractor.apply(c2));

}

}

其中,Comprator.compring的实现稍微有点复杂。

comparing是一个静态工厂方法,它生产一个Comparator类型的实例;

comparing是一个高阶函数;

接受一个函数:Function super T, ? extends U> extractor

返回一个函数:Comparator

comparing是一个语法糖,结合「方法引用」的机制,极大地改善了用户接口的表达力;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值