一文掌握Lambda表达式(上)
https://mp.csdn.net/mp_blog/creation/editor/125460693
目录
Optional是JDK1.8引入的一个对象容器,主要用作方法返回类型,如果存在值则isPresent()方法返回true否则返回false。下面我们看看具体方法如何使用
optional提供了两个静态建造方法of()和ofNullable;下面看看两者有什么区别
| 方法 | 说明 |
| of(T value) | value不能为null,如果value是null则会抛出 NullPointerException |
ofNullable(T value) | value可以为null |
- try {
- //of方法value不允许为null,如果为null 则抛出NullPointerException
- Optional.of(null);
- } catch (NullPointerException npe) {
- npe.printStackTrace();
- }
- //ofNullable允许值为null
- Optional<Object> nonValueOptional = Optional.ofNullable(null);
Optional中提供了连个静态方法判断是否有值,分别是isEmpty()和isPresent;两者语义相反
| 方法 | 说明 |
| isEmpty() | 如果值为null则返回true,否则返回false;JDK 11以后提供 |
| isPresent() | 如果值不为null则返回true,否则返回false,JDK8只能使用这个方法 |
Optional中获取值的方法如下表所示
| 方法 | 说明 |
| get() | 值不能为null,如果为null则抛出一个NoSuchElementException |
| orElse(T other) | 如果值不为null就返回值,否则返回默认值 value != null ? value : other |
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X | 如果值为null就抛出指定异常 |
T orElseGet(Supplier<? extends T> supplier) | 如果值为null,就返回supplier提供的值 |
orElseThrow() | 等价于get()方法,JDK10新增 |
Optional除了上文的方法外还提供了类似Stream一样的操作,filter,map以及flatMap
| 方法 | 说明 |
filter(Predicate<? super T> predicate) | 如果值满足指定条件则不处理,否则就返回一个empty |
<U> Optional<U> map(Function<? super T, ? extends U> mapper) | 将值映射为另外一个值,并构建一个Optional返回 |
<U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper) | flatMap与map相似,区别就是映射方法返回的就是Optional,直接使用该值返回 |
- Optional<Integer> a= Optional.ofNullable(2).filter(Objects::nonNull).map(p -> 2*p);
- Optional<Integer>b=Optional.of(2).filter(Objects::nonNull).flatMap(p->Optional.ofNullable(2*p));
收集是流操作中很重要的处理,在Collectors中提供了一些辅助工具方法帮助我们更加方法处理流
Collectors中提供了counting()方法用户统计流中元素的数量,如下文所示代码结果是5
Long collect = Stream.of(1, 2, 3, 4, 5).collect(Collectors.counting());
Collectors中提供了三个分别针对Integer,Double,Long求平均值的方法,不管是哪个方法返回数据类型都是double
- Double average = Stream.of(1, 2, 3, 4, 5).collect(Collectors.averagingInt(p -> p));
- average = Stream.of(1, 2, 3, 4, 5).collect(Collectors.averagingLong(p ->p));
- average = Stream.of(1, 2, 3, 4, 5).collect(Collectors.averagingDouble(p ->p));
Collectors也提供了求最大值和最小值的方法,具体示例如下文代码所示:
- Integer max = Stream.of(1, 2, 3, 4, 5).collect(Collectors.maxBy(Integer::compareTo)).orElse(0);
- Integer min = Stream.of(1, 2, 3, 4, 5).collect(Collectors.minBy(Integer::compareTo)).orElse(0);
- System.out.println("max value is " + max + ", min value is " + min);
Collectors提供了reducing方法用于递归计算,通过递归可以计算流中元素的和,乘积等如
| 方法 | 说明 |
reducing(BinaryOperator<T> op) | 没有初始值的递归处理返回结果为Optional, |
reducing(T identity, BinaryOperator<T> op) | 有初始值的递归处理,直接返回递归结果 |
reducing(U identity,
Function<? super T, ? extends U> mapper,
BinaryOperator<U> op) | 有初始值,对流中元素进行映射处理后进行递归 |
代码示例如下:
- Integer sum = Stream.of(1, 2, 3, 4, 5).collect(Collectors.reducing((x, y) -> x + y)).orElse(0);
-
- Integer sum2 = Stream.of(1, 2, 3, 4, 5).collect(Collectors.reducing(100, (x, y) -> x + y));
-
- Integer sum3 = Stream.of(1, 2, 3, 4, 5).collect(Collectors.reducing(100, p -> 2 * p, (x, y) -> x + y));
- System.out.println(sum + " , " + sum2 + " , " + sum3);
有时候我们在收集完成还需要对收集的结果进行一次处理,此时collectingAndThen方法就特别适合此场景;比如在计算出平均值以后,构造一个平均值是:xxx的字符串,就可以这样处理
String result = Stream.of(1, 2, 3, 4, 5).collect(Collectors.collectingAndThen(Collectors.averagingInt(p -> p), p -> "平均值是:" + p));
收集到集合是我们最常用的方法,主要的方法如下:
| 方法 | 说明 |
Collectors.toList() | 收集到List |
Collectors.toSet() | 收集到Set |
Collectors.toMap | 收集到Map |
Collectors.toUnmodifiableList() | 收集到不可变List |
Collectors.toUnmodifiableSet() | 收集到不可变Set |
Collectors.toUnmodifiableMap | 收集到不可变Map |
Collectors.toConcurrentMap | 收集到并发Map |
代码示例
- Stream.of(1, 2, 3, 4, 5).collect(Collectors.toList());
- Stream.of(1, 2, 3, 4, 5).collect(Collectors.toSet());
- Stream.of(1, 2, 3, 4, 5).collect(Collectors.toUnmodifiableList());
- Stream.of(1, 2, 3, 4, 5).collect(Collectors.toUnmodifiableSet());
-
- Stream.of(1, 2, 3, 4, 5).collect(Collectors.toMap(p->"key_"+p,p->p,(k,v)->v));
- Stream.of(1, 2, 3, 4, 5).collect(Collectors.toUnmodifiableMap(p->"key_"+p,p->p,(k,v)->v));
- Stream.of(1, 2, 3, 4, 5).collect(Collectors.toConcurrentMap(p->"key_"+p,p->p,(k,v)->v));
分组收集是流处理中比较复杂但是也是非常有用的处理。我们在工作中常常会遇到根据属性分组。比如有这样一组学生数据,我们需要按照性别分组,还有需要按照性别和姓进行多重分组我们就可以这样做:
- public class StreamDemo {
- public static void main(String[] args) {
-
-
- Map<String, List<Student>> genderGroup = Stream.of(new Student("男", "张", "三")
- , new Student("男", "李", "四"),
- new Student("男", "王", "五")
- , new Student("女", "李", "小草"),
- new Student("女", "王", "小花")
- ).collect(Collectors.groupingBy(p -> p.getGender(), Collectors.toList()));
-
-
- Map<String, Map<String,List<Student>>> multiGroup = Stream.of(new Student("男", "张", "三")
- , new Student("男", "李", "四"),
- new Student("男", "王", "五")
- , new Student("女", "李", "小草"),
- new Student("女", "王", "小花")
- ).collect(Collectors.groupingBy(p -> p.getGender(), Collectors.groupingBy(p->p.getFirstName())));
- System.out.println(genderGroup);
- System.out.println(multiGroup);
- }
-
- public static class Student {
- /**
- * 性别
- */
- private String gender;
-
- /**
- * 姓
- */
- private String firstName;
-
- /**
- * 名称
- */
- private String lastName;
-
- public Student(String gender, String firstName, String lastName) {
- this.gender = gender;
- this.firstName = firstName;
- this.lastName = lastName;
- }
-
- @Override
- public String toString() {
- return "Student{" +
- "gender='" + gender + '\'' +
- ", firstName='" + firstName + '\'' +
- ", lastName='" + lastName + '\'' +
- '}';
- }
-
- public String getGender() {
- return gender;
- }
-
- public void setGender(String gender) {
- this.gender = gender;
- }
-
- public String getFirstName() {
- return firstName;
- }
-
- public void setFirstName(String firstName) {
- this.firstName = firstName;
- }
-
- public String getLastName() {
- return lastName;
- }
-
- public void setLastName(String lastName) {
- this.lastName = lastName;
- }
- }
- }
输出的结果是:
- {女=[Student{gender='女', firstName='李', lastName='小草'}, Student{gender='女', firstName='王', lastName='小花'}], 男=[Student{gender='男', firstName='张', lastName='三'}, Student{gender='男', firstName='李', lastName='四'}, Student{gender='男', firstName='王', lastName='五'}]}
- {女={王=[Student{gender='女', firstName='王', lastName='小花'}], 李=[Student{gender='女', firstName='李', lastName='小草'}]}, 男={张=[Student{gender='男', firstName='张', lastName='三'}], 王=[Student{gender='男', firstName='王', lastName='五'}], 李=[Student{gender='男', firstName='李', lastName='四'}]}}