JAVA8新特性-lambda表达式

傷城~ 2024-04-17 20:35 240阅读 0赞

摘要

一篇让你搞懂lambda表达式、函数式接口、方法引用、Optional这些JAVA8的新特性及相互间关系。下图是本文的内容概要
在这里插入图片描述

函数式接口(Functional Interface)

如果一个接口的定义带有@FunctionanlInterface注解,它就是函数式接口。但其实函数式接口不一定非要带这个注解,只要满足一个条件:只有一个抽象的方法。

注意:静态方法,默认方法和覆盖了Object的方法都不算抽象方法

我们来定义一个函数式接口:

  1. @FunctionalInterface
  2. public interface Counter {
  3. @Override
  4. boolean equals(Counter c);
  5. public static String toString(Counter c);
  6. public int count();
  7. }

这是计数器接口只有一个计数方法count()是抽象方法

JDK 内置的函数函数式接口方法

1,Consumer
T为输入参数类型,执行某个动作但无返回值,例如

  1. Consumer<String> print = (x)-> {
  2. System.our.println(x);
  3. }

等号前是函数式接口print的定义,等号后就是lambda表达式,这里可以先透漏下lambda表达式的类型就是函数式接口,后面会说明.

2,Supplier
无输入,返回类型是T

3,Predicate
T为输入类型,返回boolean

4,Function
T为输入类型,R为返回值类型

5, BinaryOperator
输入参数有两个,类型都是T,返回值类型也是T,常见用于reduce操作

JDK内置函数式接口的其他常见的还有Runable, Callable,Comparator

lambda表达式(Lambda Express)

  1. () => System.out.println("This is a lambda express");

上面就是个简单的lambda表达式,上文中看到它是可以被赋值给一个变量的。这个变量的类型是函数式接口,而Lambda表达式本身就是函数式接口中定义的那个唯一的抽象方法的实现。

lambda表达式最直观的作用就是使代码非常简洁,有两个场景非常适合使用lambda表达式

1, 函数式接口的实现只需要用到一次

  1. public void testMethod(Printer<String> printer, String content){
  2. printer.print(content);
  3. }

假设testMethod方法作用是使用接口printer打印第二个参数中字符串.

如果是JAVA7首先必须定义好这个接口的实现类,然后在用到接口方法的时候,需要先创建实现类然后才能调用方法。

  1. // java7
  2. // 必须先定义好实现类
  3. public class PrinterImpl implements Printer {
  4. @Override
  5. public void print(String s){
  6. System.our.println(s);
  7. }
  8. }
  9. // 先创建实现类实例,再完成调用
  10. Printer printer = new PrinterImpl();
  11. testMethod(printer, "hello");

在JAVA8 中使用lambda表达式就简洁多了

  1. // java8
  2. testMethod((x)->System.out.println(x), "hello");

而且最重要的是:如果接口实现只需要用一次,你的项目中可以省去一个类。

2, 与forEach, Stream API及方法引用结合使用

假设有如下学生类定义

  1. public class Student {
  2. private String firstName;
  3. private String lastName;
  4. private int age;
  5. // 省略getter和setter方法
  6. }

现有几个学生,需要找出firstName以字母M开头的并打印

  1. List<Student> superStudents = Arrays.asList(
  2. new Student("Huateng","Ma", 4);
  3. new Student("Yun","Ma", 5);
  4. new Student("SK", "Ma", 6);
  5. new Student("Qiangdong", "Liu", 4)
  6. );
  7. //notice
  8. superStudents.stream().filter(s->s.getFirstName.startWith("M")).forEach(System.out::print);

看//notice下面那句是否非常简洁优雅。你可能现在不明白stream是什么,还有forEach里的表达式是怎么回事。没关系,往下看就知道了。

方法引用(Method References)

上个实例代码中, System.out::print就是方法应用的写法,它可以进一步简化lambda表达式.
可以看到,你只需要使用方法的名字就行,具体的调用会交给函数式接口处理。除了普通方法,构造器方法和静态方法也可以使用方法引用。

1, 构造器方法引用

格式: Class::new,调用默认构造器

2, 静态方法引用

格式: Class::static_method

3,普通方法引用

格式1:Class::method,方法不能带参数
格式2:instance::method

Optional

最后介绍下空指针异常的大杀器Optional.它单独使用时简化代码效果不明显,需要和lambda表达式配合使用。比如下面几种常见写法:

1, 若存在,执行动作

  1. // 假设stuOpt是Optional包装的Student对象
  2. stuOpt.ifPresent(doSomething())

2,若存在,则返回被包装对象,否则返回空

  1. return stuOpt.orElse(null)

3, 若存在,则返回被包装对象,否则执行方法获取

  1. return stuOpt.orElseGet(()->fetchNew())

4, 嵌套null检查

  1. return stuOpt.map(s->s.getSchool()).map(school->school.getPresent()).orElse(null);

总结

lambda表达式可以使代码异常简洁,结合方法引用可以进一步简化代码。lambda表达式可被赋值给函数式接口,它本身就是函数式接口中抽象方法的实现。lambda表达式结合Optional使用可以简化对null的处理。

至于Steam API的介绍,参考Stream API概念及用法详解

发表评论

表情:
评论列表 (有 0 条评论,240人围观)

还没有评论,来说两句吧...

相关阅读

    相关 JAVA8特性-lambda表达式

    摘要 一篇让你搞懂lambda表达式、函数式接口、方法引用、Optional这些JAVA8的新特性及相互间关系。下图是本文的内容概要 ![在这里插入图片描述][w...

    相关 Java 8特性lambda表达式

    lambda 表达式是 java 8th 给我们带来的几个重量级新特性之一,借用 lambda 表达式可以让我们的程序设计更加简洁。 一. 行为参数化 行为参数化简单的说就