Java Lambda表达式
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"的抽象方法,该方法不接受任何内容且不返回任何内容(无效)。