java 8 新特性
新特性的优势
- 速度更快
- 代码更少(新语法:Lambda 表达式)
- 强大的Stream API
- 便于并行
- 最大化减少空指针异常Optional
一、lambda 表达式
背景:用“λ演算法”去理解,为什么函数式编程会有更少的bug
Lambda 是匿名函数,可以把 Lambda 表达式理解为是一段可以当作数据去传递的代码,从而可以写出更简洁、更灵活的代码。
Lambda 表达式的专用操作符为->
。它将 Lambda 分为两个部分:
- 左侧:指定参数(只书写符号,编译器会自动推断参数类型)
- 右侧:指定了 Lambda 体。
函数式接口
函数式接口只包含一个抽象方法。
函数式接口可以指向一个由Lambda表达式创建的对象。
函数式接口建议加上@FunctionalInterface注解,该注解用于检查接口是否为函数式接口。
如果将 Lambda 表达式作为参数传递,接收 Lambda 表达式的参数类型必须是与该 Lambda 表达式兼容的函数式接口的类型。
四种基本类型函数式接口
接口 | 参数 | 返回 | 方法 |
---|---|---|---|
Consumer<T> |
T |
void |
void accept(T t) |
Supplier<T> |
T |
T get() |
|
Function<T, R> |
T |
R |
R apply(T t) |
Predicate<T> |
T |
boolean |
boolean test(T t) |
方法引用
方法引用可以简写lambda表达式中已经存在的方法。
使用操作符::
将方法名和对象或类的名字分隔开来。
1 | Consumer con = (x) -> System.out.println(x); |
二、Stream API(java.util.stream.*)
Stream 是根据数据源(集合、数组等)生成的元素序列。
Stream 用于处理集合,比如查询、过滤和映射数据,类似于SQL。
特性
- Stream 不存储数据,它是数据源的一个视图。
- Stream 不改变源数据,而是返回一个持有结果的新Stream。
- Stream 操作不会立即执行,只有等到用户真正需要结果的时候才会执行。
- Stream 遍历一次后就失效,如果要再次遍历需要重新生成。
- Stream API 支持并行执行操作。
1. 创建流
通过已有集合创建流
1
2List<String> strings = Arrays.asList("A", "B", "C", "D", "E", "F");
Stream<String> stream = strings.stream();通过Stream创建流
1 | Stream<String> stream = Stream.of("A", "B", "C", "D", "E", "F"); |
2. 常用中间操作
- filter
filter 方法用于通过设置的条件过滤出元素。
1 | List<String> strings = Arrays.asList("A", "", "B", "C", "D"); |
- map
map 方法用于映射每个元素到对应的结果。
1 | List<Integer> numbers = Arrays.asList(1,2,3,4,5,6); |
- limit/skip
limit 返回 Stream 的前 n 个元素;skip 则是跳过前 n 个元素。
1 | List<Integer> numbers = Arrays.asList(1,2,3,4,5,6); |
- sorted
sorted 方法用于对流进行排序。
1 | List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6); |
- distinct
distinct 方法给流中的元素去重。
1 | List<Integer> numbers = Arrays.asList(1, 1, 3, 4, 4, 4); |
stream 中间操作的图示:
3. 常用最终操作
Stream的中间操作得到新Stream,最终操作则把新的Stream转换成需要的类型。
最终操作会消耗流,产生一个最终结果,所以最终操作后无法再使用流。
forEach
forEach 来迭代流中的每个数据。count
count 对数据计数。collect
collect 就是一个归约操作,可以接受各种做法作为参数,将流中的元素累积成一个汇总结果。
1 | List<String> strings = Arrays.asList("A", "B", "C", "d", "D", "e", "f"); |