1. Lambda
1.1 概述
① Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。
② Lambda 表达式:->
”操作符被称为箭头操作符。它将 Lambda 分为两个部分:
- 左侧: 指定了 Lambda 表达式需要的形参列表;其的参数类型可以省略(类型推断);如果lambda形参列表只有一个参数,其一对
()
也可以省略 - 右侧: 指定了 Lambda 体, 是抽象方法的实现逻辑,也即
Lambda 表达式要执行的功能。Lambda 体应该使用一对{}
包裹;如果lambda体只有一条执行语句(可能是return
语句),省略这一对{}
和return
关键字、
③ Lambda表达式的本质:函数式接口的实例
1.2 函数式接口
如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口。我们
- 只包含一个抽象方法的接口,称为函数式接口。
- 你可以通过 Lambda 表达式来创建该接口的对象。
- 我们可以在一个接口上使用
@FunctionalInterface
注解,这样做可以检查它是否是一个函数式接口。同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。 java.util.function
包下定义了Java 8 的丰富的函数式接口
3. 方法引用
要求:接口中的抽象方法的形参列表和返回值类型 与 方法引用的方法的形参列表和返回值类型相同(前两种情况)
4. 构造器引用
函数式接口的抽象方法的形参列表和构造器的形参列表一致, 抽象方法的返回值类型即为构造器所属的类的类型
5. 数组引用
6. Stream API
6.1 概述
Stream
(java.util.stream
) 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。 使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。- 实际开发中,项目中多数数据源都来自于Mysql, Oracle等。但现在数据源可以更多了,有MongDB, Radis等,而这些NoSQL的数据就需要Java层面去处理。
Stream
和Collection
集合的区别: Collection 是一种静态的内存数据结构,而 Stream 是有关计算的。 前者是主要面向内存,存储在内存中,后者主要是面向 CPU,通过 CPU 实现计算。
6.2 创建Stream
List<Integer> list = new ArrayList<>();
Stream<Integer> stream = list.stream();
Integer[] a = new Integer[]{1,2,3,4};
Stream<Integer> stream1 = Arrays.stream(a);
6.3 Stream 的中间操作
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值” 。
//flatMap演示;类比list中套list
@Test
public void test01(){
ArrayList<String> list = new ArrayList<>();
list.add("aa");
list.add("bb");
list.add("cc");
list.add("dd");
list.add("ee");
list.stream().map(test::fromStringToStream).forEach(System.out::println);
list.stream().flatMap(test::fromStringToStream).forEach(System.out::println);
}
public static Stream<Character> fromStringToStream(String string){
ArrayList<Character> list = new ArrayList<>();
for(Character c:string.toCharArray()){
list.add(c);
}
return list.stream();
}
6.4 Stream 的终止操作
- 终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:
List
、Integer
,甚至是void
- 流进行了终止操作后,不能再次使用
//例子
List<Integer> list = Arrays.asList(1,2,3,4,5);
System.out.println(list.stream().reduce(0, Integer::sum));
Collector 接口中方法的实现决定了如何对流执行收集的操作(如收集到 List、 Set、Map)。
另外, Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下表:
List<Employee> employees = EmployeeData.getEmployees();
List<Employee> employeeList = employees.stream().filter(e -> e.getSalary() > 6000).
collect(Collectors.toList());
employeeList.forEach(System.out::println);
7. Optional类
//例子:使用Optional类的getGirlName():
public String getGirlName2(Boy boy){
Optional<Boy> boyOptional = Optional.ofNullable(boy);
//此时的boy1一定非空
Boy boy1 = boyOptional.orElse(new Boy(new Girl("迪丽热巴")));
Girl girl = boy1.getGirl();
Optional<Girl> girlOptional = Optional.ofNullable(girl);
//girl1一定非空
Girl girl1 = girlOptional.orElse(new Girl("古力娜扎"));
return girl1.getName();
}