• Lambda 在集合中的应用


    相对于构造匿名类or匿名函数, 其实lambda 在java8中, 大大加强了对数组操作的方便度

    List.sort 排序

    首先, 常用一下之前创建的Cat类。

    package com.home.javacommon.study.lambda;
    
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @NoArgsConstructor
    public class Cat {
    
        public Cat(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        private String name;
        private int age;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    传统list排序方法

    传统排序方法需要对Cat接口修改, 令它实现Comparable 接口, 重写compareTo 方法。 然后可以使用Collections.sort()方法进行排序。
    具体可以参考

    Java 中 Comparable 接口的意义和用法.



    其实传统方法有3个硬伤。

    1. 如果要排序的业务类,未实现Comparable 接口, 则有可能要修改该类(当然你也可以继承多1个子类), 违反了对修改封闭原则.
    2. 在业务类重写compareTo方法, 感觉不够优雅, 业务类不应该关心他们都对象如何被比较。
    3. 在compareTo定义好比较多规则不够灵活, 例如上面的Cat类, 我定义好按名字排序, 在客户端类如果要按其他属性(age)排序则很不方便。
    list.sort()方法

    java 8 中,增加了function包, java.util.function
    它里面集成了若干函数接口。

    其中1个Comparator接口可以用于排序方法 list.sort()
    这个是包内List类的sort 方法源码

       default void sort(Comparator<? super E> c) {
            Object[] a = this.toArray();
            Arrays.sort(a, (Comparator) c);
            ListIterator<E> i = this.listIterator();
            for (Object e : a) {
                i.next();
                i.set((E) e);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    可以看到, list.sort方法需要提供1个Comparator接口的对象, 而这个对象可以很方便地使用Lambda动态构建

    例子:

    @Component
    @Slf4j
    public class ExampleList1 implements Example {
    
        @FunctionalInterface
        private interface CatService{
            Cat getCat(String name, int age);
        }
    
    
        @Override
        public void runApp() {
    
            CatService catService=Cat::new;
    
            List<Cat> list = new ArrayList<>();
            list.add(catService.getCat("Alice", 5));
            list.add(catService.getCat("Dinesh", 3));
            list.add(catService.getCat("Cindy", 4));
            list.add(catService.getCat("Bill", 2));
    
            //sort by age
            list.sort((o1,o2) -> o1.getAge() - o2.getAge());
            log.info(list.toString());
    
            //sort by name with Reverse order
            list.sort((o1,o2) -> o2.getName().compareTo(o1.getName()));
            log.info(list.toString());
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    输出:

    2022-08-28 21:29:48.297  INFO 28960 --- [           main] c.h.j.study.lambda.list.ExampleList1     : [Cat(name=Bill, age=2), Cat(name=Dinesh, age=3), Cat(name=Cindy, age=4), Cat(name=Alice, age=5)]
    2022-08-28 21:29:48.298  INFO 28960 --- [           main] c.h.j.study.lambda.list.ExampleList1     : [Cat(name=Dinesh, age=3), Cat(name=Cindy, age=4), Cat(name=Bill, age=2), Cat(name=Alice, age=5)]
    
    • 1
    • 2

    可以看到 無論是按age排序還是按Name排序 , 只需要构造1个Comparator 对象, 告诉List 的比较规则,就可以对数组进行各种规则的排序了, 无需对业务类Cat进行任何的修改!

    List.forEach 遍历

    这也是java8 很常见的方法。
    forEach方法需要提供1个Consumer 接口对象。

    而这个方法的源码更加容易读懂

    default void forEach(Consumer<? super T> action) {
            Objects.requireNonNull(action);
            for (T t : this) {
                action.accept(t);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    就是我们要重写 Comsumer接口的accept方法, 相当于用accept方法的代码来对list中每1个对象进行处理

    例子:

            //iterate
            list.forEach((o)->log.info(o.toString()));
    
    • 1
    • 2

    输出:

    2022-08-28 21:29:48.299  INFO 28960 --- [           main] c.h.j.study.lambda.list.ExampleList1     : Cat(name=Dinesh, age=3)
    2022-08-28 21:29:48.300  INFO 28960 --- [           main] c.h.j.study.lambda.list.ExampleList1     : Cat(name=Cindy, age=4)
    2022-08-28 21:29:48.300  INFO 28960 --- [           main] c.h.j.study.lambda.list.ExampleList1     : Cat(name=Bill, age=2)
    2022-08-28 21:29:48.300  INFO 28960 --- [           main] c.h.j.study.lambda.list.ExampleList1     : Cat(name=Alice, age=5)
    
    • 1
    • 2
    • 3
    • 4

    其他方法不展开了
    学好Lambda对数组的处理方法, 能够大大减少甚至消灭嵌套地狱。
    而且大数量下处理集合的效率会更好。
    这也是函数式编程的核心。

    当然最重要的是能看懂公司其他高手写的代码拉!

  • 相关阅读:
    Redis Key操作
    11.我为 Netty 贡献源码 | 且看 Netty 如何应对 TCP 连接的正常关闭,异常关闭,半关闭场景
    【ACM算法竞赛日常训练】DAY10题解与分析【月月给华华出题】【华华给月月出题】| 筛法 | 欧拉函数 | 数论
    ROS机械臂 Movelt 学习笔记1 | 基础准备
    等差数列和等比数列 常用公式
    MySQL中如何进行表的优化和压缩?
    我有 7种 实现web实时消息推送的方案,7种!
    项目管理工具禅道
    大数据-玩转数据-Flink状态后端(下)
    软件设计——面向对象的七大原则
  • 原文地址:https://blog.csdn.net/nvd11/article/details/126576104