• 一文掌握Lambda表达式(下)


    一文掌握Lambda表达式(上)icon-default.png?t=M5H6https://mp.csdn.net/mp_blog/creation/editor/125460693

    目录

    一、Optional

    1.1 建造Optional

    1.2 是否有值 

    1.3 获取值 

    1.4 过滤与映射 

    二、Collectors

    2.1 计数

    2.2 平均值 

    2.3 最值计算

    2.4 递归计算 

    2.5 收集并转换

    2.6 收集到集合

    2.5 分组收集


    一、Optional

     Optional是JDK1.8引入的一个对象容器,主要用作方法返回类型,如果存在值则isPresent()方法返回true否则返回false。下面我们看看具体方法如何使用

    1.1 建造Optional

          optional提供了两个静态建造方法of()和ofNullable;下面看看两者有什么区别

    方法说明
    of(T value)

    value不能为null,如果value是null则会抛出

    NullPointerException

    ofNullable(T value)
    value可以为null
    1. try {
    2. //of方法value不允许为null,如果为null 则抛出NullPointerException
    3. Optional.of(null);
    4. } catch (NullPointerException npe) {
    5. npe.printStackTrace();
    6. }
    7. //ofNullable允许值为null
    8. Optional<Object> nonValueOptional = Optional.ofNullable(null);

    1.2 是否有值 

     Optional中提供了连个静态方法判断是否有值,分别是isEmpty()和isPresent;两者语义相反

    方法说明
    isEmpty()如果值为null则返回true,否则返回false;JDK 11以后提供
    isPresent()如果值不为null则返回true,否则返回false,JDK8只能使用这个方法

    1.3 获取值 

    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新增

    1.4 过滤与映射 

        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,直接使用该值返回
    1. Optional<Integer> a= Optional.ofNullable(2).filter(Objects::nonNull).map(p -> 2*p);
    2. Optional<Integer>b=Optional.of(2).filter(Objects::nonNull).flatMap(p->Optional.ofNullable(2*p));

     

    二、Collectors

    收集是流操作中很重要的处理,在Collectors中提供了一些辅助工具方法帮助我们更加方法处理流

    2.1 计数

    Collectors中提供了counting()方法用户统计流中元素的数量,如下文所示代码结果是5

    Long collect = Stream.of(1, 2, 3, 4, 5).collect(Collectors.counting());

    2.2 平均值 

    Collectors中提供了三个分别针对Integer,Double,Long求平均值的方法,不管是哪个方法返回数据类型都是double

    1. Double average = Stream.of(1, 2, 3, 4, 5).collect(Collectors.averagingInt(p -> p));
    2. average = Stream.of(1, 2, 3, 4, 5).collect(Collectors.averagingLong(p ->p));
    3. average = Stream.of(1, 2, 3, 4, 5).collect(Collectors.averagingDouble(p ->p));

    2.3 最值计算

     Collectors也提供了求最大值和最小值的方法,具体示例如下文代码所示:

    1. Integer max = Stream.of(1, 2, 3, 4, 5).collect(Collectors.maxBy(Integer::compareTo)).orElse(0);
    2. Integer min = Stream.of(1, 2, 3, 4, 5).collect(Collectors.minBy(Integer::compareTo)).orElse(0);
    3. System.out.println("max value is " + max + ", min value is " + min);

    2.4 递归计算 

    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)
    有初始值,对流中元素进行映射处理后进行递归

    代码示例如下: 

    1. Integer sum = Stream.of(1, 2, 3, 4, 5).collect(Collectors.reducing((x, y) -> x + y)).orElse(0);
    2. Integer sum2 = Stream.of(1, 2, 3, 4, 5).collect(Collectors.reducing(100, (x, y) -> x + y));
    3. Integer sum3 = Stream.of(1, 2, 3, 4, 5).collect(Collectors.reducing(100, p -> 2 * p, (x, y) -> x + y));
    4. System.out.println(sum + " , " + sum2 + " , " + sum3);

    2.5 收集并转换

      有时候我们在收集完成还需要对收集的结果进行一次处理,此时collectingAndThen方法就特别适合此场景;比如在计算出平均值以后,构造一个平均值是:xxx的字符串,就可以这样处理

    String result = Stream.of(1, 2, 3, 4, 5).collect(Collectors.collectingAndThen(Collectors.averagingInt(p -> p), p -> "平均值是:" + p));
    

    2.6 收集到集合

    收集到集合是我们最常用的方法,主要的方法如下:

    方法说明
    Collectors.toList()
    收集到List
    Collectors.toSet()
    收集到Set
    Collectors.toMap
    收集到Map
    Collectors.toUnmodifiableList()
    收集到不可变List
    Collectors.toUnmodifiableSet()
    收集到不可变Set
    Collectors.toUnmodifiableMap
    收集到不可变Map
    Collectors.toConcurrentMap
    收集到并发Map

    代码示例

    1. Stream.of(1, 2, 3, 4, 5).collect(Collectors.toList());
    2. Stream.of(1, 2, 3, 4, 5).collect(Collectors.toSet());
    3. Stream.of(1, 2, 3, 4, 5).collect(Collectors.toUnmodifiableList());
    4. Stream.of(1, 2, 3, 4, 5).collect(Collectors.toUnmodifiableSet());
    5. Stream.of(1, 2, 3, 4, 5).collect(Collectors.toMap(p->"key_"+p,p->p,(k,v)->v));
    6. Stream.of(1, 2, 3, 4, 5).collect(Collectors.toUnmodifiableMap(p->"key_"+p,p->p,(k,v)->v));
    7. Stream.of(1, 2, 3, 4, 5).collect(Collectors.toConcurrentMap(p->"key_"+p,p->p,(k,v)->v));

    2.5 分组收集

     分组收集是流处理中比较复杂但是也是非常有用的处理。我们在工作中常常会遇到根据属性分组。比如有这样一组学生数据,我们需要按照性别分组,还有需要按照性别和姓进行多重分组我们就可以这样做:

    1. public class StreamDemo {
    2. public static void main(String[] args) {
    3. Map<String, List<Student>> genderGroup = Stream.of(new Student("男", "张", "三")
    4. , new Student("男", "李", "四"),
    5. new Student("男", "王", "五")
    6. , new Student("女", "李", "小草"),
    7. new Student("女", "王", "小花")
    8. ).collect(Collectors.groupingBy(p -> p.getGender(), Collectors.toList()));
    9. Map<String, Map<String,List<Student>>> multiGroup = Stream.of(new Student("男", "张", "三")
    10. , new Student("男", "李", "四"),
    11. new Student("男", "王", "五")
    12. , new Student("女", "李", "小草"),
    13. new Student("女", "王", "小花")
    14. ).collect(Collectors.groupingBy(p -> p.getGender(), Collectors.groupingBy(p->p.getFirstName())));
    15. System.out.println(genderGroup);
    16. System.out.println(multiGroup);
    17. }
    18. public static class Student {
    19. /**
    20. * 性别
    21. */
    22. private String gender;
    23. /**
    24. * 姓
    25. */
    26. private String firstName;
    27. /**
    28. * 名称
    29. */
    30. private String lastName;
    31. public Student(String gender, String firstName, String lastName) {
    32. this.gender = gender;
    33. this.firstName = firstName;
    34. this.lastName = lastName;
    35. }
    36. @Override
    37. public String toString() {
    38. return "Student{" +
    39. "gender='" + gender + '\'' +
    40. ", firstName='" + firstName + '\'' +
    41. ", lastName='" + lastName + '\'' +
    42. '}';
    43. }
    44. public String getGender() {
    45. return gender;
    46. }
    47. public void setGender(String gender) {
    48. this.gender = gender;
    49. }
    50. public String getFirstName() {
    51. return firstName;
    52. }
    53. public void setFirstName(String firstName) {
    54. this.firstName = firstName;
    55. }
    56. public String getLastName() {
    57. return lastName;
    58. }
    59. public void setLastName(String lastName) {
    60. this.lastName = lastName;
    61. }
    62. }
    63. }

    输出的结果是:

    1. {女=[Student{gender='女', firstName='李', lastName='小草'}, Student{gender='女', firstName='王', lastName='小花'}], 男=[Student{gender='男', firstName='张', lastName='三'}, Student{gender='男', firstName='李', lastName='四'}, Student{gender='男', firstName='王', lastName='五'}]}
    2. {女={王=[Student{gender='女', firstName='王', lastName='小花'}], 李=[Student{gender='女', firstName='李', lastName='小草'}]}, 男={张=[Student{gender='男', firstName='张', lastName='三'}], 王=[Student{gender='男', firstName='王', lastName='五'}], 李=[Student{gender='男', firstName='李', lastName='四'}]}}

  • 相关阅读:
    C++学习笔记
    【面试经典150 | 栈】最小栈
    Synchronized 与 Lock 卖票问题、区别
    C++ 多态:(使用Shape类层次结构的多态性的屏幕管理器)开发一个基本图形软件包
    谷粒商城实战笔记-142-性能压测-压力测试-Apache JMeter安装使用
    Metabase学习教程:仪表盘-2
    java实现异步回调返回给前端
    集合框架的认识(三)
    使用BENCHMARKSQL工具对KingbaseES执行测试时报错funcs sh file not found
    计算机程序设计艺术习题解答(Excercise 1.2.2-28~30题)
  • 原文地址:https://blog.csdn.net/zhangwei_david/article/details/125537895