zoukankan      html  css  js  c++  java
  • 死磕Lambda表达式(三):更简洁的Lambda

    我们都是阴沟里的虫子,但总还是得有人仰望星空。——《三体》

    在之前的文章中介绍了Lambda表达式的基本语法正确使用姿势,这次我来介绍一些Lambda更简洁的用法。

    欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

    类型推断

    编译器可以通过函数式接口推断出Lambda表达式的参数类型,所以在编写Lambda表达式时,可以省略参数类型。比如:

    Comparator<Mask> comparator = (Mask o1, Mask o2) -> o1.getBrand().compareTo(o2.getBrand());
    

    就可以简写为:

    Comparator<Mask> comparator = (o1, o2) -> o1.getBrand().compareTo(o2.getBrand());
    

    另外,当Lambda表达式只有一个参数的时候,不仅可以省略参数类型,还可以省略到参数名称两边的括号,比如:

    Predicate<Mask> predicate = (Mask mask) -> mask.getType() == "N95";
    

    就可以简写为:

    Predicate<Mask> predicate = mask -> mask.getType() == "N95";
    

    欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

    方法引用

    什么是方法引用?

    方法引用是Java8中引入的新特性,它提供了一种引用方法而不执行方法的方式,可以让我们重复使用现用方法的定义,做为某些Lambda表达式的另一种更简洁的写法。

    比如前面的例子:

    Comparator<Mask> comparator = (o1, o2) -> o1.getBrand().compareTo(o2.getBrand());
    

    使用方法引用以后,可以简写为:

    Comparator<Mask> comparator = Comparator.comparing(Mask::getBrand);
    

    当你需要方法引用时,目标引用放在分隔符::前,方法的名称放在分隔符::后。比如,上面的Mask::getBrand,就是引用了Mask中定义的getBrand方法。方法名称后不需要加括号,因为我们并没有实际调用它。方法引用提高了代码的可读性,也使逻辑更加清晰。

    欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

    怎么构建方法引用?

    可以构建方法引用的场景的有四种:

    1. 静态方法

    指向静态方法的引用,语法:类名::静态方法名,类名放在分隔符::前,:静态方法名放在分隔符::后。比如:

    (String str) -> Integer.parseInt(str)
    

    使用方法引用以后,可以简写为:

    Integer::parseInt
    

    欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

    2. 内部对象的实例方法

    指向Lambda表达式内部对象的实例方法的引用,语法:类名::实例方法名,类名放在分隔符::前,:实例方法名放在分隔符::后。比如:

    (Mask mask) -> mask.getBrand()
    

    使用方法引用以后,可以简写为:

    Mask::getBrand
    

    欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

    3. 外部对象的实例方法

    指向Lambda表达式外部对象的实例方法的引用,语法:实例名::实例方法名,类名放在分隔符::前,:实例方法名放在分隔符::后。比如:

    String type = "N95";
    Predicate<String> predicate = (String str) -> type.equals(str);
    System.out.println(predicate.test("N95"));
    

    其中,type是一个Lambda表达式外部的局部变量,使用方法引用以后,可以简写为:

    String type = "N95";
    Predicate<String> predicate = type::equals;
    System.out.println(predicate.test("N95"));
    

    如果对于Predicate接口还不熟悉,没关系,以后的文章会介绍到,这里暂且知道它的抽象方法的签名是(T) -> boolean就可以了。

    欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

    4. 构造方法

    指向构造方法的引用,语法:类名::new,类名放在分隔符::前,new放在分隔符::后。比如:

    (String brand, String type) -> new Mask(brand, type)
    

    使用方法引用以后,可以简写为:

    Mask::new
    

    小测试

    看了这么多,是不是摩拳擦掌准备试一试了?我们就来一个小测试:

    1. (char[] array) -> new String(array)
    2. (String str) -> str.length()
    3. (String type) -> mask.setType(type),其中的mask是一个Mask对象的局部变量。
    4. (String str) -> System.out.println(str)

    欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

    请思考片刻…
    .
    .
    .

    .
    .
    .

    宣布答案

    1. 因为(char[] array) -> new String(array)是一个构造方法的Lambda表达式,此种方法引用的语法是:类名::new,所以正确答案是:String::new
    2. 因为(String str) -> str.length()是一个内部对象的实例方法的Lambda表达式,此种方法引用的语法是:类名::实例方法名,所以正确答案是:String::length
    3. 因为(String type) -> mask.setType(type)中的mask是一个Mask对象的局部变量,它是一个包含外部对象的Lambda表达式,此种方法引用的语法是:实例名::实例方法名,所以正确答案是mask::setType
    4. 因为(String str) -> System.out.println(str)是一个静态方法的Lambda表达式,此种方法引用的语法是:类名::静态方法名,所以正确答案是System.out::println

    怎么样?都答对了嘛?

    欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

    《死磕Lambda表达式》系列

    欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

  • 相关阅读:
    bzoj3771 Triple
    【BZOJ-1597】土地购买 DP + 斜率优化
    【BZOJ-1911】特别行动队 DP + 斜率优化
    【BZOJ-3144】切糕 最小割-最大流
    【BZOJ-2095】Bridge 最大流 + 混合图欧拉回路 + 二分
    【BZOJ-3996】线性代数 最小割-最大流
    【BZOJ-1497】最大获利 最大流
    【BZOJ-1500】维修数列 Splay
    【BZOJ-1458】士兵占领 最大流
    【BZOJ-3626】LCA 树链剖分
  • 原文地址:https://www.cnblogs.com/heihaozi/p/12515902.html
Copyright © 2011-2022 走看看