美文网首页
Lambda结合函数式接口的使用

Lambda结合函数式接口的使用

作者: 手扶拖拉机_6e4d | 来源:发表于2023-08-07 11:53 被阅读0次

函数式接口, 一般可以作为方法的参数和返回值类型

  • 案例1:函数式接口作为方法的参数
#自定义函数式接口
package FunctionInterface;
public interface MyFunctionInterface {
    public abstract void method();
}
public class functionDemo {
    public static void show(MyFunctionInterface myFunctionInterface) {
        myFunctionInterface.method();
    }

public static void main(String[] args) {
     // 方式1
    // 调用show方法,参数是一个接口,可以传递接口的匿名内部类
        show(new MyFunctionInterface(){
            @Override
            public void method() {
                System.out.println("使用匿名内部类重写抽象方法");
            }
        });

        // 方式2
       // Lambda表达式
        show(() ->{
            System.out.println("Lambda表达式实现");
        });
}
  • 函数式接口作为参数
public class functionDemo {
      public static void threadStart(Runnable run) {
        new Thread(run).start();
    }

    // 方式1:匿名内部类
  threadStart(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "启动了");
            }
        });
    // 注意:参数Runnabl 一个函数式接口,并且只有一个抽象方法(run),可以传递Lambda表达式
    //方式2: Lambda表达式
    threadStart(() -> System.out.println(Thread.currentThread().getName() + "启动了"));
}

输出:

Thread-0启动了
Thread-1启动了
  • 案例2:函数式接口作为返回值
# 对字符串按照字符长度倒序

package FunctionInterface;
import java.util.Arrays;
import java.util.Comparator;

public class LambdaReturn {
    public static Comparator<String> getComparator(){
        //方式1:方法的返回值类型是一个接口,我们可以返回这个接口的匿名内部类
/*
        return new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                // 按照字符串的降序排列
                return o2.length() - o1.length();
            }
        };
*/
  
        // 方式1: 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[] strList = {"abc", "bcd", "wudy", "petwr", "world"};
        System.out.println("排序前=" + Arrays.toString(strList));
        Arrays.sort(strList, getComparator());
        System.out.println("排序后=" + Arrays.toString(strList));
    }
}

输出:

排序前=[abc, bcd, wudy, petwr, world]
排序后=[petwr, world, wudy, abc, bcd]
  • 案例3: Lambda延迟执行
  • 有些场景的代码执行后,结果一定会被使用,从而造成性能浪费,而Lambda是延迟执行的,正好可以作为解决方案
    性能浪费的日志案例:对日志消息进行拼接后,在满足条件的情况下进行打印输出
package FunctionInterface;

public class LambdaDelay {
    public static void main(String[] args) {
        String msg1 = "hello";
        String msg2 = "world";
        String msg3 = "java";
        showLog(2, msg1 + msg2 + msg3);
    }

    public static void showLog(int level, String msg) {
        if (level == 1) {
            System.out.println("日志级别等于1" + msg);
        }
    }

注意: 上述代码存在的问题: 拼接的字符串在level != 1 的时候并没有用到,存在性能浪费

  • 优化如下:
  • 使用Lambda优化日志案例
    特点:延时加载, 定义一个显式日志的方法,方法的参数传递日志的等级和MessageBuilder接口
    使用Lambda表达式作为参数传递,仅仅是把参数传递到showLog方法中
    只有满足条件(日志等级是1),才会调用接口MessageBuilder中的方法messageBuilder
    如果不满足条件,日志的等级不是1,那么接口MessageBuilder中的方法messageBuilder不会执行
    所以拼接字符串的代码也不会执行所以不会存在性能的浪费
package FunctionInterface;
@FunctionalInterface
public interface MessageBuilder {
    // 定义一个拼接消息的抽象方法, 返回被拼接的消息
    public abstract String builderMessage();
}
package FunctionInterface;

public class LambdaDelay {
    public static void main(String[] args) {
        String msg1 = "hello";
        String msg2 = "world";
        String msg3 = "java";
        showLog(1, () -> {
            return msg1 + msg2 + msg3;
        });
    }

   private static void showLog2(int level, MessageBuilder messageBuilder) {
        if (1 == level) {
            System.out.println("测试啥时候进来这里啊!");
            System.out.println(messageBuilder.builderMessage());;
        }
    }

结论: 当level==2的时候,不会进入Lambda表达式中,就不会执行字符串拼接,从而节省性能

  • 案例4: 使用Supplier接口作为方法参数类型
Supplier 被称之为生产型接口,指定接口的范型是什么类型,那么接口中的get方法就会生产什么类型的数据
package FunctionInterface;

import java.util.function.Supplier;
public class SupplierDemo {
    public static void main(String[] args) {
       // 调用getSupplier方法, 方法的参数Supplier是一个函数式接口,所以可以传递Lambda表达式
       String name = getSupplier(() -> {
               return "wudy";
       });

      //String name = getSupplier(() -> "wudy");
      System.out.println(name);
    }

