函数式接口

函数式接口

函数式接口:有且仅有一个抽象方法的接口

Java中的函数式编程体现就是Lambda表达式,所以函数式接口就是用于Lambda使用的接口

只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利推导

如何检验接口是否是函数式接口:

  • @FunctionalIneterface
  • 放于接口的上方:如果接口是函数式接口,编译通过;如果不是,编译失败

下面给出示例代码:

public class MyInterfaceDemo {
    public static void main(String[] args) {
        //我们采用lambda方法来创建接口对象
        MyInterface my = () -> {
            System.out.println("函数式接口");
        };
        //直接调用方法,方法是由lambda标注的
        my.show();
    }
}
//函数式接口标记
@FunctionalInterface
public interface MyInterface {
    void show();
}

函数式接口作为方法的参数

需求:

  • 定义一个类(RunnableDemo),在类中提供两个方法
    • startThread(Runnable r):方法参数是Runnable函数式接口
    • main():调用startThread方法

下面给出代码示例:

public class RunnableDemo {
    public static void main(String[] args) {
        //第一种方法:匿名函数类
        startThread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + ":" + "启动了");
            }
        });

        //第二种方法,lambda
        startThread(() -> { System.out.println(Thread.currentThread().getName() + ":" + "启动了");});
    }

    //定义方法
    public static void startThread(Runnable r)
    {
        new Thread(r).start();
    }
}

函数式接口作为方法的返回值

需求:

  • 定义一个类(ComparatorDemo),在类中提供两个方法
    • Comparator getComparator():方法返回值是一个Comparator,用作比较方法
    • main():调用 getComparator方法

下面给出代码示例:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;

public class ComparatorDemo {
    public static void main(String[] args) {
        //构造使用场景
        ArrayList<String> arrayList = new ArrayList<>();

        //先添加一些元素
        arrayList.add("aa");
        arrayList.add("ccc");
        arrayList.add("bbbb");
        arrayList.add("d");

        //我们输出查看结果:
        System.out.println(arrayList);

        //首先我们使用默认排序方法
        Collections.sort(arrayList);

        //我们输出查看结果:
        System.out.println(arrayList);

        //我们使用带Comparator的排序方法
        //这里我们通过GetComparator获得Comparator
        Collections.sort(arrayList,getComparator2());

        //我们输出查看结果:
        System.out.println(arrayList);
    }

    public static Comparator<String> getComparator1() {
        //这里我们通过构造器方法创建
        return new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.length() - o2.length();
            }
        };
    }

    public static Comparator<String> getComparator2() {
        //这里我们通过lambda方法来创建
        return (s1, s2) -> s1.length() - s2.length();
    }
}

函数式常用接口

下面我们介绍四种函数式常用接口:

  • Supplier接口:用于获得数据结果
  • Consumer接口:用于消费所加载的数据
  • Predicate接口:用于判断所加载的数据
  • Function接口:用于进行数据类型转换

Supplier接口

Supplier:包含一个无参的方法

  • T get():获得结果
  • 该方法不需要参数,会按照实现逻辑(Lambda表达式实现)返回一个数据
  • Supplier接口被称为生产型接口,如果我们指定了接口的泛型是什么类型,get方法就会产生什么类型

下面给出示例代码:

import java.util.function.Supplier;

public class Demo {
    public static void main(String[] args) {
        //我们输出由方法获得的值
        //这里是使用lambda作为参数
        System.out.println(getString(() -> "胡桃"));
        System.out.println(getInteger(() -> 30));
    }

    //GetString
    public static String getString(Supplier<String> sup){
        return sup.get();
    }

    //GetInteger
    public static Integer getInteger(Supplier<Integer> sup){
        return sup.get();
    }
}

练习:

  • 定义一个类(SupplierTest),在类中提供两个方法
    • int getMax():返回数组中最大的值
    • main():调用 getMax方法

下面给出示例代码:

import java.util.function.Supplier;

public class Demo1 {
    public static void main(String[] args) {
        //定义一个数组
        int[] arr = {2,13,44,76,52};

        //获得最大值
        int max = getMax(() -> {
            int maxValue = arr[0];
            for(int i=0;i< arr.length;i++){
                if(arr[i] > maxValue){
                    maxValue = arr[i];
                }
            }
            return maxValue;
        });
        System.out.println(max);
    }

    private static int getMax(Supplier<Integer> sup){
        return sup.get();
    }
}

Consumer接口

Consumer:包含两个方法

  • void accept(T t):对给定的参数执行此操作
  • default Consumer andThen(Consumer after):返回一个组合的Consumer,依次执行此操作,然后执行after操作
  • Consumer接口也被称为消费型接口,它消费的数据类型由泛型指定

下面给出示例代码:

import java.util.function.Consumer;

public class Demo1 {
    public static void main(String[] args) {
        //Consumer消费一个字符串
        operatorString1("胡桃",(String name) -> {
            System.out.println(name);
        });

        //Consumer不同方法消费同一个字符串
        operatorString2("胡桃",(String name)-> System.out.println(name),(String name) -> System.out.println(new StringBuilder(name).reverse().toString()));
    }

    //Consumer消费一个字符串
    public static void operatorString1(String name, Consumer<String> con){
        con.accept(name);
    }

