• 23、匿名类的排序、Lambda 表达式、方法引用


    一、匿名类排序

    ☘️ Java 官方通过匿名类这种语法,让使用者可以传入不同的排序逻辑(是升序排序,还是倒序排序)

    🔖 可以使用java.util.Arrays类对数组进行排序

    Arrays.sort() 进行升序排序:

    public class TestDemo {
        public static void main(String[] args) {
            int[] ints = {5, 2, 0, 1, 3, 1, 4, 8, 7, 22, 35, 51, 6};
    
            /* 使用 Arrays.toString() 可以打印数组里面的内容 */
            // [5, 2, 0, 1, 3, 1, 4, 8, 7, 22, 35, 51, 6]
            System.out.println(Arrays.toString(ints));
    
            /* Arrays.sort() 可对数组进行升序排序(默认就是升序排序) */
            Arrays.sort(ints);
    
            // [0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 22, 35, 51]
            System.out.println(Arrays.toString(ints));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    ☘️ 通过该方法还可对数组进行倒顺序排序,这就需要通过匿名类语法传入排序逻辑了。

    Arrays.sort() 进行降序排序:

    public class TestDemo {
        public static void main(String[] args) {
            Integer[] intArr = {5, 2, 0, 1, 3, 1, 4, 8, 7, 22, 35, 51, 6};
    
            /* 使用 Arrays.toString() 可以打印数组里面的内容 */
            // [5, 2, 0, 1, 3, 1, 4, 8, 7, 22, 35, 51, 6]
            System.out.println(Arrays.toString(intArr));
    
            /* Arrays.sort() 可对数组进行降序排序 */
            Arrays.sort(intArr, new Comparator<Integer>() {
                @Override
                public int compare(Integer i1, Integer i2) {
                    // return 0; // 相当于没有进行排序操作
                    // return i1 - i2; // 升序排序
                    return i2 - i1; // 降序排序
                }
            });
    
            // [51, 35, 22, 8, 7, 6, 5, 4, 3, 2, 1, 1, 0]
            System.out.println(Arrays.toString(intArr));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    ☘️ Comparator 是 jdk 自带的一个接口
    ☘️ Comparator 中有一个 compare 方法(compare 方法中可以指定是降序还是升序)【具体看上面的代码】

    二、Lambda 表达式

    (1) Lambda 基本使用

    🔖 Lambda Expression 是 Java8 开始才有的语法

    🔖 函数式接口(Functional Interface):只包含1个抽象方法的接口(可以包含多个默认方法和静态方法)

    📕 可以在接口上加上@FunctionalInterface注解,表示它是一个函数式接口

    🔖 当匿名类实现的是函数式接口的时候,可以使用 Lambda 表达式简化代码的书写(但是匿名类和 Lambda 在作用域上还是有点区别的)


    Lambda 表达式格式:

       /*
           Lambda 表达式格式:
           (parameter list) -> {
               return xxx;
           }
        */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    📕 Lambda 表达式的格式和 JavaScript 中的箭头函数非常相似
    📕 parameter list:指函数式接口里面唯一的抽象方法的参数列表(若那个唯一的抽象方法没有参数,可不写)

    计算代码执行时间的工具类(上篇文章介绍的):

    /**
     * 计算某段代码的执行时间
     */
    public class CodeTimes {
    
        @FunctionalInterface
        public interface BlockInter {
            void passCode();
        }
    
        public static void check(String description, BlockInter codeBlock) {
        	if(codeBlock == null) return;
        	
            System.out.println("\n----------------------------");
            System.out.println("测试功能:" + description);
            long beginTime = System.currentTimeMillis();
    
            codeBlock.passCode();
    
            long endTime = System.currentTimeMillis();
            long duration = (endTime - beginTime) / 1000;
            System.out.println("代码执行花费时间:" + duration + "秒");
            System.out.println("----------------------------");
        }
    }
    
    • 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
    public class TestDemo {
        public static void main(String[] args) {
            CodeTimes.check("简单测试1", () -> {
                String string = "Happy";
                for (int i = 0; i < 50000; i++) {
                    string += i;
                }
            });
    
            CodeTimes.check("简单测试2", () -> {
                test();
            });
        }
    
        private static void test() {
            StringBuilder string = new StringBuilder("Happy");
            for (int i = 0; i < 50000; i++) {
                string.append(i);
            }
        }
    
        /*
                ----------------------------
                测试功能:简单测试1
                代码执行花费时间:6秒
                ----------------------------
    
                ----------------------------
                测试功能:简单测试2
                代码执行花费时间:0秒
                ----------------------------
         */
    }
    
    • 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
    • 32
    • 33

    📕 本篇文章第一节中用到的 Arrays.sort() 进行降序排序的时候使用到的 Comparator 也是函数式接口
    📕 它的书写方式也可以使用 Lambda 表达式进行简化

    Lambda 简化 Arrays.sort() 进行降序排序时候的 Comparator 接口的写法:

    public class TestDemo {
        public static void main(String[] args) { 
            Integer[] intArr = {1, 3, 5, 7, 9, 2, 6, 8, 10};
            
            // 降序排序
            Arrays.sort(intArr, (Integer i1, Integer i2) -> {
                return i2 - i1;
            });
    
            // [10, 9, 8, 7, 6, 5, 3, 2, 1]
            System.out.println(Arrays.toString(intArr));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    (2) Lambda 更加简化

    ✏️ 参数列表可以省略参数类型
    ✏️ 当只有一条语句的时候:可以省略大括号、分号和return
    ✏️ 当只有一个参数的时候:可以省略小括号(一个参数都没有的时候不能省略小括号)
    更加简化后的降序排序代码:

    public class TestDemo {
        public static void main(String[] args) {
            Integer[] intArr = {1, 3, 5, 7, 9, 2, 6, 8, 10};
    
            // 降序排序
            Arrays.sort(intArr, (i1, i2) -> i2 - i1);
    
            // [10, 9, 8, 7, 6, 5, 3, 2, 1]
            System.out.println(Arrays.toString(intArr));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    (3) Lambda 使用注意

    ✏️ Lambda 只能访问 final 或有效 final 的局部变量(和匿名类一样)
    ✏️ Lambda 没有引入新的作用域(和匿名类不同)

    @FunctionalInterface
    interface Testable {
        void test(int p);
    }
    
    public class OuterClass {
        private int age = 666;
    
        public class InnerClass {
            private int age = 888;
    
            void inner() {
                // int p = 123; // ERROR: Variable p is already defined in the scope
                Testable t = p -> { // p 只能在 Lambda 的大括号里面使用
                    System.out.println(p); // 678
                    System.out.println(age); // 888 (Lambda 表达式没有引入新的作用域)
                    System.out.println(this.age); // 888 (Lambda 表达式没有引入新的作用域)
                    System.out.println(InnerClass.this.age); // 888
                    System.out.println(OuterClass.this.age); // 666
                };
                t.test(678);
            }
        }
    }
    
    class TestDemo {
        public static void main(String[] args) {
            OuterClass outerClass = new OuterClass();
            OuterClass.InnerClass innerClass = outerClass.new InnerClass();
            innerClass.inner();
        }
    }
    
    • 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
    • 32

    匿名类和 Lambda 表达式区别测试代码:

    @FunctionalInterface
    interface Testable {
        void test(int p);
    }
    
    public class OuterClass {
        private int age = 666;
    
        public class InnerClass {
            private int age = 888;
    
            void inner() {
                /* 匿名类类似局部类(可以访问外部类的所有成员) */
                Testable t = new Testable() {
                    // int age = 5;
    
                    @Override
                    public void test(int p) {
                        // System.out.println(this.age); // ERROR:age 未定义
                        System.out.println(age); // 888
                        System.out.println(p); // 678
                    }
                };
                t.test(678);
            }
        }
    }
    
    • 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

    三、方法引用

    ✏️ 方法引用:Method Reference
    ✏️ 若 Lambda 中的内容仅仅是调用某个方法,可以使用方法引用来简化
    ✏️ Lambda 表达式是对匿名类的简化,方法引用是对 Lambda 表达式的简化

    🌻 引用静态方法:ClassName::staticMethodName
    🌻 引用特定对象的实例方法:ObjectName::instanceMethodName
    🌻 引用特定类型的任意对象的实例方法:ClassName::methodName
    🌻 引用构造方法:Class:new
    🌻 引用当前类中定义的实例方法:this::instanceMethodName
    🌻 引用父类中定义的实例方法:super::instanceMethodName

    💡 平时写代码的时候把它写成 Lambda 表达式即可,编译器会帮忙简化代码的书写

  • 相关阅读:
    内网渗透神器CobaltStrike之Beacon详解(三)
    Spring Security 集成 Authing CAS 认证(一)
    王道链表综合题(中)
    美摄AR人像美颜,全新视觉体验
    腾讯觅影数智医疗影像平台获颁世界互联网领先科技成果大奖
    主从复制和读写分离
    网站整站优化-网站整站优化工具
    Armv9 Cortex-A720的L2 memory system 和 L2 Cache
    JavaWeb、JDBC
    编辑距离问题
  • 原文地址:https://blog.csdn.net/m0_54189068/article/details/126867342