Lambda表达式

目录

1.什么是Lambda表达式?

2. 如何辨别Lambda表达式

3.引用值而不是变量

5.函数接口

6.总结


面对大型数据集合,Java还欠缺高效的并行操作,因此Java 8增加了Lambda表达式。Lambda表达式能够使开发者简单高效地开发出在多核CPU上高效运行的代码。Lambda表达式是函数式编程,我们知道面向对象编程是对数据进行抽象,而函数式编程是对行为进行抽象。那什么是函数式编程?函数式编程的核心思想是在思考问题时,使用不可变值和函数, 函数对一个值进行处理映射成另外的一个值。

1.什么是Lambda表达式?

Java8的最大变化是引入了Lambda表达式,一种紧凑的、传递行为的方式。下面的例子中,我们创建了一个新对象,它是实现了ActionListener接口。 为了调用一行重要的逻辑代码,不得不加上4行冗余的样板代码:

 Runnable old = new Runnable() {
       @Override
       public void run() {
          System.out.println("Hello World");
    }
 };

如果我们不想传入对象,只想传入行为,可以使用Lambda表达式实现:

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

->将参数和Lambda表达式的主体分开,而主体是用户点击按钮时会运行的一些代码。在Lambda表达式中无需指定类型,程序依然可以编译。这是因为Javac 根据程序的上下文,在后台推断了参数类型。这意味着如果参数类型不言而明,则无需显式指定。有时,编译器不一定能根据上下文推断出参数的类型,此时 我们声明参数时就必须包含类型信息。

2. 如何辨别Lambda表达式

Lambda表达式除了基本的形式外还有以下几种形式:

    1   Runnable noArguments = () -> System.out.println("Hello World");
    2   ActionListener oneArgument = event -> System.out.println("Hello World");
    3   Runnable multiStatement = () -> {
            System.out.println("Hello");
            System.out.println("World");
        };
    4   BinaryOperator<Long> add = (x, y) -> x + y;
    5   BinaryOperator<Long> addExplicit = (Long x, Long y) -> x + y;
  • 1中Lambda表达式不包含参数,使用空括号()表示没有参数
  • 2中所示的Lambda表达式包含且只包含一个参数,可省略参数的括号
  • 3中所示Lambda表达式的主体不仅可以是一个表达式,而且也是一段代码块,使用大括号({})将代码块括起来
  • 4中表示Lambda表达式也可以表示包含多个参数的方法,这时就有必要思考怎样去阅读该Lambda表达式。这行代码并不是将两个数字相加,而是创建了一个函数

用来计算两个数字相加的结果。
以上四种Lambda表达式中的参数类型都是由编译器推断得出的,但有时最好也可以显式的声明参数类型,此时就需要使用小括号将参数括起来,多个参数的情况
也是如此。

3.引用值而不是变量

如果你曾使用过匿名内部类, 也许遇到过这样的情况: 需要引用它所在方法里的变量。 这时,需要将变量声明为 final,如下代码所示:

final String name = getUserName();
button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent event) {
    System.out.println("hi " + name);
    }
});

将变量声明为 final, 意味着不能为其重复赋值,同时也意味着在使用 final 变量时,实际上是在使用赋给该变量的一个特定的值。Java 8中虽然放松了这一限制,可以用非final的变量,但是该变量在既定事实上必须是final,否则编译器就会报错。因此Lambda表达式中引用的局部变量也必须是final或者是既成事实上的final变量。这种行为也解释了为什么Lambda表达式被称为是闭包。未赋值的变量与周边魂晶隔离起来,进而被绑定到一个特定的值。Lambda表达式都是静态类型的,因此,接下来分析一下Lambda表达式本身的类型:函数接口。

Lambda表达式示例代码如下:

/**
 * 使用Lambda表达式的必要条件:
 * 1.必须有一个接口
 * 2.接口当中必须保证有且仅有一个抽象方法
 * FunctionalInterface注解用来检测是否是函数式接口,当不是函数式接口时,编译失败
 *
 * @author: xuzongxin
 * @date: 2019/7/16 14:38
 * @description:
 */
@FunctionalInterface
public interface Bird {
    //唯一抽象方法
    void sing();
}

测试实现代码:

public class BirdTest {
    public static void method(Bird bird) {
        bird.sing();
    }

    public static void main(String[] args) {
        method(() -> {
            System.out.println("bling bling...");
        });
    }
}

5.函数接口

函数接口是只有一个抽象方法的接口,用作Lambda表达式的类型。Java中的重要的函数接口主要如下:

大多数情况下,省略类型信息可以减少干扰,使得代码更加的简洁,因此在Java8中,程序员可以省略Lambda表达式中的所有参数类型。javac根据Lambda表达式上下文信息就能推断出参数的正确类型。程序依然要经过类型检查来保证运行的安全性,但不用再显式声明类型罢了。 这就是所谓的类型推断。

Predicate<Integer> atLeast5 = x -> x > 5;

Predicate是一个具有返回值的Lambda表达式,Lambda表达式实现了Predicate接口,因此它的单一参数被推断为Integer 类型,如果我们把Integer去掉就会编译报错。javac还可检查Lambda表达式的返回值是不是boolean,这正是Predicate方法的返回类型。

6.总结


• Lambda 表达式是一个匿名方法, 将行为像数据一样进行传递。
• Lambda 表达式的常见结构: BinaryOperator<Integer> add = (x, y) → x + y。
• 函数接口指仅具有单个抽象方法的接口, 用来表示 Lambda 表达式的类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值