02_Java语音进阶||day12【!】_函数式接口、函数式编程、常用函数式接口(Supplier、Consumer、Predicate、Function)

第一章 函数式接口

1.1 函数式接口的概念&函数式接口的定义

  1. 函数式接口在Java中是指:有且仅有一个抽象方法的接口
  2. 语法糖是指:使用更加方便,但是原理不变的代码语法。
    • 例:for-each就是迭代器的语法糖。
    • 应用层来讲:Lambda可以当做匿名内部类的语法糖
      • 但是二者原理是不同的。
      • 匿名内部类会生成.class文件($命名),但是Lambda不会
      • 所以Lambda效率高
  • 注:函数式接口:有且只有一个抽象方法的接口,称之为函数式接口
    • 当然接口中可以包含其他的方法(默认,静态,私有)

1.2 函数式接口的格式

1.3 函数式接口的@FunctionalInterface注解

  1. @FunctionalInterface注解->以后写函数式接口都加上
    • 作用:可以检测接口是否是一个函数式接口
      • 是:编译成功
      • 否:编译失败(接口中没有抽象方法抽象方法的个数多余1个)

1.4 函数式接口的使用

  1. 函数式接口的使用:一般可以作为方法的参数返回值类型【重点】

第二章 函数式编程

2.1 Lambda的延迟执行

2.1.1 性能浪费的日志案例

  1. 日志:
    • 可以帮助我们快速的定位问题,记录程序运行过程中的情况,以便项目的监控和优化
  2. 日志案例
    • 发现以下代码存在的一些性能浪费的问题【!】
    • 调用showLog方法,传递的第二个参数是一个拼接后的字符串
    • 先把字符串拼接好,然后在调用showLog方法
    • showLog方法中如果传递的日志等级不是1级
    • 那么就不会是如此拼接后的字符串
    • 所以感觉字符串就白拼接了,存在了浪费
    public class Demo01Logger {
        //定义一个根据日志的级别,显示日志信息的方法
        public static void showLog(int level, String message){
            //对日志的等级进行判断,如果是1级别,那么输出日志信息
            if(level == 1){
                System.out.println(message);
            }
        }
    
        public static void main(String[] args) {
            //定义三个日志信息
            String msg1 = "Hello";
            String msg2 = "World";
            String msg3 = "Java";
    
            //调用showLog方法,传递日志级别和日志信息
            showLog(1, msg1 + msg2 + msg3);
        }
    }
    
    //结果:
    HelloWorldJava

2.1.2 使用Lambda优化日志案例

  1. 使用Lambda优化日志案例
    • Lambda的特点:延迟加载【!】
    • Lambda的使用前提,必须存在函数式接口【!】
  2. 使用Lambda表达式作为参数传递,仅仅是把参数传递到showLog方法中
    1. 只有满足条件,日志的等级是1级
      • 才会调用接口MessageBuilder中的方法builderMessage
      • 才会进行字符串的拼接
    2. 如果条件不满足,日志的等级不是1级
      • 那么MessageBuilder接口中的方法builderMessage也不会执行
      • 所以拼接字符串的代码也不会执行
    • 所以不会存在性能的浪费
    //定义的函数式接口:MessageBuilder.java
    @FunctionalInterface
    public interface MessageBuilder {
        //定义一个拼接消息的抽象方法,返回被拼接的信息
        public abstract String builderMessage();
    }
    
    //主方法:Demo02Lambda.java
    public class Demo02Lambda {
        //定义一个显示日志的方法,方法的参数传递日志的等级和MessageBuilder接口
        public static void showLog(int level, MessageBuilder mb){
            //对日志的等级进行判断,如果是一级,则调用MessageBuilder接口中的builderMessage方法
            if(level == 1){
                System.out.println(mb.builderMessage());
            }
        }
    
        public static void main(String[] args) {
            //定义三个日志信息
            String msg1 = "Hello";
            String msg2 = "World";
            String msg3 = "Java";
    
            //调用showLog方法,参数MessageBuilder是函数式接口,所以可以传递Lambda表达式
            showLog(1, () -> {
                System.out.println("不满足条件不执行");
                //返回一个拼接好的字符串
                return msg1 + msg2 + msg3;
            });
    
        }
    }
    //结果:(满足时)
    不满足条件不执行
    HelloWorldJava
    //结果:(不满足)
    

