lambda 表达式是 Java8 的新特性, 虽说都发布很久了, 但是不到万不得已是肯定不会研究这个的, 现在就是那不得不学习的时候了.
本文主要说一下什么 lambda 表达式, Java 中为什么要有 lambda 表达式以及 lambda 表达式的应用.
在 Java 面向对象的思想中, 我们知道函数是不能单独存在的, 函数一般会作为某个对象的功能封装在对象之中, 我们传递参数也不能传递一个函数. 曾经 Java 也为此挣扎过, 我们看下面这段代码, 创建一个线程, 输出一句话.
- new Thread(new Runnable() {
- @Override
- public void run() {
- System.out.println("Hello World !");
- }
- }).start();
有点基础应该都知道这是匿名内部类, 但是你知道的, 真正有效的代码就一行输出语句. 其余代码基本没用, 我们可以反过来想一下, 我们创建线程是为了执行某一个任务, 也就是某一个方法, 那我们为何不直接传入一个方法呢?
按照这个思路, 我们可以这样写伪代码.
new Thread((某某任务)).start();
好了, 现在问题就出现了, 如何去形容这个任务, 或者说在 Java 中如何表示呢? lambda 表达式应运而生.
一个函数, 可能会有入参, 函数要有函数体, 于是就这样定义了 lambda 表达式 "(参数 1, 参数 2)-> { 函数体 }" .
但是吧, 实际使用过程中, 因为参数和函数体的不同, 又有一些变种的写法, 一个 lambda 表达式可以有零个或多个参数, 参数之间用逗号相隔. 空括号代表参数为空.
lambda 表达式的主体可包含零条或多条语句, 如果 lambda 表达式的主体只有一条语句, 花括号 { } 可省略, 否则必须包含在花括号 { } 中.
OK, 到这里我们就可以重写上面的线程了.
- new Thread(
- () -> System.out.println("Hello World")
- ).start();
说到这简单回忆一下什么是 lambda 表达式, 曾经 Java 中不能直接把函数做参数, 为了能行, 创造了 lambda 表达式, 可以把 lambda 表达式理解为一个功能块, 只不过匿名罢了.
其实 lambda 的出现是为了和函数式编程相呼应, 函数式编程, 就是用函数为主体来编程, 把函数当成是代码的基本组成部分, 就像变量一样. 官方说法叫第一等公民.
举个例子说明一下函数式编程的特点.
计算如下表达式:
(1 + 2) * 3 - 4
传统的过程式编程, 可能这样写 (比较傻, 为了演示效果):
- int a = 1 + 2;
- int b = a * 3;
- int c = b - 4;
函数式编程要求使用函数, 我们可以把运算过程定义为不同的函数, 然后写成下面这样:
int result = subtract(multiply(add(1,2), 3), 4);
有点蒙, 没关系, 先理解 lambda 表达式的使用再说, lambda 表达式最常用的莫过于替换 Runnable 接口实现线程任务, 还有什么用处呢?
太难的不介绍, 说一个比较简单的, 用于列表的迭代.
对一个列表的每一个元素进行操作, 不使用 Lambda 表达式时如下:
- List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
- for (int element : numbers) {
- System.out.prinln(element);
- }
使用 Lambda 表达式:
- List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
- numbers.forEach(x -> System.out.println(x));
重点在操作上, 输入是 x , 然后对 x 进行输出操作. 就线程和列表迭代来说, 为什么他们能接收 lambda 表达式作为参数呢? 我们看看 forEach 方法的参数内部是什么.
- * @since 1.8
- */
- @FunctionalInterface
- public interface Consumer<T> {
- /**
- * Performs this operation on the given argument.
- *
- * @param t the input argument
- */
- void accept(T t);
是一个接口, 而这个接口被定义为函数式接口, lambda 表达式可以替换功能接口, 我们就来自定义一个函数式接口来演示一下.
定义一个函数式接口:
- // 定义一个功能接口或叫函数式接口
- @FunctionalInterface
- public interface WorkerInterface {
- // 该接口中只能有一个抽象方法
- public void doSomeWork();
- }
- public class WorkerInterfaceTest {
- public static void execute(WorkerInterface worker) {
- worker.doSomeWork();
- }
- public static void main(String[] args) {
- // invoke doSomeWork using Annonymous class
- execute(new WorkerInterface() {
- @Override
- public void doSomeWork() {
- System.out.println("Worker invoked using Anonymous class");
- }
- });
- // invoke doSomeWork using Lambda expression
- execute(()->{System.out.println("Worker invoked using Lambda expression");});
- }
- }
总结一下最开始提出的几个问题, lambda 表达式可以理解为是一个匿名的函数, 我们可以通过 lambda 表达式来代替功能接口 (比方说 Runnable 接口). 函数式编程是一种编程模式, Java 为了支持它而定义了 lambda .lambda 的应用主要在替代功能接口, 列表迭代, 还有一些对集合的操作上.
最后, 能告诉我你现在使用 Lambda 表达式了吗, 都是用在什么地方呢 ?
来源: http://www.bubuko.com/infodetail-2988109.html