    //Consumer不同方法消费同一个字符串
    public static void operatorString2(String name, Consumer<String> con1,Consumer<String> con2){
        con1.andThen(con2).accept(name);
    }
}

练习:

  • 创造一个String数组,数组以“姓名,年龄”来组成
  • 我们用Consumer接口来分别获取姓名和年龄,并输出

下面给出示例代码:

import java.util.function.Consumer;

public class Demo2 {
    public static void main(String[] args) {
        //创建一个数组
        String[] strArray = {"胡桃,18","钟离,20","七七,12"};

        //针对str做出输出
        printInfo(strArray,(String str) -> System.out.print(str.split(",")[0])
                ,(String str) -> System.out.println(Integer.parseInt(str.split(",")[1])));
    }

    //创造消费方法
    private static void printInfo(String[] strArray, Consumer<String> con1,Consumer<String> con2){
        for(String str : strArray){
            con1.andThen(con2).accept(str);
        }
    }
}

Predicate接口

Predicate:常用四个方法

  • boolean test(T t):对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值
  • dafault predicate negate():返回一个逻辑的否定,对应逻辑非
  • dafault predicate and():返回一个组合判断,对应短路与
  • dafault predicate or()返回一个组合判断,对应短路或
  • Predicate接口常用于判断参数是否满足指定条件

下面给出示例代码:

import java.util.function.Predicate;

public class Demo1 {
    public static void main(String[] args) {
        System.out.println(test("Jerry",(String s) -> s.length()>8));

        System.out.println(negateTest("Jerry",(String s) -> s.length()>8));

        System.out.println(andTest("Jerry",(String s) -> s.length()<8,(String s) -> s.length()>3));

        System.out.println(orTest("Jerry",(String s) -> s.length()>10,(String s) -> s.length()<3));
    }

    public static boolean test(String s, Predicate<String> pre){
        //对s进行测试,测试内容在main中用lambda完成
        return pre.test(s);
    }

    public static boolean negateTest(String s,Predicate<String> pre){
        //对s进行反向测试,得到的结果是相反结果
        return pre.negate().test(s);
    }

    public static boolean andTest(String s,Predicate<String> pre1,Predicate<String> pre2){
        //对s进行测试,测试是否同时满足两个条件
        return pre1.and(pre2).test(s);
    }

    public static boolean orTest(String s,Predicate<String> pre1,Predicate<String> pre2){
        //对s进行测试,测试是否满足至少一个条件
        return pre1.and(pre2).test(s);
    }
}

练习:

  • 我们给出String[] stArray
  • 通过Predicate接口获取满足条件的String并输出

下面给出示例代码:

import java.util.function.Predicate;

public class Demo2 {
    public static void main(String[] args) {
        //创造字符串对象
        String[] arr = {"芽衣,29","雷神,33","提亚娜,29"};

        //调用方法
        printInfo(arr,(String s) -> s.split(",")[0].length()>2,(String s) -> Integer.parseInt( s.split(",")[1])<30);
    }

    private static void printInfo(String[] strArray, Predicate<String> pre1,Predicate<String> pre2){
        for(String str : strArray){
            boolean b = pre1.and(pre2).test(str);
            if(b){
                System.out.println(str);
            }
        }
    }
}

Funciton接口

Function<T,R>:常用的两个方法

  • R apply(T t):将此函数应用于给定的参数
  • dafault Function andThen(Function after):返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果
  • Function<T,R>接口常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值

下面给出示例代码:

import java.util.function.Function;

public class Demo1 {
    public static void main(String[] args) {
        //方法1
        method1(100,(Integer i) -> String.valueOf(i+500));

        //方法2
        method2("200",(String s) -> Integer.parseInt(s));

        //方法3
        method3("200",(String s) -> Integer.parseInt(s),(Integer i) -> String.valueOf(i+500));
    }

    //方法1:把int类型+500转化为字符串类型
    private static void method1(int i, Function<Integer,String> fun){
        String s = fun.apply(i);
        System.out.println(s);
    }
    //方法2:把字符串类型转化为int类型
    private static void method2(String s, Function<String,Integer> fun){
        int i = fun.apply(s);
        System.out.println(s);
    }
    //方法3:把字符串类型,转化为int类型,int类型+500后转化为字符串类型输出
    private static void method3(String s, Function<String,Integer> fun1,Function<Integer ,String> fun2){
        String str = fun1.andThen(fun2).apply(s);
        System.out.println(str);
    }
}

练习:

  • 我们给出String s = “胡桃,20”;
  • 按下列步骤:
    • 将字符串截取到数字年龄部分
    • 将上一步的字符串转换为int类型
    • 将上一步的int类型+70后得到结果并输出
  • 请通过Function接口实现函数拼接
import java.util.function.Function;

public class Demo2 {
    public static void main(String[] args) {
        //调用方法:
        printInfo("胡桃,20",(String s) -> s.split(",")[1],(String s) -> Integer.parseInt(s),(Integer i) -> i + 70);
    }

    //方法
    private static void printInfo(String s, Function<String, String> fun1,Function<String,Integer> fun2,Function<Integer,Integer> fun3){
        System.out.println(fun1.andThen(fun2).andThen(fun3).apply(s));
    }
}

结束语

好的,关于函数式接口的内容就到这里

posted @ 2022-07-06 15:31  秋落雨微凉  阅读(65)  评论(0编辑  收藏  举报