2.2 函数式接口作为’方法的参数’案例

    /*
        例如java.lang.Runnable接口就是一个函数式接口,
        假设有一个startThread方法使用该接口作为参数,那么就可以使用Lambda进行传参。
        这种情况其实和Thread类的构造方法参数为Runnable没有本质区别。
     */
    public class Demo01Runnable {
        //定义一个方法startThread,方法的参数使用函数式接口Runnable
        public static void startThread(Runnable run){
            //开启多线程
            new Thread(run).start();
        }
    
        public static void main(String[] args) {
            //调用startThread方法,方法的参数是一个接口,那么我们可以传递这个接口的匿名内部类
            startThread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "-->" + "线程启动了");   //currentThread()当前正在执行的线程
                }
            });
    
            //调用startThread方法,方法的参数是一个函数式接口,所以可以传递Lambda表达式
            startThread(() -> {
                System.out.println(Thread.currentThread().getName() + "-->" + "线程启动了");   //currentThread()当前正在执行的线程
            });
    
            //优化Lambda
            startThread(() -> System.out.println(Thread.currentThread().getName() + "-->" + "线程启动了"));
        }
    }
    
    //结果:
    Thread-0-->线程启动了
    Thread-1-->线程启动了
    Thread-2-->线程启动了

2.3 函数式接口作为’方法的返回值类型’案例

    /*
        如果一个方法的返回值类型是一个函数式接口,那么就可以直接返回一个Lambda表达式。
        当需要通过一个方法来获取一个java.util.Comparator接口类型的对象作为排序器时,就可以调该方法获取。
     */
    public class Demo02Comparator {
        //定义一个方法,方法的返回值类型使用函数式接口Comparator
        public static Comparator<String> getComparator(){
            //方法的返回值类型是一个接口,那么我们可以返回这个接口的匿名内部类
            /*return new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    //按照字符串的降序排序
                    return o2.length()-o1.length();
                }
            };*/
    
            //方法的返回值类型是一个函数式接口,所有我们可以返回一个Lambda表达式
            /*return (String o1, String o2) -> {
                return o2.length()-o1.length();
            };*/
    
            //继续优化Lambda
            return (o1, o2) -> o2.length()-o1.length();
        }
    
        //主函数
        public static void main(String[] args) {
            //创建一个字符串数组
            String[] arr = {"aaa", "bb", "cccccc", "ddddddddddd"};
            //输出排序前的字符串
            System.out.println(Arrays.toString(arr));   //[aaa, bb, cccccc, ddddddddddd]
            //调用Arrays中的sort方法,对字符串数组进行排序
            Arrays.sort(arr, getComparator());
            //输出排序后的字符串
            System.out.println(Arrays.toString(arr));   //[ddddddddddd, cccccc, aaa, bb]
        }
    }
    
    //结果:
    [aaa, bb, cccccc, ddddddddddd]
    [ddddddddddd, cccccc, aaa, bb]

第三章 常用函数式接口

3.1常用的函数式接口_Supplier(供应商)接口

  1. java.util.function.Supplier接口仅包含一个无参的方法
    • T get()。用来获取一个泛型参数指定类型的对象数据。
    • Supplier接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据
    • 生产一个数据
    public class Demo01Supplier {
        //定义一个方法,方法的参数传递Supplier<T>接口,泛型执行String,get方法就会返回一个String
        public static String getString(Supplier<String> sup){
            return sup.get();
        }
    
    
        public static void main(String[] args) {
            //调用getString方法,方法的参数Supplier是一个函数式接口,所以可以传递Lambda表达式
            String s = getString(() -> {
                //生产一个字符串并返回
                return "胡歌";
            });
            System.out.println(s);
    
            //优化Lambda
            String s2 = getString(() -> "谷歌");
            System.out.println(s2);
        }
    }
    //结果:
    胡歌
    谷歌

