Java Lambda表达式

时间:2020-02-23 14:36:39  来源:igfitidea点击:

Java lambda表达式可以被视为Java 8中引入的最酷的功能之一。
这是Java进入函数式编程的第一步。
Java lambda表达式可以视为可以创建的函数,而不必属于任何类。
同样,它可以像对象一样传递并按需执行。

Java Lambda表达式

基本上,Lambda Expression是可以传递的匿名函数的简洁表示。
因此,它具有以下属性:

  • 匿名:我们可以说是匿名的,因为它没有方法通常具有的显式名称。
    因此,写作和思考的时间肯定要少得多。

  • 函数:可以将其视为函数,因为lambda并不像方法那样与特定类相关联。
    但是像方法一样,lambda具有参数列表,主体,返回类型以及可能抛出的异常列表。

  • 传递:Lambda表达式可以作为参数传递给方法或者存储在变量中。

  • 简洁:我们不需要像编写匿名类那样编写很多样板文件。

从技术上讲,Lambda表达式不允许我们做Java 8之前没有做的任何事情。
只是为了使用行为参数化,我们不需要编写笨拙的代码。

Java Lambda表达式示例

举个例子肯定有助于弄清楚一个主意。
考虑Apple类:

public class Apple {
  String color;
  Double weight;

  public String getColor() {
      return color;
  }

  public void setColor(String color) {
      this.color = color;
  }

  public Double getWeight() {
      return weight;
  }

  public void setWeight(Double weight) {
      this.weight = weight;
  }
}

如果我们想编写一个自定义比较器来按重量比较苹果,那么在Java 7之前,我们通常通过以下方式编写它:

Comparator<Apple> byWeight = new Comparator<Apple>() {
  public int compare(Apple a1, Apple a2){
      return a1.getWeight().compareTo(a2.getWeight());
  }
};

现在,使用Lambda Expression,我们可以编写与以下内容相同的东西:

Comparator<Apple> byWeight 
= (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());

Java Lambda表达式说明

让我们深入研究一下此表达式中的各个部分:

  • 参数列表:在这种情况下,它镜像了a的compare方法的参数
    比较器–两个Apple对象。

  • 箭头:箭头->将参数列表与lambda主体分开。

  • Lambda的主体:比较两个苹果的重量。
    该表达式被认为
    Lambda的返回值。

Java 8 Lambda Expression用法

让我们看一下Java lambda表达式的一些用例示例。

  • 布尔表达式:(List list)-> list.isEmpty()
  • 创建对象:()-> new Apple()
  • 从对象消耗:(Apple a)-> {System.out.println(a.getWeight()); }
  • 从对象中选择/提取:((String s)-> s.length()`
  • 通过对两个值执行计算来产生一个值:((int a,int b)-> a * b`
  • 比较两个对象:(Apple a1,Apple a2)-> a1.getWeight()。 compareTo(a2.getWeight())

Java功能接口

很明显想知道其中允许这样的表达式?以前,我们看到了一个lambda表达式来替换Comparator实现。
我们也可以按如下方式使用它:

List<String> greenApples 
= listOfApples.stream().filter(a -> a.getColor().equals("Green"))
    .collect(Collectors.toList());

其中filter()方法需要一个谓词。
我们只是传递了一个lambda而不是所需的接口。

基本上,我们可以在功能接口的上下文中使用它们。
现在,功能接口到底是什么?

简而言之,功能接口是一种接口,它恰好指定了一种抽象方法。

Java中一些已知的功能接口是Comparator,Runnable,ActionListener,Callable等。

还要注意,即使接口定义了一个或者多个默认方法,只要它定义了一个抽象方法,它仍然是一个功能接口。

当然,除了Java提供的默认接口之外,我们总是可以定义自定义功能接口。

Java Lambda表达式使我们可以直接,内联地直接为功能接口的抽象方法提供实现,并将整个表达式视为该接口的具体实现的实例。

Java Lambda表达式与匿名类

考虑前面的示例,使用匿名类也可以实现相同的目的,但是如果我们内联编写实现,代码将变得更加笨拙。

我们来看一个"可运行"的示例。
考虑一个带有Runnable实例的process方法:

public class RunnableDemo {
  public static void process(Runnable r){
      r.run();
  }
}

无需使用Lambda,我们可以将其实现为:

Runnable runnableWithAnonymousClass = new Runnable() {
  @Override
  public void run() {
      System.out.println("I am inside anonymous class implementation.");
  }
};
process(runnableWithAnonymousClass);

使用lambda表达式:

Runnable runnableWithLambda = () -> System.out.println("I am inside Lmabda Expression.");
process(runnableWithLambda);

另外,在仅使用此Runnable实现一次的情况下,我们也可以在调用process方法时直接提供它:

process(() -> System.out.println("I am inside Lambda Expression."));

函数描述符

使用lambda表达式时要了解的重要事项是函数描述符。
功能接口的抽象方法的签名实质上描述了lambda表达式的签名。
我们将此抽象方法称为函数描述符。

例如,Runnable接口可以看作是不接受任何内容且不返回任何内容(无效)的函数的签名,因为它只有一个称为" run"的抽象方法,该方法不接受任何内容且不返回任何内容(无效)。