Lambda表达式
Posted to.to
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lambda表达式相关的知识,希望对你有一定的参考价值。
1.Lambda表达式
以下转自:https://www.runoob.com/java/java8-lambda-expressions.html
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。
语法
lambda表达式的语法格式如下:
(parameters) -> expression
或
(parameters) ->{ statements; }
以下是lambda表达式的重要特征:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
1.1.Lambda表达式实例
Lambda 表达式的简单例子:
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
//5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s);
在 Demo1.java 文件输入以下代码:
package project;
public class Demo1 {
public static void main(String[] args) {
Demo1 tester = new Demo1();
// 类型声明
MathOperation addition = (int a, int b) -> a + b;
// 不用类型声明
MathOperation subtraction = (a, b) -> a - b;
// 大括号中的返回语句
MathOperation multiplication = (int a, int b) -> { return a * b; };
//没有大括号及返回语句
MathOperation division = (int a, int b) -> a / b;
System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
System.out.println("10 * 5 = " + tester.operate(10, 5, multiplication));
System.out.println("10 / 5 = " + tester.operate(10, 5, division));
//不用括号
GreetingService greetingService1 = message ->
System.out.println("Hello " + message);
//用括号
GreetingService greetingService2 = (message) ->
System.out.println("Hello " + message);
greetingService1.sayMessage("Runoob");
greetingService2.sayMessage("Google");
}
interface MathOperation {
int operation(int a, int b);
}
interface GreetingService {
void sayMessage(String message);
}
private int operate(int a, int b, MathOperation mathOperation) {
return mathOperation.operation(a, b);
}
}
执行以上脚本,输出结果:
10 + 5 = 15
10 - 5 = 5
10 * 5 = 50
10 / 5 = 2
Hello Runoob
Hello Google
使用Lambda表达式需要注意以下两点:
Lambda表达式主要用来定义行内执行的方法类型接口,例如,一个简单方法接口。在上面例子中,我们使用各种类型的Lambda表达式来定义MathOperation接口的方法。然后我们定义了sayMessage的执行。
Lambda表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。
1.2.变量作用域
lambda表达式只能引用标记了 final 的外层局部变量,这就是说不能在lambda内部修改定义在域外的局部变量,否则会编译错误。
在Demo2.java文件输入以下代码:
public class Demo2 {
final static String salutation = "Hello! ";
public static void main(String[] args) {
GreetingService greetService1 = message ->
System.out.println(salutation + message);
greetService1.sayMessage("Runoob");
}
interface GreetingService {
void sayMessage(String message);
}
}
执行以上脚本,输出结果为:
Hello! Runoob
1.3.Lambda 表达式的来对集合进行遍历
代码示例如下:
package project;
import java.util.Arrays;
import java.util.function.Consumer;
public class Demo3 {
public static void main(String[] args) {
//使用Lambda表达式
Arrays.asList(1,2,3).forEach(element -> System.out.println(element));
System.out.println("----------------------------------");
//使用匿名内部类
Arrays.asList(1,2,3).forEach(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(integer);
}
});
}
}
输出结果:
1
2
3
----------------------------------
1
2
3
Lambda表达式语法如下:
用逗号分隔的形式参数列表,用括号括起来。
Note: 数据类型可以省略,只有一个参数还可以省略括号,例如,上图的element。
标识符:->
主体:放在{}内。
Note:如果主体仅仅是一个表达式或者或一个语句块,{} 和 ; 可以省略。只存在单条返回语句的话,return 关键字也可以省略。
我们对集合进行遍历,做一个完整的演进:
package project;
import java.util.Arrays;
import java.util.function.Predicate;
public class Demo4 {
public static void main(String[] args) {
//完整形式
Arrays.asList(1,2,3).stream().allMatch((Integer element) -> {
return element > 0;
});
//省略 数据类型,()
Arrays.asList(1,2,3).stream().allMatch(element -> {
return element > 0;
});
//省略 数据类型,()以及{},return 和;
Arrays.asList(1,2,3).stream().allMatch(element -> element > 0);
//外部定义 Lambda 表达式
Predicate<Integer> predicate = element -> element > 0;
Arrays.asList(1,2,3).stream().allMatch(predicate);
}
}
不过,Lambda 表达式只能用于功能接口(函数式接口),也就是说只能用在一个接口除了含有单个抽象方法和 Object 中的 public 访问修饰符定义的方法外,不能再含有其它抽象方法。Java中常见的Comparator便是一个很好的例子。
1.4.Lambda表达式的结构
让我们了解一下Lambda表达式的结构。
一个 Lambda 表达式可以有零个或多个参数。
参数的类型既可以明确声明,也可以根据上下文来推断。例如:(int a)与(a)效果相同。
所有参数需包含在圆括号内,参数之间用逗号相隔。例如:(a, b) 或 (int a, int b) 或 (String a, int b, float c)
空圆括号代表参数集为空。例如:() -> 42
当只有一个参数,且其类型可推导时,圆括号()可省略。例如:a -> return a*a
Lambda 表达式的主体可包含零条或多条语句。
如果Lambda表达式的主体只有一条语句,花括号{}可省略。匿名函数的返回类型与该主体表达式一致。
如果Lambda表达式的主体包含一条以上语句,则表达式必须包含在花括号{}中(形成代码块)。匿名函数的返回类型与代码的返回类型一致,若没有返回则为空。
Java 中的 Lambda 表达式通常使用 (argument) -> (body) 语法书写,例如:
(arg1, arg2...) -> {body}
(type1 arg1, type2 arg2...) -> {body}
以下是一些 Lambda 表达式的例子:
(int a, int b) -> { return a + b; }
() -> System.out.println("Hello World");
(String s) -> { System.out.println(s); }
() -> 42
() -> {return 3.1415};
1.5.map的使用
package demo2;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Demo1 {
public static void main(String[] args) {
List<String> list= Arrays.asList("a", "b", "c", "d");
//String::toUpperCase 表示string中的toUpperCase方法
List<String> collect =list.stream().map(String::toUpperCase).collect(Collectors.toList());
System.out.println(collect); //[A, B, C, D]
List<Integer> num = Arrays.asList(1,2,3,4,5);
List<Integer> collect1 = num.stream().map(n -> n * 2).collect(Collectors.toList());
System.out.println(collect1); //[2, 4, 6, 8, 10]
}
}
1.6.Java 8十个lambda表达式案例
以下转自:https://www.jdon.com/idea/java/10-example-of-lambda-expressions-in-java8.html
1.6.1.实现Runnable线程案例
使用() -> {} 替代匿名类:
package project;
public class Demo5 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Before Java8");
}
}).start();
new Thread( () -> System.out.println("In Java8!")).start();
}
}
1.6.2.实现事件处理
如果你曾经做过Swing 编程,你将永远不会忘记编写事件侦听器代码。使用lambda表达式如下所示写出更好的事件侦听器的代码。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
public class Demo6 {
public static void main(String[] args) {
//Before Java 8:
JButton show = new JButton("Show");
show.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("without lambda expression is boring");
}
});
// Java 8 way:
show.addActionListener((e) -> {
System.out.println("Action !! Lambda expressions Rocks");
});
}
}
1.6.3.使用Lambda表达式遍历List集合
import java.util.Arrays;
import java.util.List;
public class Demo7 {
public static void main(String[] args) {
// prior Java 8
List<String> features = Arrays.asList("Lambdas", "Default Method",
"Stream API", "Date and Time API");
for (String feature : features) {
System.out.println(feature);
}
System.out.println("===========================");
// In Java 8
// List<String> features = Arrays.asList("Lambdas", "Default Method", "Stream API",
// "Date and Time API");
features.forEach(n -> System.out.println(n));
System.out.println("===========================");
// Even better use Method reference feature of Java 8
// method reference is denoted by :: (double colon) operator
// looks similar to score resolution operator of C++
features.forEach(System.out::println);
}
}
方法引用是使用两个冒号::这个操作符号
输出结果:
Lambdas
Default Method
Stream API
Date and Time API
===========================
Lambdas
Default Method
Stream API
Date and Time API
===========================
Lambdas
Default Method
Stream API
Date and Time API
1.6.4.使用Lambda表达式和函数接口
为了支持函数编程,Java 8加入了一个新的包java.util.function,其中有一个接口java.util.function.Predicate是支持Lambda函数编程:
package demo2;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class Demo1 {
public static void main(String[] args) {
List<String> languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp");
System.out.println("Languages which starts with J:");
filter(languages, (str) -> str.startsWith("J"));
System.out.println("--------------------------");
System.out.println("Languages which ends with a ");
filter(languages, (str) -> str.endsWith("a"));
System.out.println("--------------------------");
System.out.println("Print all languages: ");
filter(languages, (str) -> true);
System.out.println("--------------------------");
System.out.println("Print no language: ");
filter(languages, (str)-> false);
System.out.println("-------------------------");
System.out.println("Print language whose length greater than 4:");
filter(languages, (str)->str.length() > 4);
}
// public static void filter(List<String> names, Predicate<String> condition) {
// for(String name : names) {
// if (condition.test(name)) {
// System.out.println(name + " ");
// }
// }
// }
public static void filter(List<String> names, Predicate<String> condition) {
names.stream().filter((name) -> (condition.test(name)))
.JAVA由一个将JSONArray转成Map的需求引发的lambda语法的学习