      public static String getSupplier(Supplier<String> supplier) {
           return supplier.get();
    }
}

输出:

wudy
  • Supplier接口作为方法参数类型, 通过Lambda表达式求出int数组中的最大值
package FunctionInterface;

import java.util.function.Supplier;
public class SupplierDemo {
    public static void main(String[] args) {
         Integer[] list = {88, 10, -12, -34, 0, 65, 102};
         int maxValue = getMax(() -> {
             System.out.println("second");
              int max = list[0];
              for (int i: list) {
                  if (i > max) {
                      max = i;
                  }
              }
              return max;
        });

        System.out.println(maxValue);
  }

    public static Integer getMax(Supplier<Integer> supplier) {
        System.out.println("first");
        return supplier.get();
    }
}

输出:

first
second
102
Consumer接口是一个消费型接口,范型指定什么类型,就可以使用accept方法消费什么类型的数据
  • 案例5: Consumer反转字符串
package FunctionInterface;

import java.util.function.Consumer;
public class ConsumerDemo {
    public static void main(String[] args) {
        method("wudy", (String name) -> {
            // 重写accept
            // 反转字符串
            String revName = new StringBuffer(name).reverse().toString();
            System.out.println(revName);
        });
    }

      public static void method(String name, Consumer<String> consumer){
            consumer.accept(name);
    }
}

输出:

yduw
  • AndThen方法: 需要两个Consumer接口,可以把两个Consumer接口组合到一起,再对数据进行消费
package FunctionInterface;
import java.util.function.Consumer;

public class ConsumerAndThen {
    public static void main(String[] args) {
        method("Hello World", (String name) -> {
            System.out.println("执行con1=" + name.toUpperCase());
        }, (String name) -> {
            System.out.println("执行con2=" + name.toLowerCase());
        });
    }

      public static void method(String s, Consumer<String> con1, Consumer<String> con2){
          // 先执行con2消费数据,再执行con1消费数据
          con2.andThen(con1).accept(s);
    }
}

输出:

执行con2=hello world
执行con1=HELLO WORLD
  • AndThen方法: 格式化打印信息
  • 将下面的字符串按照格式"姓名:XX。性别:XX" 的格式打印出来,要求将打印姓名的动作作为第一个Consumer接口的Lambda实例,
    将打印性别的动作作为第二个Consumer接口的Lambda实例,将两个Consumer接口按照顺序拼接到一起
package FunctionInterface;
import java.util.function.Consumer;

public class FormatPrint {

    public static void main(String[] args) {
        String[] strList = {"wudy,男","peter,女","timo,女"};

        for (String str: strList) {
            printInfo(str, (String name) -> {
                name = str.split(",")[0];
                System.out.print("姓名:" + name);
            }, (String sex) -> {
                sex = str.split(",")[1];
                System.out.println("。性别:" + sex + "。");
            });
        }
    }

    public static void printInfo(String str, Consumer<String> con1, Consumer<String> con2) {
        con1.andThen(con2).accept(str);
    }
}

输出:

姓名:wudy。性别:男。
姓名:peter。性别:女。
姓名:timo。性别:女。
  • 有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果
package FunctionInterface;
import java.util.function.Predicate;

public class PredicateDemo {
    public static void main(String[] args) {
        String str = "macBookPro";
        boolean b = checkString(str, (String s) -> s.length() >15);

        System.out.println(b);
    }

    public static boolean checkString(String str, Predicate<String> predicate) {
        return predicate.test(str);
    }
}

输出:

false

相关文章

  • lambda表达式

    前言: lambda是结合函数式接口使用的 函数式接口是指只有一个抽象方法的接口

  • Java8实战之-Lambda

    应该在什么地方使用Lambda表达式 你可以在函数式的接口上使用Lambda表达式。什么是函数式接口?接口只定义了...

  • jdk8新特性-方法引用

    简单实例,解决Lambda表达式的冗余 定义函数式接口 调用函数式接口 使用对象名引用成员变量 函数式接口 创建对...

  • JDK8新特性 内置函数式接口

    1. 内置函数式接口由来 lambda表达式的前提是需要有函数式接口。而且lambda表达式使用时不关心接口名,抽...

  • Java8的lambda表达式和streamAPI举例

    lambda表达式 使用 总结 函数式接口:接口内只有一个抽象方法 何时使用函数式接口:当需要对这些接口进行实例化...

  • Java—Java 8 新增特性详解(Predicate和Str

    Predicate接口 Predicate接口介绍   Predicate是函数式接口,可以使用Lambda表达式...

  • JDK8新特性 - 函数式编程

    一、JDK8之自定义函数式编程 1.使用Lambda表达式,自定义lambda接口编程 定义⼀个函数式接口 需要标...

  • Lambda表达式总结

    Lambda表达式总结使用范例以及例子Lambda表达式基础语法函数式接口Lambda练习Java8四大内置函数式...

  • 42 函数式接口

    函数式接口在Java中是有且只有一个抽象方法的接口,java中就是使用Lambda接口作为函数式接口 定义接口格式...

  • Java基础-Java8特性-Lambda表达式和Stream

    Lambda表达式可以理解为:简写的函数式接口的实现。对于“函数式接口”的简化写法(和其他特性结合构成更加简洁的代...

网友评论

      本文标题:Lambda结合函数式接口的使用

      本文链接:https://www.haomeiwen.com/subject/bprycktx.html