Java8--Lambda表达式和方法引用

Lambda 表达式

这是 Java 函数式编程的核心。Lambda 表达式是 Java 中的主要构造,它在语言中提供了一种新的语法,使我们能够以自然的方式表达函数。

1、Lambda 表达式是面向对象平台中函数式编程原则的实现
2、Lambda 表达式用于直接在代码中表达函数,而无需面向对象的包装器来支持它们(从语言语法的角度来看)。在方法上,可以看作是匿名方法。
3、由于 lambda 遵循函数的语义,就像在函数式编程语言中一样, 因此它们获得了可以从不可变的、一致的函数中获得的所有并行性和并发性优势。
4、Lambda 表达式可以在任何需要函数式接口的代码中使用,这实际上意味着,在内部,lambda 表达式是函数式接口的实现,因此是语言中的一等公民。它们可以被分配/存储,作为参数传递等。
5、如果匿名类是只包含一个方法的接口的实现,则 Lambdas 可以替换匿名类,然后匿名类可以替换为一个 lambda,这会形成干净且不那么冗长的代码。

现在让我们将 Java 中的 lambda 表达式与 lambda 演算或函数式编程中的构造进行比较:

1、函数是匿名的——lambda表达式也是匿名的
2、函数不会改变状态——lambda 表达式遵循与匿名/本地类相同的闭包规则,即它们只能访问 final 或有效的 final 变量
3、函数可以用作输入或作为其他函数的输出返回
4、Lambda 演算的语法 λx.x2 与 lambda 表达式 x→x^2 的语法相匹配。λx 成为参数部分, dot 成为箭头, expr 主体在这里成为 lambda 表达式的主体。

一、Lambda 表达式语法

让我们来看看用于在代码中表达不同类型函数的语言语法。

1、指定函数参数,参数类型可选,如果只有一个参数可以省略小括号
2、用于分隔参数和正文的箭头运算符
3、如果只有一个语句,函数体、大括号和返回可以省略

语法示例:

1、无参数: () →System.out.println(“Nothing”)

2、一个参数: x →x+2

3、两个参数: (x,y) →x+y

4、带参数类型: (Integer x, Integer y) →x+y

5、多个语句:

(x,y){
    System.out.println(x);
    System.out.println(y);
    return x+y;
}

二、Lambda表达式与传统代码的比较

让我们将使用 Lambda 表达式的代码与传统代码进行比较,以了解在代码中使用 lambda 表达式的区别和优势:

Thread t = new Thread(new Runnable() {
  @Override
  public void run() {
    System.out.println("From a thread");
  }
});

Thread t = new Thread(() -> System.out.println("From a thread"));
Collections.sort(Arrays.asList(3, 2, 1), new Comparator<Integer>() {
  @Override
  public int compare(Integer o1, Integer o2) {
    return o1.compareTo(o2);
  }
});

Collections.sort(Arrays.asList(3, 2, 1), (o1, o2) -> o1.compareTo(o2));
List<String> strings = Arrays.asList("R", "O", "B");
for (String string : strings) {
  System.out.println(string);
}

List<String> strings = Arrays.asList("R", "O", "B");
strings.forEach(s -> System.out.println(s));
// 或者使用方法引用
strings.forEach(System.out::println);

有关 Lambda 表达式及其在 Java 中实现的更多详细信息,将在后续的文章中讨论。

方法引用

Lambda 表达式用于表达函数的主体,但如果已经编写/定义了函数/方法,则可以在使用 lambda 表达式的任何地方直接将它们用作方法引用。我们可以看到 lambda 表达式和方法具有相同的用法,只是第一个是匿名的,而后者是命名的。因此,如果我们已经定义了一个方法,则方法引用允许我们按名称使用该方法来代替匿名 lambda 表达式。

有四种方法引用:

1、对静态方法的引用
— ContainingClass::staticMethodName
2、对特定对象的实例方法的引用
— containsObject::instanceMethodName
3、对特定类型的任意对象的实例方法的引用
— ContainingType::methodName
4、对构造函数的引用
— ClassName::new

让我们看看四种方法引用的例子:

public class MethodRef {
  public void printLowerCase(String s) {
    System.out.println(s.toLowerCase());
  }

  public static void printUpperCase(String s) {
    System.out.println(s.toUpperCase());
  }

  public void publicMethod() {
    List<String> list = Arrays.asList("A", "B", "C");
    list.forEach(this::printLowerCase);
    list.forEach(MethodRef::printUpperCase);
    list.forEach(String::toLowerCase);
    list.forEach(String::new); 
  }
}

list.forEach(this::printLowerCase) 是对特定对象的实例方法的引用的示例。请注意,如果在此处使用 lambda 表达式而不是此方法引用,则有一个区别:使用 lambda 表达式时,只能访问 final 或有效的 final 字段,而使用此方法引用,可以访问任何字段。

list.forEach(MethodRef::printUpperCase) 是对静态方法的方法引用的示例。

list.forEach(String::toLowerCase) 是对特定类型的任意对象的实例方法的方法引用的示例。

list.forEach(String::new) 是对构造函数的方法引用的示例。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值