3.2 Supplier接口练习_求数组元素最大值

    public class Demo02Test {
        //定义一个方法,用于获取int类型数组中元素的最大值,方法的参数传递Supplier接口,泛型使用Integer
        public static int getMax(Supplier<Integer> sup){
            return sup.get();
        }
    
        public static void main(String[] args) {
            //定义一个int类型的数组,并赋值
            int[] arr = {100, 22, -33, 88, 40, 0};
            //调用getMax方法,方法的参数Supplier是一个函数式接口,所以可以传递Lambda表达式
            int maxValue = getMax(() -> {
                //获取数组的最大值,并返回
                // 定义一个变量,把数组中的第一个元素赋值给该变量,记录数组中元素的最大值
                int max = arr[0];
                //遍历数组,获取数组中的其他元素
                for (int i : arr) {
                    //使用其他元素和最大值比较
                    if (i > max) {
                        //如果i大于max,则替换max作为最大值
                        max = i;
                    }
                }
                return max;
            });
            System.out.println("数组中最大的元素是:" + maxValue);
        }
    
    }
    
    //结果:
    数组中最大的元素是:100

3.3 常用的函数式接口_Consumer(消费者)接口

  1. java.util.function.Consumer接口则正好与Supplier接口相反,
    • 它不是生产一个数据,而是消费一个数据,其数据类型由泛型决定。
    • Consumer接口中包含抽象方法void accept(T t),意为消费一个指定泛型的数据
  2. Consumer接口是一个消费型接口,泛型执行什么类型,就可以使用accept方法消费什么类型的数据【总结】
    • 至于具体怎么消费(使用),需要自定义(输出,计算…)
    • 注:无返回值
    public class Demo01Consumer {
        /*
            定义一个方法
            方法的参数传递一个字符串的姓名
            方法的参数传递Consumer接口,泛型使用String
            可以使用Consumer接口消费字符串的姓名
         */
        public static void method(String name, Consumer<String> con){
            con.accept(name);
        }
    
        public static void main(String[] args) {
            //调用method方法,传递字符串姓名,方法的另一个参数是Consumer接口,是一个函数式接口,所以可以传递Lambda表达式
            method("赵丽颖", (String name) -> {
                //对传递的字符串进行消费
                //消费方式:直接输出
                //System.out.println(name); //赵丽颖
    
                //消费方式:反转
                String reName = new StringBuilder(name).reverse().toString();   //链式编程
                System.out.println(reName);
            });
        }
    }
    
    //结果:
    颖丽赵

3.4 Consumer接口的默认方法andThen

  1. Consumer接口的默认方法andThen
    • 作用:需要两个Consumer接口,可以把两个Consumer接口组合到一起,在对数据进行消费
    • 注:也可以多个接口连接在一起
         con1.andThen(con2).andThen(con3).accept(s);
    
  2. 例如:
        Consumer<String> con1
        Consumer<String> con2
        String s = "hello";
        
        con1.accept(s);
        con2.accept(s);
        
        连接两个Consumer接口  再进行消费
        con1.andThen(con2).accept(s); 谁写前边谁先消费
    
    • 注:谁写前边谁先消费
    public class Demo02AndThen {
        //定义一个方法,方法的参数传递一个字符串和两个Consumer接口,Consumer接口的泛型使用字符串
        public static void method(String s, Consumer<String> con1, Consumer<String> con2){
            //先使用普通方法
            //con1.accept(s);
            //con2.accept(s);
            //使用接口中默认方法andThen
            //连接两个Consumer接口  再进行消费
            con1.andThen(con2).accept(s); //谁写前边谁先消费
        }
    
    
        public static void main(String[] args) {
            //调用method方法,传递一个字符串,两个Lambda表达式
            method("Hello", (s) -> {
                //消费方法,将字符串转换为大写输出
                System.out.println(s.toUpperCase());
            }, (s) -> {
                //消费方法,将字符串转换为小写输出
                System.out.println(s.toLowerCase());
            });
        }
    }
    
    //结果:
    HELLO
    hello

3.5 Consumer接口练习_字符串拼接输出

    public class Demo03Test {
        //定义一个方法,参数传递String类型的数组和两个consumer接口,泛型使用String
        public static void printInfo(String[] arr, Consumer<String> con1, Consumer<String> con2){
            //遍历字符串数组
            for (String message : arr) {
                //使用andThen方法连接两个Consumer接口,消费字符串
                con1.andThen(con2).accept(message);
            }
        }
    
        public static void main(String[] args) {
            //定义一个字符串类型的数组
            String[] arr = {"迪丽热巴,女", "古力娜扎,女", "马尔扎哈,男"};
    
            //调用printInfo方法,传递一个字符串数组,和两个Lambda表达式
            printInfo(arr, (message) -> {
                //消费方式,对message进行切割,获取姓名,按照指定的格式输出
                String name = message.split(",")[0];    //字符串数组索引0保存的姓名
                System.out.print("姓名:" + name);
            }, (message) -> {
                //消费方式,对message进行切割,获取性别,按照指定的格式输出
                String sex = message.split(",")[1];    //字符串数组索引1保存的性别
                System.out.println(",姓名:" + sex + "。");
            });
        }
    }
    
    //结果:
    姓名:迪丽热巴,姓名:女。
    姓名:古力娜扎,姓名:女。
    姓名:马尔扎哈,姓名:男。

