Lambda 管中窥豹

什么是 Lambda 表达式?简单的来说,Lambda 表达式是一个匿名函数,Lambda 表达式基于数学中的λ演算得名,直接对应其中的 Lambda 抽象( lambda abstraction ),是一个匿名函数,既没有函数名的函数。Lambda 表达式可以表示闭包(注意和数学传统意义的不同)。你也可以理解为,简洁的表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出异常的列表。

有时候,我们为了简化代码而去使用匿名类,虽然匿名类能简化一部分代码,但是看起来很啰嗦。为了更好的的提高开发的效率以及代码的简洁性和可读性,Java8 推出了一个核心的新特性之一:Lambda 表达式。

Java8 之前,使用匿名类给用户排序的代码:

users.sort(new Comparator<User>() {
    @Override
    public int compare(User o1, User o2) {
        return o1.getAge().compareTo(o2.getAge());
    }
});

而有了lambda后,代码可能会是这样的

Comparator<User> byWeight = (User a1, User a2) -> a1.getAge().compareTo(a2.getAge());

还可能是这样的

Comparator<User> byAge = Comparator.comparing(User::getAge);

看上去更简洁了,少了好多行代码是不是?

Lambda的本质

lambda的本质就是匿名函数

我们都知道在java里赋值语句是这样的

String str = "123";

但是如果你想把“一块代码块”赋值给一个变量,该怎么做呢?,比如在javascript中可以这么写

var fun = ()->{alert(1)}

java做为老大哥,能不能有类似的写法呢?

codeSpan = public void doSomething(){System.out.pringln("乐猿社区")};

在java8之前是做不到,但有了java8之后,我们可以一步步简化上面的代码实现类似的效果

java 匿名 map 类 java匿名函数lambda_java 匿名 map 类

函数式接口

这样,我们就成功的非常优雅的把“一块代码”赋给了一个变量。而“这块代码”,或者说“这个被赋给一个变量的函数”,就是一个Lambda表达式。看到可能会有javaer要问,codeSpan的类型是什么呢?

在Java 8里面,所有的Lambda的类型都是一个接口,而Lambda表达式本身,也就是”一块代码“,需要是这个接口的实现。简而言之就是,Lambda表达式本身就是一个接口的实现。俗话说一图胜千言:

java 匿名 map 类 java匿名函数lambda_java 匿名 map 类_02

这种只有一个接口函数需要被实现的接口类型,我们叫它”函数式接口“。为了避免后来的人在这个接口中增加接口函数导致其有多个接口函数需要被实现,变成"非函数接口”,我们可以在这个上面加上一个声明@FunctionalInterface, 这样别人就无法在里面添加新的接口函数了:

@FunctionalInterface
public interface MyLambdaInterface {
    void doSomething();
}

这样一个完整的函数式接口实现如下

public class Test {
    MyLambdaInterface codeSpan = () -> System.out.println(""乐猿社区);
}

而在Java7之前实现接口如下

public class MyInterfaceImpl implements MyLambdaInterface{
    @Override
    public void doSomething() {
        System.out.println("乐猿社区");
    }
}

在jvm层,这两种写法的本质一样的,但明显java8的写法更简洁清晰。

jdk默认的函数式接口

接口

参数

返回值

类别

Consumer

T

void

消费型接口

Supplier

None

T

供给型接口

Function

T

R

函数型接口

Predicate

T

boolean

断言型接口

基础语法

在lambda中我们遵循如下的表达式来编写

expression = (variable) -> action
  • variable: 这是一个变量,一个占位符。像x,y,z,可以是多个变量;
  • action: 这里我称它为action, 这是我们实现的代码逻辑部分,它可以是一行代码也可以是一个代码片段

可以看到Java中lambda表达式的格式:参数、箭头、以及动作实现,当一个动作实现无法用一行代码完成,可以编写 一段代码用{}包裹起来。

lambda表达式可以包含多个参数,例如:

int sum = (x, y) -> x + y;

这时候我们应该思考这段代码不是之前的x和y数字相加,而是创建了一个函数,用来计算两个操作数的和。 后面用int类型进行接收,在lambda中为我们省略去了return。

Lambda作用

  • lambda最直观的作用就是使得代码变得异常简洁
  • Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中)

写在最后的

lambda灵活多变,内容博大精深,本文只是介绍了lambda的基本原理以及基础语法,顺带讲述了下什么是函数式接口,让初次接触java8的Javaer对lambda有了一个大概的了解。