常用的函数接口

常用的函数接口

  1. 函数式接口的使用

    • 接口MyFunctionalInterface

      package cn.xiaoge.day20.demo01;
      
      public class Demo {
      
          public static void show(MyFunctionalInterface myInter) {
              myInter.method();
          }
      
          public static void main(String[] args) {
              // 调用show方法, 方法的参数是一个接口, 所以可以传递接口的实现类对象
              show(new MyFunctionalInterfaceImpl());
      
              // 调用show方法, 方法的参数是一个接口, 所以我们可以传递接口的匿名内部类
              show(new MyFunctionalInterface() {
                  @Override
                  public void method() {
                      System.out.println("使用匿名内部类重写接口中的方法");
                  }
              });
      
              // 调用show方法, 方法的参数是一个函数式接口, 所以我们可以lambda表达式
              show(()->{
                  System.out.println("使用lambda重写接口中的方法");
              });
      
              // 使用lambda简化方式
              show(()-> System.out.println("使用lambda简化方式重写接口中的方法"));
          }
      
      }
      
    • 类MyFunctionalInterfaceImpl

      package cn.xiaoge.day20.demo01;
      
      /*
          @Override注解
          检查方法是否为重写方法
              是: 编译成功
              否: 编译失败
       */
      
      public class MyFunctionalInterfaceImpl implements MyFunctionalInterface{
          @Override
          public void method() {
              System.out.println("实现类重写接口中的方法");
          }
      }
      
      
    • demo

      package cn.xiaoge.day20.demo01;
      
      public class Demo {
      
          public static void show(MyFunctionalInterface myInter) {
              myInter.method();
          }
      
          public static void main(String[] args) {
              // 调用show方法, 方法的参数是一个接口, 所以可以传递接口的实现类对象
              show(new MyFunctionalInterfaceImpl());
      
              // 调用show方法, 方法的参数是一个接口, 所以我们可以传递接口的匿名内部类
              show(new MyFunctionalInterface() {
                  @Override
                  public void method() {
                      System.out.println("使用匿名内部类重写接口中的方法");
                  }
              });
      
              // 调用show方法, 方法的参数是一个函数式接口, 所以我们可以lambda表达式
              show(()->{
                  System.out.println("使用lambda重写接口中的方法");
              });
      
              // 使用lambda简化方式
              show(()-> System.out.println("使用lambda简化方式重写接口中的方法"));
          }
      
      }
      
      
      // 运行结果
      实现类重写接口中的方法
      使用匿名内部类重写接口中的方法
      使用lambda重写接口中的方法
      使用lambda简化方式重写接口中的方法
      
  2. 性能浪费日志案例&使用Lambda优化日志案例

    • 接口MessageBuilder

      package cn.xiaoge.day20.demo02;
      
      @FunctionalInterface
      public interface MessageBuilder {
      
          // 定义一个拼接消息的抽象方法, 返回被拼接的消息
          public abstract String builderMessage();
      
      }
      
      
    • Demo01Logger

      package cn.xiaoge.day20.demo02;
      
      /*
          日志案例
      
          发现以下代码存在的一个性能浪费问题
          调用showLog方法, 传递的第二个参数是一个拼接后的字符串
          先把字符串拼接好, 然后在调用showLog方法
          showLog方法中如果传递的日志登记不是1级
          那么就不会打印拼接后的字符串
          所以感觉字符串白拼接了, 存在浪费
       */
      
      public class Demo01Logger {
      
          public static void showLog(int level, String msg){
              if (level == 1) {
                  System.out.println(msg);
              }
          }
      
          public static void main(String[] args) {
              // 定义三个日志信息
              String msg1 = "Hello";
              String msg2 = "World";
              String msg3 = "Java";
      
              // 调用showLog方法, 传递日志级别和日志信息
              showLog(1, msg1+msg2+msg3);
          }
      
      }
      
      // 运行结果
      HelloWorldJava
      
    • Demo02Lambda

      package cn.xiaoge.day20.demo02;
      
      /*
          使用Lambda优化日志案例
          Lambda的特点: 延迟加载
          Lambda的使用前提, 必须存在函数式接口
       */
      
      import java.io.File;
      
      public class Demo02Lambda {
      
          // 定义一个现实日志的方法, 方法的参数传递日志的登记和MessageBuilder接口
          public static void showLog(int level, MessageBuilder msgBuild){
              if (level == 1){
                  System.out.println(msgBuild.builderMessage());
              }
      
          }
      
          public static void main(String[] args) {
              // 定义三个日志信息
              String msg1 = "Hello";
              String msg2 = "World";
              String msg3 = "Java";
      
              // 调用showLog方法, 参数MessageBuilder是一个函数式接口, 所以传递Lambda表达式
              showLog(1, ()->{
                  // 返回拼接的字符串
                  return msg1 + msg2 + msg3;
              });
      
              /*
                  使用Lambda表达式作为参数传递, 仅仅是吧参数传递到showLog方法中
                  只有满足条件, 日志的等级是1级
                      才会调用接口MessageBuilder中的方法builderMessage
                      才会进行字符串的拼接
                  如果条件不满足, 日志的等级不是1级
                      那么MessageBuilder接口中的方法builderMessage也不会执行
                      所以拼接字符串的代码也不会执行
                  所以不会存在性能浪费
               */
      
          }
      
      }
      
      // 运行结果
      HelloWorldJava
      
  3. 函数式接口作为方法参数案例

    • Demo01Runnable

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

    • Demo02Comparator

      package cn.xiaoge.day20.demo03;
      
      /*
          如果一个方法的返回值类型是一个函数式接口,那么就可以直接返回一个Lambda表达式。
          当需要通过一 个方法来获取一个 java.util.Comparator 接口类型的对象作为排序器时,就可以调该方法获取。
       */
      
      import java.util.Arrays;
      import 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", "b", "cccc", "dddddd"};
              // 输出排序前的数组
              System.out.println(Arrays.toString(arr));
              // 调用Arrays中的sort方法, 对字符串进行排序
              Arrays.sort(arr, getComparator());
              System.out.println(Arrays.toString(arr));
          }
      
      }
      
      
      // 运行结果
      [aaa, b, cccc, dddddd]
      [dddddd, cccc, aaa, b]
      
  5. 常用的函数式接口_Supplier接口

    • Demo01Supplier

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

      package cn.xiaoge.day20.demo04;
      
      /*
          练习: 求数组元素最大值
              使用Supplier接口作为方法的参数类型, 通过lambda表达式求出int数组中的最大值.
              提示: 接口的泛型请使用java.lang.Integer类.
       */
      
      import java.util.function.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 = {2, 4, 1, 6, 3, 7, 5};
              // 调用getMax方法, 方法的参数Supplier是一个函数式接口, 所以可以传递Lambda表达式
              int maxValue = getMax(()->{
                  // 获取数组的最大值, 并返回
                  // 定义一个变量, 把数组中的第一个元素赋值给该变量, 记录数组中元素的最大值
                 int max = arr[0]; // 最大值
                  // 遍历数组, 获取数组中的最大值
                 for(int i=1; i < arr.length; i++){
                     // 使用其他的元素和最大值比较
                     if (arr[i] > max) {
                         // 如果arr[i]大于max, 则替换max作为最大值
                         max = arr[i];
                     }
                 }
                 // 返回最大值
                 return max;
              });
              System.out.println("数组中元素的最大值: " + maxValue);
          }
      
      }
      
      
      // 运行结果
      数组中元素的最大值: 7
      
  6. 常用的函数式接口_Consumer

    • Demo01Consumer

      package cn.xiaoge.day20.demo05;
      
      /*
          java.util.function.Consumer<T>接口则正好与Supplier接口相反
              它不是生产一个数据, 而是消费一个数据, 其数据类型由泛型决定.
          Consumer接口中包含抽象方法void accept(T t), 意为消费一个指定泛型的数据
      
          Consumer接口是一个消费型接口, 它的泛型指定什么类型, 就可以使用accept方法消费什么类型的数据
          至于具体怎么消费(使用), 需要自定义(输出, 计算....)
       */
      
      import java.util.Arrays;
      import java.util.function.Consumer;
      
      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);
      
                  // 消费方式, 把字符串进行反转输出
                  // StringBuffer(name)  字符串缓冲区的内容就是该字符串值
                  // reverse反转数组值, 返回字符数组
                  // 重写了toString方法, 把字符数组转换为字符串
                  String reName = new StringBuffer(name).reverse().toString();
                  System.out.println(reName);
              });
          }
      
      }
      
      
      // 运行结果
      金泫雅
      雅泫金
      
    • Demo02AndThen

      package cn.xiaoge.day20.demo05;
      
      /*
          Consumer接口的默认方法andThen
          作用: 需要两个Consumer接口, 可以把两个Consumer接口组合到一起, 在对数据进行消费
      
          列如:
              Consumer<String> con1
              Consumer<String> con2
              String s = "hello";
              con1.accept(s);
              con2.accept(s);
      
              等同于
      
              链接两个Consumer接口  在进行消费
              con1.andThen(con2).accept(s); 谁写前边谁先消费
       */
      
      import java.util.function.Consumer;
      
      public class Demo02AndThen {
      
          // 定义一个方法, 方法的参数传递一个字符串和两个Consumer接口, Consumer接口的泛型使用字符串
          public static void method(String s, Consumer<String> con1, Consumer<String> con2) {
              // 使用andThen方法, 把两个Consumer接口链接到一起, 在消费数据
              con1.andThen(con2).accept(s); // con1链接con2, 先执行con1消费数据, 在执行con2消费数据
          }
      
          public static void main(String[] args) {
              method("Hello", (String s1)->{
                  // 把字符串转换为大写输出
                  System.out.println(s1.toUpperCase());
              }, (String s2)->{
                  // 把字符串转换为小写输出
                  System.out.println(s2.toLowerCase());
              });
          }
      
      }
      
      
      // 运行结果
      HELLO
      hello
      
    • Demo03Test

      package cn.xiaoge.day20.demo05;
      
      /*
          练习:
              字符串数组当中存有多条信息,请按照格式“ 姓名:XX。性别:XX。 ”的格式将信息打印出来。
              要求将打印姓 名的动作作为第一个 Consumer 接口的Lambda实例,
              将打印性别的动作作为第二个 Consumer 接口的Lambda实 例,
              将两个 Consumer 接口按照顺序“拼接”到一起
       */
      
      import java.util.function.Consumer;
      
      public class Demo03Test {
      
          // 定义一个方法, 参数传递String类型的数组和两个Consumer接口, 泛型使用String
          public static void method(String[] arr, Consumer<String> con1, Consumer<String> con2){
              for (String s : arr) {
                  // 使用呢andThen方法链接两个Consumer接口, 消费字符串
                  con1.andThen(con2).accept(s);
              }
      
          }
      
          public static void main(String[] args) {
              String[] arr = {"金泫雅,女", "金所炫,女", "权志龙,男"};
      
              method(arr, (String s1)->{
                  String name = s1.split(",")[0];
                  System.out.print("姓名: " + name);
              }, (String s2)->{
                  String gender = s2.split(",")[1];
                  System.out.println(".年龄: " + gender + ". ");
              });
          }
      
      }
      
      
      // 运行结果
      姓名: 金泫雅.年龄:. 
      姓名: 金所炫.年龄:. 
      姓名: 权志龙.年龄:. 
      
  7. 常用的函数式接口_Predicate

    • Demo01Predicate

      package cn.xiaoge.day20.demo06;
      
      /*
          java.util.function.Predicate<T>接口
          作用: 对某种数据类型的数据进行判断, 结果返回一个boolean值
      
          Predicate接口中包含一个抽象方法:
              boolean test(T t): 用来对指定数据类型数据进行判断的方法
                  结果:
                      符合条件, 返回true
                      不符合条件, 返回false
       */
      
      import java.util.function.Predicate;
      
      public class Demo01Predicate {
      
          /*
              定义一个方法
              参数传递一个String类型的字符串
              传递一个Predicate接口, 泛型使用String
              使用Predicate中的方法test对字符串进行判断, 并把判断的结果返回
           */
          public static boolean checkString(String s, Predicate<String> p) {
              return p.test(s);
          }
      
          public static void main(String[] args) {
              // 定义一个字符串
              String s = "abcdef";
      
              // 调用checkString方法对字符串进行校验, 参数传递字符串和Lambda表达式
              /*boolean isTrue = checkString(s, (String str)->{
                  return s.length() > 5;
      
              });*/
      
              // 优化Lambda
              boolean isTrue = checkString(s, (str)->s.length() > 5);
              System.out.println(isTrue);
          }
      
      }
      
      
      // 运行结果
      true
      
    • Demo02Predicate_and

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

      package cn.xiaoge.day20.demo06;
      
      /*
          逻辑表达式: 可以链接多个判断的条件
          &&: 与运算符, 有false则false
          ||: 或运算符, 有true则true
          !: 非(取反)运算符, 非真则假, 非假则真
      
          需求: 判断一个字符串, 有两个判断的条件
              1. 判断字符串的长度是否大于5
              2. 判断字符串中是否包含a
          满足一个条件, 我们就可以使用||运算符链接两个条件
      
          Predicate接口中有一个方法or, 表示或者关系, 也可以用于连接诶两个判断条件
          default Predicate<T> or(Predicate<? super T> other) {
              Objects.requireNonNull(other);
              return (t) -> this.test(t) || other.test(t);
          }
      
          方法内部的两个判断条件, 也是使用||运算符链接起来的.
       */
      
      import java.util.function.Predicate;
      
      public class Demo03Predicate_or {
      
          /*
              定义一个方法, 方法的参数, 传递一个字符串
              传递两个Predicate接口
                  一个用于判断字符串的长度是否大于5
                  一个用于判断字符串中是否包含a
                  满足一个条件即可
           */
          public static boolean method(String s, Predicate<String> p1, Predicate<String> p2) {
              // return p1.test(s) || p2.test(s);
              return p1.or(p2).test(s); // 等价于 return p1.test(s) || p2.test(s);
          }
      
          public static void main(String[] args) {
              String s = "abcde";
              boolean b = method(s, (String s1)->{
                  return s1.length() > 5;
              }, (String s2)->{
                  // contains判断字符串是否包含a
                  return s2.contains("a");
              });
              System.out.println(b);
          }
      
      
      }
      
      
      // 运行结果
      true
      
    • Demo04Predicate_negate

      package cn.xiaoge.day20.demo06;
      
      /*
          需求: 判断一个字符串长度是否大于5
              如果字符串的长度大于5, 那么返回false
              如果字符串的长度不大于5, 那么返回true
          所以我们可以使用取反符号!对判断的结果进行取反
      
          Predicate接口中有一个方法negate, 也表示取反的意思
          default Predicate<T> negate() {
              return (t) -> !test(t);
          }
       */
      
      import java.util.function.Predicate;
      
      public class Demo04Predicate_negate {
      
          /*
              定义一个方法, 方法的参数, 传递一个字符串
              使用Predicate接口判断字符串的长度是否大于5
           */
          public static boolean method(String s, Predicate<String> p) {
              return p.negate().test(s);
          }
      
          public static void main(String[] args) {
              boolean b = method("123456", (String s)->{
                  // 判断字符串的长度是否大于5, 并且返回结果
                  return s.length()>5;
              });
              System.out.println(b);
          }
      
      }
      
      
      // 运行结果
      false
      
    • Demo05Test

      package cn.xiaoge.day20.demo06;
      
      /*
          练习: 集合信息筛选
          数组当中有多条“姓名+性别”的信息如下,
          String[] array = { "迪丽热巴,女", "古力娜扎,女", "马尔扎哈,男", "赵丽颖,女" };
          请通过 Predicate 接口的拼装将符合要求的字符串筛选到集合 ArrayList 中,
          需要同时满足两个条件:
              1. 必须为女生;
              2. 姓名为4个字。
      
          分析:
              1. 有两个判断条件, 所以需要使用两个Predicate接口, 对条件进行判断
              2. 必须同时满足两个条件, 所以使用and方法链接两个判断
       */
      
      import java.util.ArrayList;
      import java.util.function.Predicate;
      
      public class Demo05Test {
      
          /*
              定义一个方法
              方法的参数传递一个包含人员信息的数组
              传递两个Predicate接口, 用于对数组中的信息进行过滤
              把满足条件的信息存到ArrayList集合中并返回
           */
          public static ArrayList<String> filter(String[] arr, Predicate<String> p1, Predicate<String> p2) {
              // 定义一个ArrayList集合, 存储过滤之后的信息
              ArrayList<String> list = new ArrayList<>();
              // 遍历数组, 获取数组中的每一条信息
              for (String s : arr) {
                  // 使用Predicate接口中的方法test多获取到的字符串进行判断
                  boolean b = p1.and(p2).test(s);
                  if(b){
                      // 条件成立, 两个条件都满足, 把信息存储到ArrayList集合中
                      list.add(s);
                  }
      
              }
              // 把集合返回
              return list;
          }
      
          public static void main(String[] args) {
              // 定义一个存储字符串的数组
              String[] arr = {"迪丽热巴,女", "古力娜扎,女", "马尔扎哈,男", "赵丽颖,女"};
      
              // 调用filter方法, 传递字符串数组和两个Lambda表达式
              ArrayList<String> list = (filter(arr, (String s1)->{
                      String name = s1.split(",")[0];
                      // 判断名字长度是否等于4
                      return name.length() == 4;
                  }, (String s2)->{
                      String gender = s2.split(",")[1];
                      // 判断性别是否为女
                      return "女".equals(gender);
                  }));
              System.out.println(list);
          }
      
      }
      
      
      // 运行结果
      [迪丽热巴,, 古力娜扎,]
      
  8. 常用的函数式接口_Function

    • Demo01Function

      package cn.xiaoge.day20.demo07;
      
      /*
          java.util.function.Function<T,R> 接口用来根据一个类型的数据得到另一个类型的数据,
              前者称为前置条件, 后者称为后置条件。
          Function 接口中最主要的抽象方法为: R apply(T t) ,根据类型T的参数获取类型R的结果。
              使用的场景例如:将 String 类型转换为 Integer 类型。
       */
      
      import java.util.function.Function;
      
      public class Demo01Function {
      
          /*
              顶一个方法
              方法的参数传递一个字符串类型的整数
              方法的参数列表传递一个Function接口, 泛型使用<String, Integer>
              使用Function接口中的方法apply, 把字符串类型的整数, 转换为Integer类型的整数
           */
          public static void change(String s, Function<String, Integer> f) {
              // Integer i = f.apply(s);
              int i = f.apply(s); // 自动拆箱
              System.out.println(i);
          }
      
          public static void main(String[] args) {
              // 调用change方法, 传递字符串类型的整数, 和Lambda表达式
              change("123456", (String s)->{
                  // 把字符串类型的整数, 转换为Integer类型的整数返回
                  return Integer.parseInt(s);
              });
      
              // 优化Lambda表达式
              change("123456", (String s)->Integer.parseInt(s));
          }
      
      }
      
      
      // 运行结果
      123456
      123456
      
    • Demo02Function_andThen

      package cn.xiaoge.day20.demo07;
      
      /*
          Function接口中的默认方法andThen: 用来进行组合操作
      
          需求:
              把String类型的"123", 转换为Integer类型, 把转换后的结果加10
              把增加之后的Integer类型的数据, 转换为String类型
      
          分析:
              转换了两次
              第一次是把String类型转换为了Integer类型
                  所以我们可以使用Function<String, Integer> f1
                      Integer num = f1.apply("123") + 10;
              第二次是把Integer类型转换为String类型
                  所以我们可以使用Function<Integer, String> f2
                      String s = f2.apply(num);
              我们可以使用andThen方法, 把两次转换组合在一起使用
                  String s = f1.andThen(f2).apply("123");
                  f1先调用apply方法, 把字符串转换为Integer
                  f2在调用apply方法, 把Integer转换为字符串
      
       */
      
      import java.util.function.Function;
      
      public class Demo02Function_andThen {
      
          public static void change(String s, Function<String, Integer> f1, Function<Integer, String> f2) {
              System.out.println(f1.andThen(f2).apply(s));
          }
      
          public static void main(String[] args) {
              change("123", (String s)->{
                  // 将字符串转换为Integer类型
                  int num = Integer.parseInt(s); // 自动拆箱
                  return num+10;
              }, (Integer num)->{
                  // 把Integer类型转换为字符串  也可以直接 + ""转换为字符串
                  String s = Integer.toString(num);
                  // getClass获取变量类型
                  System.out.println(s.getClass());
                  return s;
              });
      
              // 优化Lambda表达式
              change("123", (s)->Integer.parseInt(s)+10, (num)->Integer.toString(num));
      
          }
      
      }
      
      
      // 运行结果
      class java.lang.String
      133
      133
      
    • Demo03Test

      package cn.xiaoge.day20.demo07;
      
      /*
          练习:自定义函数模型拼接
          题目
          请使用 Function 进行函数模型的拼接,按照顺序需要执行的多个函数操作为:
              String str = "赵丽颖,20";
      
          分析:
              1. 将字符串截取数字年龄部分,得到字符串;
                  Function<String, String>  "赵丽颖,20" --> "20"
              2. 将上一步的字符串转换成为int类型的数字;
                  Function<String, Integer>  "20" --> 20
              3. 将上一步的int数字累加100,得到结果int数字。
                  Function<Integer, Integer>  20 --> 120
       */
      
      import java.util.function.Function;
      
      public class Demo03Test {
      
          /*
              定义一个方法
              参数传递包含姓名和年龄的字符串
              参数在传递3个Function接口用于类型转换
           */
          public static int change(String s, Function<String, String> f1, Function<String, Integer> f2, Function<Integer, Integer> f3) {
              // 使用andThen方法把三个转换组合到一起
              return f1.andThen(f2).andThen(f3).apply(s);
          }
      
          public static void main(String[] args) {
              // 调用change方法, 参数传递字符串和3个Lambda表达式
              int num = change("赵丽颖,20", (String s1)->{
                  // "赵丽颖,20" --> "20"
                  return s1.split(",")[1];
              }, (String s2)->{
                  // "20" --> 20
                  return Integer.parseInt(s2);
              }, (Integer i)->{
                  // 20 --> 120
                  return i+100;
              });
              System.out.println(num);
      
              // 优化Lambda表达式
              int num2 = change("赵丽颖,20", (s1)->s1.split(",")[1], (s2)->Integer.parseInt(s2), (i)->i+100);
              System.out.println(num2);
      
          }
      
      }
      
      
      // 运行结果
      120
      120
      
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只因为你温柔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值