3.6 常用的函数式接口_Predicate(谓语)接口

  1. java.util.function.Predicate接口
    • 作用:对某种数据类型的数据进行判断,结果返回一个boolean值
    • 不能进行存储到集合的操作,需要自定义—>只是一个判断
    • 有返回值
  2. Predicate接口中包含一个抽象方法test
    • boolean test(T t):用来对指定数据类型数据进行判断的方法
      • 结果:
        • 符合条件,返回true
        • 不符合条件,返回false
    public class Demo01Predicate {
        /*
            定义一个方法
            参数传递一个String类型的字符串
            传递一个Predicate接口,泛型使用String
            使用Predicate中的方法test对字符串进行判断,并把判断的结果返回
         */
        public static boolean checkString(String s, Predicate<String> pre){
            return pre.test(s);
        }
    
        public static void main(String[] args) {
            //定义一个字符串
            String s = "abcde";
    
            //调用checkString方法对字符串进行校验,参数传递字符串和Lambda表达式
            /*boolean b = checkString(s, (String str) -> {
                //对参数传递的字符串进行判断,判断字符串的长度是否大于5,并把判断的结果返回
                return str.length() > 5;
            });*/
    
            //优化Lambda表达式
            boolean b = checkString(s, str -> str.length() > 5);
    
            System.out.println(b);
        }
    }
    
    //结果:
    false

3.7 Predicate接口_三个默认方法之_and

  1. 逻辑表达式:可以连接多个判断的条件
    • &&:与运算符,有false则false
    • ||:或运算符,有true则true
    • !:非(取反)运算符,非真则假,非假则真
  2. Predicate接口中有一个方法and,表示并且关系,也可以用于连接两个判断条件
        default Predicate<T> and(Predicate<? super T> other) {
            Objects.requireNonNull(other);
            return (t) -> this.test(t) && other.test(t);
        }
    
    • 方法内部的两个判断条件,也是使用&&运算符连接起来的
  3. 练习需求:判断一个字符串,有两个判断的条件
    1. 判断字符串的长度是否大于5
    2. 判断字符串中是否包含a
    • 两个条件必须同时满足,我们就可以使用&&运算符连接两个条件
    public class Demo02Predicate_and {
        /*
            定义一个方法,方法的参数,传递一个字符串
            传递两个Predicate接口
                一个用于判断字符串的长度是否大于5
                一个用于判断字符串中是否包含a
                两个条件必须同时满足
         */
        public static boolean checkString(String s, Predicate<String> pre1, Predicate<String> pre2){
            return pre1.and(pre2).test(s);  //等价于return pre1.test(s) && pre2.test(s);
        }
    
        public static void main(String[] args) {
            //定义一个字符串
            String s = "abcdef";
            //调用checkString方法,参数传递字符串和两个Lambda表达式
            boolean b = checkString(s, (String str) -> {
                //判断字符串的长度是否大于5
                return str.length() > 5;
            }, (String str) -> {
                //判断字符串中是否包含a
                return str.contains("a");
            });
            System.out.println(b);
        }
    }
    
    //结果:
    true

