美文网首页
Java8函数式编程(一): Lambda 表达式

Java8函数式编程(一): Lambda 表达式

作者: packet | 来源:发表于2018-07-20 19:01 被阅读0次

Java编程的精髓是面向接口编程,Java8最大变化正在于接口。

  • 默认方法(default method)
  • 函数式接口(functional interface)

默认方法颠覆了必须实现接口中方法的特性。默认方法最大的优点是复用,否则必须定义一层抽象类。
函数式接口由@FunctionalInterface 修饰的接口,关于这个注解,请看JDK文档:

An informative annotation type used to indicate that an interface type declaration is intended to be a functional interface as defined by the Java Language Specification.

什么样的接口才能被注解为函数式接口呢?

Java8接口中的方法可以分为3类:

  1. 抽象方法
  2. 默认方法(接口中实现,由default修饰)
  3. 静态方法(接口中实现,由static修饰)

如果接口中有且只有一个抽象方法,则可以被注解为函数式接口。举几个例子:

java.lang.Runnable
java.util.concurrent.Callable
java.util.Comparator
java.util.function.Predicate<T>
java.util.function.Consumer<T>
java.util.function.Function<T, R>
java.util.function.Supplier<T>
java.util.function.UnaryOperator<T>
java.util.function.BinaryOperator<T>
继续追问:定义函数式接口有什么好处呢?答案是可以隐式地转化为Lambda 表达式。这里就引出了本文标题中的主角——Lambda 表达式。
Lambda 表达式是函数式编程中的一种思想,与命令式编程中的变量不同。普通的编程代表的是数值、指针或者引用,而Lambda表达式表示的是一种行为(抽象为函数)
比如Iterable接口的实现类,经常需要循环遍历,写起来往往需要一个循环块,往往比较啰嗦。Iterable接口里增加了默认方法forEach:

default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

请注意上述方法中的this关键字!!在lambda中,this不是指向lambda表达式产生的那个SAM对象,而是声明它的外部对象。
action表示函数式编程接口Consumer,从代码中可以猜出,Consumer的唯一抽象方法是accept。

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}

比如有一个List,现在要遍历打印其中每一个元素,可以写成:

List<Integer> list = Arrays.asList(0, 1, 2, 3);
Consumer<Integer> consumer = new Consumer<Integer>() {
    @Override
    public void accept(Integer integer) {
        System.out.println(integer);
    }
};
list.forEach(consumer);

看起来还是嗦螺,这时Lambda 表达式就有了用武之地,用它来代替函数式接口的实现类。

Consumer<Integer> consumer = integer -> System.out.println(integer);
list.forEach(consumer);
或者
list.forEach(integer -> System.out.println(integer));
或者
list.forEach(System.out::println);

到这里,可以看出,函数式接口表示一套行为,而函数式接口可以用Lambda 表达式简化,所以Lambda 表达式又被称为匿名函数,或者也可以理解为一段带有输入参数的可执行语句块
函数有几个要素:修饰符,返回值,函数名,参数,方法体。在调用函数的时候需要明确方法名和参数,而使用Lambda 表达式则可以省略方法名。通过几个例子来学习下的写法。

函数的参数需要写在圆括号()里,函数体需要写在花括号{}里。
Lambda 表达式的基本形式是(arg1, arg2 ...)-> { statement1; statement2; ... }
如果函数参数只有一个,则可以省略圆括号。
如果方法体内只有一行语句,则可以省略花括号和return关键字。
当没有参数时,前面的( )一般不能省略。

Runnable noArguments = () -> System.out.println("Hello World");

如果省略前面的( ),则可以写成下面的形式,不过功能非常单一,只能打印换行符。

Runnable noArguments = System.out::println

还有一个闭包问题,就是Lambda 表达式要使用方法内的变量时,需要用final修饰或者没有改变改变过值的变量。

小结:

  1. Java8对接口有哪些改变?
  2. 函数式接口是什么?
  3. Lambda 表达式是什么?怎么写?有哪些常用的?

参考文档:FunctionalInterface (Java Platform SE 8 )

相关文章

  • Java8-函数式编程

    Java8-函数式编程 为什么java8 的Lambda 这么受关注? Java8可以用Lambda表达式很简便的...

  • Java8 - Lambda

    函数式编程在并发和事件驱动编程中优势明显。所以Java8引入了Lambda表达式的概念。 面向对象编程与函数式...

  • Lambda表达式总结

    Lambda表达式总结使用范例以及例子Lambda表达式基础语法函数式接口Lambda练习Java8四大内置函数式...

  • 说说 Java 中的函数式编程

    Java8 提供了以下两种方式,来支持函数式编程。 Lambda 表达式 方法引用 (MethodReferenc...

  • Java8函数式编程之三:函数式接口

    上一篇博客Java8函数式编程之二 : Lambda表达式 - 简书介绍了Lambda表达式,最后也留下了一个问题...

  • Java 函数式接口说明

    整理一下 Java8 之后的重要概念 函数式接口的说明和团队分享,这是函数式编程和 Lambda 表达式的基础。虽...

  • 2019-05-25

    lambda表达式学习第一天 java8已经更新了将近五年,静下心来学习函数式编程 常见的lambda表达式的语法...

  • Lambda表达式基本语法与应用

    Lambda简介 Lambda表达式是Java8中提供的一种新的特性,它支持Java也能进行简单的“函数式编程”,...

  • Kotlin修炼指南(二):lambda表达式的精髓

    lambda表达式是Kotlin函数式编程的一个重要概念,要想掌握函数式编程,就必须熟练掌握lambda表达式,并...

  • 从点滴基础探究Kotlin的独特魅力

    0. 序言 从接触Rxjava了解到函数式编程,从了解函数式编程想起Lambda表达式,从Lambda表达式接触到...

网友评论

      本文标题:Java8函数式编程(一): Lambda 表达式

      本文链接:https://www.haomeiwen.com/subject/vywqmftx.html