一 . 概述
集合是我们 java 程序员每天都需要的工具, 没有了集合, java 程序员几乎不能干任何的事情, 我们每天的工作也是在对集合进行不同的操作.
尽管集合的功能已经足够强大, 但是当我们面对复杂的业务问题的时候, 利用原始的集合操作就会变得让人恶心.
于是在 java8 之中出现了 lambda 和 stream 的 API, 为我们以一种更加优雅的方式使用集合.
没错, 就是集合, 当我们现在使用 NOSQL, 各种日志分析, 等等的大数据操作的时候, 我们不可能使用原始的数据库的 sql 操作帮助我们完成如排序, 求和, 分组等操作了,
我们急缺一中工具来完成我们的任务, 很让人高兴的一点就是, Stream 做到了, 并且很优雅.
那么, 函数式编程式编程和 Stream,lambda 有什么关系呢? 就是因为 java 引入了函数式编程的编程范式来解决这个问题的,
因此, 我们的起点就应该是函数式编程.
二 . 从函数式编程到 lambda
行为参数化, 一个很抽象的概念, 其实我们每天都在用, 很像一种策略模式, 如我们在 js 之中不断传入的回调函数一样.
在 java8 之中, 函数式编程的根基就是 lambda, 这是整个 java 函数式编程的基础.
在这里不去说函数式编程的准确含义, 因为没有人能说清楚.
我们想在想做的就是引入 lambda.
请看下面的例子:
我们以前使用线程 Runnable 的方式:
- Runnable runnable = new Runnable() {
- @Override
- public void run() { for(;;)
- System.out.println("thread is running...");
- }
- };
- new Thread(runnable).start();
以前我们使用匿名内部类的方式来编写一个 Runnbale 的实现, 其实在上面的代码之中, 只有红色部分是有用的.
当我们编写了很多这样的代码之后, 我们大概能够知道, 我们其实就是想创建一种行为而已(或者说一种实现而已), 根本没有必要每次都写大量的模板代码.
于是, 在 java8 之中, 我们可以写下面的代码.
- new Thread(()->{
- for(;;)
- System.out.println("thread is running...");
- }).start();
嘿嘿, 我们现在就编写了一个 lambda 的表达式来描述我们的行为.
三 .lambda 表达式的本质
lambda 表达式的本质和匿名内部类是一样的, 而且它的条件更加苛刻.
下面的例子证明 lambda 和匿名内部类其实是一种事物:
- Runnable run = ()->{
- for(;;)
- System.out.println("thread is running...");
- };
看到上面的代码没有编译的问题了吗? 这就证明 lambda 本质上就是一个匿名内部类的实现而已.
从这里我们能够看到, 即使 java 出现了 lambda, 从本质上还是没有推翻我们之前的世界观.
在上面, 提到了 lambda 的条件更加苛刻, 为什么呢?
我们知道, 一个匿名内部类可以实现多个方法, 但是 lambda 却只能实现一个.
因此, 在 java8 之中为了更好地表达 lambda 的使用, 出现了一个新的概念, 就是函数式接口.
看到了吗, lambda 和函数式接口出现了, 函数式接口本身就是为了 lambda 服务的.
那么, 什么是函数式接口呢? 很简单, 就是一个接口 (抽象类) 内部仅仅只有一个待实现的方法, 我们就称为函数式接口.
为了表达这个概念, 在 java8 之中使用一个注解表达这个概念,
public @interface FunctionalInterface {}
这个注解仅仅只是一个标记注解, 能提供的作用仅仅是在编译之前指明语法错误, 像 @Override 一样.
即使一个接口没有这个注解, 也不会妨碍这个接口成为一个函数式接口.
来源: http://www.bubuko.com/infodetail-2714788.html