3.8 Predicate接口_三个默认方法之_or

  1. Predicate接口中有一个方法or,表示或者关系,也可以用于连接两个判断条件
        default Predicate<T> or(Predicate<? super T> other) {
            Objects.requireNonNull(other);
            return (t) -> test(t) || other.test(t);
        }
    
  2. 方法内部的两个判断条件,也是使用||运算符连接起来的
  3. 练习:需求:判断一个字符串,有两个判断的条件
    1. 判断字符串的长度是否大于5
    2. 判断字符串中是否包含a
    • 满足一个条件即可,我们就可以使用||运算符连接两个条件
    public class Demo03Predicate_or {
        /*
                定义一个方法,方法的参数,传递一个字符串
                传递两个Predicate接口
                    一个用于判断字符串的长度是否大于5
                    一个用于判断字符串中是否包含a
                    满足一个条件即可
             */
        public static boolean checkString(String s, Predicate<String> pre1, Predicate<String> pre2){
            //return pre1.test(s) || pre2.test(s);
            return  pre1.or(pre2).test(s);//等价于return pre1.test(s) || pre2.test(s);
        }
    
        public static void main(String[] args) {
            //定义一个字符串
            String s = "bcgggg";
            //调用checkString方法,参数传递字符串和两个Lambda表达式
            boolean b = checkString(s,(String str)->{
                //判断字符串的长度是否大于5
                return str.length()>5;
            },(String str)->{
                //判断字符串中是否包含a
                return str.contains("a");
            });
            System.out.println(b);
        }
    }
    
    //结果:
    true

3.9 Predicate接口_三个默认方法之_&negate(否定)

  1. Predicate接口中有一个方法negate,也表示取反的意思
        default Predicate<T> negate() {
            return (t) -> !test(t);
        }
    
  2. 练习需求:判断一个字符串长度是否大于5
    1. 如果字符串的长度大于5,那返回false
    2. 如果字符串的长度不大于5,那么返回true
    * 所以我们可以使用取反符号!对判断的结果进行取反
    public class Demo04Predicate_negate {
        /*
               定义一个方法,方法的参数,传递一个字符串
               使用Predicate接口判断字符串的长度是否大于5
        */
        public static boolean checkString(String s, Predicate<String> pre){
            return pre.negate().test(s);    //等效于return !pre.test(s);
        }
    
    
        public static void main(String[] args) {
            //定义一个字符串
            String s = "abc";
            //调用checkString方法,参数传递字符串和Lambda表达式
            /*boolean b = checkString(s, (String str) -> {
                return str.length() > 5;
            });*/
    
            //优化Lambda
            boolean b = checkString(s, str -> str.length() > 5);
    
            System.out.println(b);
        }
    
    }
    
    //结果:
    true

3.10 Predicate接口练习_集合信息筛选

    public class Demo05Test {
        /*
            定义一个方法
            方法的参数传递一个包含人员信息的数组
            传递两个Predicate接口,用于对数组中的信息进行过滤
            把满足条件的信息存到ArrayList集合中并返回
         */
        public static ArrayList<String> filter(String[] arr, Predicate<String> pre1, Predicate<String> pre2){
            //定义一个ArrayList集合,存储过滤后的信息
            ArrayList<String> listA = new ArrayList<>();
            //遍历数组,获取数组中的每一条信息
            for (String s : arr) {  //是arr不是listA
                //使用Predicate接口中的方法test对获取到的字符串进行判断
                boolean b = pre1.and(pre2).test(s);
                //对得到的boolean值进行判断
                if(b){
                    //条件成立,两个条件都满足,把信息存储到ArrayList集合中
                    listA.add(s);
                }
            }
            //把集合返回
            return listA;
        }
    
        public static void main(String[] args) {
            //定义一个存储字符串的数组
            String[] array = { "迪丽热巴,女", "古力娜扎,女", "马尔扎哈,男", "赵丽颖,女" };
            //调用filter方法,传递字符串数组和两个Lambda表达式
            ArrayList<String> listA = filter(array, (String str) -> {
                //必须为女生
                return str.split(",")[1].equals("女");
            }, (String str) -> {
                //姓名为4个字。
                return str.split(",")[0].length()==4;
            });
    
            //遍历集合
            for (String s : listA) {
                System.out.println(s);
            }
        }
    }
    
    //结果:
    迪丽热巴,女
    古力娜扎,女

