Lambda
表达式也叫闭包,允许把函数作为一个方法的参数,可以将代码变得简介紧凑,核心思想是将面向对象中的传递数据变成传递行为。对于只有单一方法的匿名类会显得很繁琐,Lambda
表达式可以让我们直接将某种功能作为参数,可以让上面的行为变得更加简洁。关于Lambda
官方详细文档戳这里。
1.基本语法为expression=(parameters) -> action
(参数、箭头、动作实现):
// 方式1
(parameters) -> expression
// 方式2
(parameters) -> {statements;}
【说明】
- 可选类型声明:不需要声明参数类型,编译器可以统一识别参数;
- 可选参数圆括号:一个参数无须定义圆括号,但多个参数需要定义圆括号;
- 可选花括号:如果主体中只包含一个语句,就不需要使用花括号了,否则需要使用;
- 可选的返回关键字:如果主体中只有一个表达式则编译器会自动返回值,如果多个表达式使用花括号,就需要指明返回一个值;
2.使用场景,下面是一些用例代码:
public class LambdaTest {
public static void main(String[] args) {
LambdaTest lambdaTest = new LambdaTest();
// 声明类型
MathOperation add = (int a, int b) -> a + b;
// 不声明类型
MathOperation sub = (a, b) -> a - b;
// 使用花括号返回值
MathOperation multi = (a, b) -> {
return a * b;
};
// 没有大括号及返回语句
MathOperation div = (a, b) -> a / b;
System.out.println(lambdaTest.operate(2, 3, add));
System.out.println(lambdaTest.operate(3, 2, sub));
System.out.println(lambdaTest.operate(2, 3, multi));
System.out.println(lambdaTest.operate(10, 5, div));
String hello = "Hello ";
GreetingService greetingService = message -> System.out.println(hello + message);
greetingService.sayMessage("China");
greetingService.sayMessage("Janey");
// 用()->{}代替匿名类
new Thread(() -> System.out.println("lambda")).start();
List<String> list = Arrays.asList(new String[]{"c", "b", "h"});
// 遍历List的方法1
list.forEach(l -> System.out.println(l));
System.out.println("=================");
// 遍历List的方法2,其中::代表方法引用的操作符
list.forEach(System.out::println);
// 排序,其实有点类似上面的匿名类
Comparator<String> stringComparator = (str1, str2) -> str1.compareTo(str2);
list.sort(stringComparator);
}
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);
}
}
关于上述的方法引用操作符是::
,基本是下面的形式:
objectName::instanceMethod
ClassName::staticMethod
ClassName::instanceMethod
在遍历List
时用到的System.out::println
和x -> System.out.println(x)
是一样的,Math::max
就等同于(x,y) -> Math.max(x,y)
。
这一块结合昨天遇到的Stream
很好用,Stream
是一个来自数据源的元素队列并支持聚合操作:
- 元素是特定类型的对象,形成一个队列,
Stream
并不会存储元素,而是按需计算; - 数据源是
Stream
的来源,可以是数组、集合等对象; - 聚合操作,就是按需进行的一些操作,如过滤、遍历、匹配等操作;
下面是之前写的一些常用方法的案例:
// 初始化一个流
Stream stream = Stream.of("a", "b", "c");
// 将数组转化为一个流
String[] arr = new String[]{"cb", "b", "pb", "ub", "b"};
Stream stream1 = Stream.of(arr);
// 将一个集合对象转为一个流
List<String> list = Arrays.asList(arr);
Stream stream2 = Stream.of(list);
Object collect = stream2.sorted().collect(Collectors.toList());
// 1.1 map方法实现遍历映射操作(有点类似于覆盖源数据的意思),collect方法是得到操作后的集合
List<String> list1 = list.stream().map(String::toUpperCase).collect(Collectors.toList());
System.out.println(list1);
// 1.2 更新值
List<String> list2 = list.stream().map(s -> s + "ha").collect(Collectors.toList());
System.out.println(list2);
// 1.3 遍历还可以直接用forEach
stream.forEach(s -> System.out.println(s));
// 2.1 利用filter进行过滤,对过滤后的流再使用collect方法转成对应的集合
List<String> list3 = list.stream().filter(s -> !s.contains("c")).collect(Collectors.toList());
System.out.println(list3);
// 3. 对流进行忽略或者limit操作(类似于MySQL中limit),skip(2)就是跳过流的前2个,返回前1个
List<String> list4 = list.stream().skip(2).limit(1).collect(Collectors.toList());
System.out.println(list4);
// 4. 排序
List<String> list5 = list.stream().sorted().collect(Collectors.toList());
System.out.println(list5);
// 5. 去重,distinct方法可以将流中的重复元素去除
List<String> list6 = list.stream().distinct().collect(Collectors.toList());
System.out.println(list6);
// 6. 匹配, allMatch、anyMatch、noneMatch
// 6.1 anyMatch只要有一个元素符合predicate(这里就是a)就返回true
boolean anyMatch = list.stream().anyMatch(s -> s.equals("i"));
System.out.println(anyMatch);
// 6.2 noneMatch匹配不满足条件的,只有全部不满足才返回true
boolean noneMatch = list.stream().noneMatch(s -> s.contains("a"));
System.out.println(noneMatch);
// 6.3 allMatch匹配满足条件的,只有全部满足条件的才返回true
boolean allMatch = list.stream().allMatch(s -> s.contains("b"));
System.out.println(allMatch);
List<Integer> integers = filterVersions(2017);
System.out.println(integers);