• JAVA中的函数接口,你都用过吗


    公众号「架构成长指南」,专注于生产实践、云原生、分布式系统、大数据技术分享。

    在这篇文章中,我们将通过示例来学习 Java 函数式接口。

    函数式接口的特点

    1. 只包含一个抽象方法的接口称为函数式接口。
    2. 它可以有任意数量的默认静态方法,但只能包含一个抽象方法。它还可以声明对象类的方法。
    3. 函数接口也称为单一抽象方法接口或SAM 接口。
    4. 函数式接口只有在没有任何抽象方法时才可以扩展另一个接口。
    5. Java API 具有许多单方法接口,例如 Runnable、Callable、Comparator、ActionListener等。它们可以使用匿名类语法来实现和实例化。

    接口示例

    创建一个自定义的Sayable接口,这是一个使用@FunctionalInterface注解的函数式接口。
    @FunctionalInterface注解表示该接口是一个函数式接口,并且只包含一个抽象方法。

    自定义函数接口示例
    @FunctionalInterface  
    interface Sayable{  
        void say(String msg);   // abstract method   
    }  
    
    • 1
    • 2
    • 3
    • 4

    让我们通过main()方法来演示一个自定义的函数式接口。我们使用Lambda表达式来实现函数式接口。

    public class FunctionalInterfacesExample {
    
        public static void main(String[] args) {
    
            Sayable sayable = (msg) -> {
                System.out.println(msg);
            };
            sayable.say("Say something ..");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    Predefined 函数接口

    Java提供了Predefined的函数式接口,通过使用 lambda 和方法引用来处理函数式编程。

    Predicate是检查条件的函数,它接受一个参数并返回boolean结果。

    让我们来看一下Predicate接口的内部实现。

    import java.util.function.Predicate;
    
    public interface Predicate<T> {
        boolean test(T t);
    
        default Predicate<T> and(Predicate<? super T> other) {
            // 默认方法的实现
            return (t) -> test(t) && other.test(t);
        }
    
        // 其他默认方法和静态方法...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    Predicate接口只包含一个抽象方法test(T t)同时它还包含默认方法和静态方法。

    让我们创建一个示例来演示Predicate函数式接口的用法:

    import java.util.Arrays;
    import java.util.List;
    import java.util.function.Predicate;
    
    public class Main {
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    
            // 使用Predicate接口检查数字是否为偶数
            Predicate<Integer> evenNumberPredicate = number -> number % 2 == 0;
            System.out.println("Even numbers:");
            printNumbers(numbers, evenNumberPredicate);
    
            // 使用Predicate接口检查数字是否大于5
            Predicate<Integer> greaterThanFivePredicate = number -> number > 5;
            System.out.println("Numbers greater than 5:");
            printNumbers(numbers, greaterThanFivePredicate);
        }
    
        public static void printNumbers(List<Integer> numbers, Predicate<Integer> predicate) {
            for (Integer number : numbers) {
                if (predicate.test(number)) {
                    System.out.println(number);
                }
            }
        }
    }
    
    • 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
    Function 函数接口

    Function函数接口是Java中的一个函数式接口,它定义了一个接收一个参数并返回结果的函数。它的定义如下:

    @FunctionalInterface
    public interface Function<T, R> {
        R apply(T t);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Function接口有两个泛型参数:T表示输入参数的类型,R表示返回结果的类型。它包含一个抽象方法apply(),接收一个类型为T的参数,并返回一个类型为R的结果。

    Function接口常用于将一个值转换为另一个值,或者对输入值进行处理和计算。它可以被用于各种场景,如数据转换、映射、计算和处理等。

    以下是一个使用Function函数接口的示例:

    import java.util.function.Function;
    
    public class Main {
        public static void main(String[] args) {
            // 创建一个Function接口来将字符串转换为大写
            Function<String, String> uppercaseFunction = str -> str.toUpperCase();
    
            // 使用Function接口将字符串转换为大写
            String result = uppercaseFunction.apply("hello world");
            System.out.println(result);  // 输出: HELLO WORLD
    
            // 使用Function接口将字符串转换为其长度
            Function<String, Integer> lengthFunction = str -> str.length();
            int length = lengthFunction.apply("hello");
            System.out.println(length);  // 输出: 5
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    Supplier 函数接口

    Supplier用于表示一个提供(供应)结果的函数。它通常用于延迟计算或在需要时生成值。通过调用get()方法,我们可以获取由Supplier实例提供的结果。

    以下是Consumer接口的实现

    @FunctionalInterface
    public interface Supplier<T> {
    
        /**
         * Gets a result.
         *
         * @return a result
         */
        T get();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    由于Supplier接口只有一个抽象方法,因此可以使用lambda表达式快速创建Supplier实例。下面是一个示例:

    import java.util.Random;
    import java.util.function.Supplier;
    
    public class Main {
        public static void main(String[] args) {
            // 创建一个Supplier接口来生成随机整数
            Supplier<Integer> randomIntegerSupplier = () -> new Random().nextInt();
    
            // 使用Supplier接口生成随机整数
            int randomNumber = randomIntegerSupplier.get();
            System.out.println(randomNumber);
    
            // 创建一个Supplier接口来生成当前时间戳
            Supplier<Long> timestampSupplier = () -> System.currentTimeMillis();
    
            // 使用Supplier接口生成当前时间戳
            long timestamp = timestampSupplier.get();
            System.out.println(timestamp);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    Consumer 函数接口

    Consumer用于表示接受一个参数并执行某些操作的函数。它定义了一个名为accept(T t)的抽象方法,接受一个参数,并且没有返回值。

    以下是Consumer接口的简化版本

    @FunctionalInterface
    public interface Consumer<T> {
        void accept(T arg0);
    }
    
    • 1
    • 2
    • 3
    • 4

    Consumer接口适用于那些需要对传入的参数进行某种操作,而不需要返回结果的情况。它可以用于在不同的上下文中执行各种操作,如打印、修改状态、更新对象等。
    下面是一个使用Consumer接口的示例:

    import java.util.Arrays;
    import java.util.List;
    import java.util.function.Consumer;
    
    public class Main {
        public static void main(String[] args) {
            List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Dave");
    
            // 使用Consumer接口打印每个名字
            Consumer<String> printName = name -> System.out.println(name);
            names.forEach(printName);
    
            // 使用Consumer接口修改每个名字为大写形式
            Consumer<String> uppercaseName = name -> {
                String uppercase = name.toUpperCase();
                System.out.println(uppercase);
            };
            names.forEach(uppercaseName);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在上述示例中,我们创建了两个Consumer接口的实例。第一个printName用于打印每个名字,第二个uppercaseName用于将每个名字转换为大写形式并打印。

    通过调用forEach()方法并传入相应的Consumer接口实例,我们可以对列表中的每个元素执行相应的操作。在示例中,我们对名字列表中的每个名字进行了打印和转换操作。

    Consumer接口的使用场景包括遍历集合、处理回调函数、更新对象状态等。它提供了一种简洁的方式来执行针对输入参数的操作,使得代码更加清晰和模块化。

    BiFunction 函数接口

    BiFunction函数式接口表示接受两个参数并返回结果的函数。它定义了一个名为apply(T t, U u)的抽象方法,接受两个参数,并返回一个结果。

    让我们来看一下BiFunction接口的简化版本。

    @FunctionalInterface
    public interface BiFunction<T, U, R> {
        R apply(T arg0, U arg1);
    }
    
    • 1
    • 2
    • 3
    • 4

    BiFunction接口适用于那些需要接受两个输入参数并产生结果的情况。它可以用于执行各种操作,如计算、转换、筛选等。
    下面是一个使用BiFunction接口的示例:

    import java.util.function.BiFunction;
    
    public class Main {
        public static void main(String[] args) {
            // 使用BiFunction接口计算两个数的和
            BiFunction<Integer, Integer, Integer> sumFunction = (a, b) -> a + b;
            int sum = sumFunction.apply(5, 3);
            System.out.println(sum);  // 输出: 8
    
            // 使用BiFunction接口将两个字符串拼接起来
            BiFunction<String, String, String> concatenateFunction = (str1, str2) -> str1 + str2;
            String result = concatenateFunction.apply("Hello, ", "World!");
            System.out.println(result);  // 输出: Hello, World!
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    BiConsumer函数接口

    BiConsumer接口,用于表示接受两个参数并执行某些操作的函数。它定义了一个名为accept(T t, U u)的抽象方法,接受两个参数,并且没有返回值。

    以下是BiConsumer接口的简化版本:

    import java.util.function.BiConsumer;
    
    @FunctionalInterface
    public interface BiConsumer<T, U> {
        void accept(T t, U u);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    BiConsumer接口适用于那些需要对传入的两个参数进行某种操作,而不需要返回结果的情况。它可以用于在不同的上下文中执行各种操作,如打印、修改状态、更新对象等。
    下面是一个使用BiConsumer接口的示例:

    import java.util.function.BiConsumer;
    
    public class Main {
        public static void main(String[] args) {
            // 使用BiConsumer接口打印两个数的和
            BiConsumer<Integer, Integer> sumPrinter = (a, b) -> System.out.println(a + b);
            sumPrinter.accept(5, 3);
    
            // 使用BiConsumer接口打印两个字符串的拼接结果
            BiConsumer<String, String> concatenationPrinter = (str1, str2) -> System.out.println(str1 + str2);
            concatenationPrinter.accept("Hello, ", "World!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    那些库或中间件再用BiConsumer

    BiPredicate 函数接口

    BiPredicate接口用于表示接受两个参数并返回一个布尔值的函数。它定义了一个名为test(T t, U u)的抽象方法,接受两个参数,并返回一个布尔值。

    以下是BiPredicate接口的简化版本:

    @FunctionalInterface 
    public interface BiPredicate<T, U> {
         boolean test(T t, U u);
         // Default methods are defined also
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    BiPredicate接口适用于那些需要对传入的两个参数进行某种条件判断,并返回布尔值的情况。它可以用于执行各种条件判断,如相等性比较、大小比较、复杂条件判断等。

    下面是一个使用BiPredicate接口的示例:

    import java.util.function.BiPredicate;
    
    public class Main {
        public static void main(String[] args) {
            // 使用BiPredicate接口判断两个数是否相等
            BiPredicate<Integer, Integer> equalityPredicate = (a, b) -> a.equals(b);
            boolean isEqual = equalityPredicate.test(5, 5);
            System.out.println(isEqual);  // 输出: true
    
            // 使用BiPredicate接口判断一个字符串是否包含另一个字符串
            BiPredicate<String, String> containsPredicate = (str1, str2) -> str1.contains(str2);
            boolean isContains = containsPredicate.test("Hello, World!", "World");
            System.out.println(isContains);  // 输出: true
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    只要5秒就能“克隆”本人语音!美玉学姐不再查寝,而是吃起了桃桃丨开源
    static
    Python学习----函数
    RT-DETR算法优化改进:Backbone改进|RIFormer:无需TokenMixer也能达成SOTA性能的极简ViT架构 | CVPR2023
    Java中的数组、Set、List、Map类型的互相转换总结
    登录验证的步骤
    在 Spring Boot 中使用 JDBI
    手机配合termux部署DDbot 教程
    【MySQL】表的增删改查(一)
    Jekyll 语句语法、功能的实现方法和结构介绍小手册
  • 原文地址:https://blog.csdn.net/dweizhao/article/details/134488963