3.11 常用的函数式接口_Function接口

  1. java.util.function.Function<T,R>:接口用来根据一个类型的数据得到另一个类型的数据
    • 前者称为前置条件,后者称为后置条件。
  2. Function接口中最主要的抽象方法为:R apply(T t):根据类型T的参数获取类型R的结果。
  3. 练习:使用的场景例如:将String类型转换为Integer类型。
    public class Demo01Function {
        /*
            定义一个方法
            方法的参数传递一个字符串类型的整数
            方法的参数传递一个Function接口,泛型使用<String,Integer>
            使用Function接口中的方法apply,把字符串类型的整数,转换为Integer类型的整数
         */
        public static void change(String s, Function<String, Integer> fun){
            Integer in = fun.apply(s);  //也可以写成int,自动拆箱Integer->int
            System.out.println(in);
        }
    
        public static void main(String[] args) {
            //定义一个字符串类型的整数
            String s = "1234";
            //调用change方法,传递字符串类型的整数,和Lambda表达式
            /*change(s, (String str) -> {
                //把字符串类型的整数,转换为Integer类型的整数返回
                return Integer.parseInt(str);
            });*/
            
            //优化Lambda
            change(s, str -> Integer.parseInt(str));
        }
    }
    
    //结果:(Integer类型了)
    1234

3.12 Function接口_默认方法andThen

  1. Function接口中的默认方法andThen:用来进行组合操作
  2. 需求:
    1. 把String类型的"123",转换为Inteter类型,把转换后的结果加10
    2. 把增加之后的Integer类型的数据,转换为String类型
  3. 分析:
    • 转换了两次
    1. 第一次是把String类型转换为了Integer类型
      • 所以我们可以使用Function<String,Integer> fun1
        • Integer i = fun1.apply(“123”)+10;
    2. 第二次是把Integer类型转换为String类型
      • 所以我们可以使用Function<Integer,String> fun2
        • String s = fun2.apply(i);
    • 我们可以使用andThen方法,把两次转换组合在一起使用
      • String s = fun1.andThen(fun2).apply(“123”);
      • fun1先调用apply方法,把字符串转换为Integer
      • fun2再调用apply方法,把Integer转换为字符串
    public class Demo02Function_andThen {
        /*
            定义一个方法
            参数串一个字符串类型的整数
            参数再传递两个Function接口
                一个泛型使用Function<String,Integer>
                一个泛型使用Function<Integer,String>
         */
        public static void change(String s, Function<String, Integer> fun1, Function<Integer, String> fun2){
            String ss = fun1.andThen(fun2).apply(s);
            System.out.println(ss);
        }
    
        public static void main(String[] args) {
            //定义一个字符串类型的整数
            String s = "123";
            //调用change方法,传递字符串和两个Lambda表达式
            /*change(s, (String str) -> {
                //把字符串转换为整数 + 10
                return Integer.parseInt(str) + 10;
            }, (Integer i) -> {
                //把整数转换为字符串
                return i + "";
            });*/
    
            //优化Lambda
            change(s, str -> Integer.parseInt(str) + 10, i -> i + "");
        }
    }
    
    //结果:
    133

3.13 Function接口练习_自定义函数模型拼接

  1. 分析:
    1. 将字符串截取数字年龄部分,得到字符串;
      Function<String,String> “赵丽颖,20”->“20”
    2. 将上一步的字符串转换成为int类型的数字;
      Function<String,Integer> “20”->20
    3. 将上一步的int数字累加100,得到结果int数字。
      Function<Integer,Integer> 20->120
    public class Demo03Test {
        /*
            定义一个方法
            参数传递包含姓名和年龄的字符串
            参数再传递3个Function接口用于类型转换
         */
        public static int change(String s, Function<String, String> fun1, Function<String, Integer> fun2, Function<Integer, Integer> fun3){
            return fun1.andThen(fun2).andThen(fun3).apply(s);
        }
    
        public static void main(String[] args) {
            //定义一个字符串
            String str = "赵丽颖,20";
            //调用change方法,参数传递字符串和3个Lambda表达式
            /*int num = change(str, (String s) -> {
                //将字符串截取数字年龄部分,得到字符串
                //"赵丽颖,20"->"20"
                return s.split(",")[1];
            }, (String s) -> {
                //"20"->20
                return Integer.parseInt(s);
            }, (Integer i) -> {
                //20->120
                return i + 100;
            });*/
    
            //简化Lambda
            int num = change(str, s -> s.split(",")[1], s -> Integer.parseInt(s), i -> i + 100);
    
            System.out.println(num);
        }
    }
    
    //结果:
    120
发布了42 篇原创文章 · 获赞 6 · 访问量 1127

猜你喜欢

转载自blog.csdn.net/qq_40572023/article/details/104852716
今日推荐