首页 > 基础资料 博客日记

Java 函数式接口详解及使用

2024-10-15 04:00:06基础资料围观84

文章Java 函数式接口详解及使用分享给大家,欢迎收藏Java资料网,专注分享技术知识

在 Java 中,函数式接口(Functional Interface)是指只包含一个抽象方法的接口。函数式接口是 Java 8 引入的概念,用于支持函数式编程,并且可以通过 lambda 表达式来实例化。

函数式接口具有以下特点:

  1. 只包含一个抽象方法,但可以包含多个默认方法或静态方法。

  2. @FunctionalInterface 注解来显式声明该接口是函数式接口(虽然这个注解并不是必需的,主要用于编译级错误检查,加上该注解,当接口不符合函数式接口定义的时候,编译器会报错。此注解不是编译器将接口识别为功能接口的必要条件,而仅是帮助捕获设计意图并获得编译器帮助识别意外违反设计意图的帮助。)。

Java 标准库中有一些内置的函数式接口,比如 java.util.function 包中的一些接口,如 Function<T, R>Consumer<T>Predicate<T> 等。这些接口都是函数式接口的典型例子。

一、 Function

Function 接口源码

从源码中可以看到 Function 接口中有四个方法:

  • R apply (T t):接受一个参数 t,并返回一个结果。这是 Function 接口中的唯一抽象方法。
  • compose:将另一个函数作为参数传递给当前函数,然后返回一个先执行传入函数,再执行当前函数的函数。
  • andThen:将当前函数执行完毕后的结果作为参数传递给另一个函数,并返回另一个函数的执行结果。
  • identity:返回一个执行输入参数的函数。

下面是一个简单的示例,演示了如何使用 Function 接口的 apply 方法以及默认方法 andThencompose

public static void function_test(){
        Function<Integer, Integer> addOne = x -> x + 1;
        Function<Integer, Integer> multiplyByTwo = x -> x * 2;
        //使用 apply 方法
        System.out.println("addOne.apply:"+addOne.apply(2));
        System.out.println("multiplyByTwo.apply:"+multiplyByTwo.apply(2));

        // 使用 compose 方法进行函数组合
        Function<Integer, Integer> multiplyByTwoAndThenAddOne = addOne.compose(multiplyByTwo);
        System.out.println("addOne.compose(multiplyByTwo):"+multiplyByTwoAndThenAddOne.apply(3));

        // 使用 andThen 方法进行函数组合
        Function<Integer, Integer> addOneAndThenMultiplyByTwo = addOne.andThen(multiplyByTwo);
        System.out.println("addOne.andThen(multiplyByTwo):"+addOneAndThenMultiplyByTwo.apply(3));


    }
addOne.apply:3
multiplyByTwo.apply:4
addOne.compose(multiplyByTwo):7
addOne.andThen(multiplyByTwo):8

identity 方法是 Function 接口中的一个默认方法。它返回一个执行输入参数的函数。换句话说,Function.identity () 方法返回一个函数,该函数接受一个参数并返回相同的参数,即它是一个恒等函数。

在函数式编程中,identity 方法通常用于在函数组合操作中作为起始点或终止点,或者用作默认的转换函数。

下面是一个简单的示例,演示了 identity 方法的使用:

public static void main(String[] args) {
        Function<String, String> identityFunction = Function.identity();
        
        String result = identityFunction.apply("Hello, world");
        System.out.println(result);  // 输出结果为 "Hello, world"
    }

当我们理解了这个函数接口后,我们可以在 java.util.function 包下面看到许多其它类似的函数接口

比如 BiFunction 接口,接受两个参数并返回一个结果的函数

IntFunction 接口,仅支持 int 类型参数

其它的这里就不一一列举了

二、Consumer 消费者

Consumer 接口是 Java 中的一个函数式接口,用于表示接受单个输入参数并不返回结果的操作。它通常用于执行一些操作,比如对参数进行处理、打印输出或者进行其他副作用。

Consumer 源码

Consumer 接口定义了一个名为 accept 的抽象方法,该方法接受一个参数并执行操作,不返回任何结果。除了抽象方法之外,Consumer 接口还包含了一个默认方法,用于函数的组合、转换和操作。

  • void accept (T t):接受一个参数 t,并执行操作,不返回任何结果。这是 Consumer 接口中的唯一抽象方法。

  • andThen:将当前消费者执行完毕后,继续执行另一个消费者。

Consumer 接口通常用于需要对输入参数执行一些操作,而不需要返回结果的情况。它允许开发人员定义并传递需要执行一些操作的函数,从而支持更灵活的函数式编程。
以下是一个简单的示例,演示了如何使用 Consumer 接口:

public static void consumer_test(){
        Consumer<Integer> addOne =  x -> {
            x = x + 1;
            System.out.println("addOne:"+x);
        };
        addOne.accept(2);

        Consumer<Integer> multiplyByTwo = x -> {
            x = x * 2;
            System.out.println("multiplyByTwo:"+x);
        };
        addOne.andThen(multiplyByTwo).accept(2);

    }
addOne:3
addOne:3
multiplyByTwo:4

从结果中可以看出 andThen 方法是将两个方法组合成了一个方法,然后调用方法是参数初始值是同一个,但不是同一个对象,类似

Consumer<Integer> addOne =  x -> {
 x = x + 1;
    System.out.println("addOne:"+x);
};
Consumer<Integer> multiplyByTwo = x -> {
    x = x * 2;
    System.out.println("multiplyByTwo:"+x);
};
addOne.accept(2);
multiplyByTwo.accept(2);
addOne:3
multiplyByTwo:4

同样的,在 java.util.function 包下面看到许多其它类似的函数接口,原理也差不多

三、Predicate 谓语

Predicate接口是 Java 中的一个函数式接口,它代表着一个断言(即一个布尔类型的函数),接受一个参数并返回一个布尔值。在Predicate接口中,通常会定义一个名为test 的抽象方法,用于对给定的参数进行条件判断。
Predicate 源码

Predicate 接口中定义了几个方法,这些方法可以帮助你对多个 Predicate 实例进行组合、取反等操作。以下是 Predicate 接口中的一些主要方法:

  • test(T t):这是 Predicate 接口中的抽象方法,用于对给定的参数进行条件判断。它接受一个参数并返回一个布尔值,表示参数是否满足条件。

  • and(Predicate<? super T> other):该方法返回一个新的 Predicate 实例,它表示当前 Predicate 与另一个 Predicate 的逻辑与操作。即,只有当两个 Predicate 都返回 true 时,新的 Predicate 才会返回 true

  • or(Predicate<? super T> other):该方法返回一个新的 Predicate 实例,表示当前 Predicate 与另一个 Predicate 的逻辑或操作。即,只要两个 Predicate 中有一个返回 true,新的 Predicate 就会返回 true

  • negate():该方法返回一个新的 Predicate 实例,表示当前 Predicate 的逻辑非操作。即,新的 Predicate 的返回值与当前 Predicate 的返回值相反。

  • static <T> Predicate<T> not(Predicate<? super T> target):该方法返回一个新的 Predicate 实例,用于创建一个与给定 Predicate 相反的 Predicate 实例

  • static <T> Predicate<T> isEqual(Object targetRef):接受一个目标对象作为参数,并返回一个 Predicate 实例,该实例用于判断输入对象是否与目标对象相等。如果目标对象为 null,则返回一个 Predicate 实例,该实例用于判断输入对象是否也为 null;否则返回一个 Predicate 实例,该实例用于判断输入对象是否与目标对象相等。

通过这些方法,Predicate 接口为你提供了丰富的条件判断和组合操作的功能,使得你能够轻松地构建复杂的条件判断逻辑。

public static void predicate_test(){
        Predicate<Integer> predicate1 = p -> p==1;
        Predicate<Integer> predicate2 = p -> p==2;

        System.out.println("p==1&&p==2:"+predicate1.and(predicate2).test(1));
        System.out.println("p==1||p==2:"+predicate1.or(predicate2).test(1));
        System.out.println("p!=1:"+predicate1.negate().test(1));

        Predicate<Integer> isEqual = Predicate.isEqual(1);
        System.out.println("p==1:"+isEqual.test(1));

        Predicate<Integer> isEven = n -> n % 2 == 0;
        Predicate<Integer> isOdd = Predicate.not(isEven);

        System.out.println("偶数:"+isEven.test(4));
        System.out.println("奇数:"+isOdd.test(4));

    }
p==1&&p==2:false
p==1||p==2:true
p!=1:false
p==1:true
偶数:true
奇数:false

同样的,在 java.util.function 包下面看到许多其它类似的函数接口,原理也差不多

四、Supplier 供应商

Supplier接口是一个函数式接口,它不接受任何参数,但返回一个值。该接口定义了一个名为get的抽象方法,用于获取一个值。Supplier 接口通常用于表示一个生产者,它提供一个可以获取值的方法,但不接受任何参数。

Supplier 接口中只包含一个抽象方法 get,它返回类型为 T,表示获取一个值的操作。由于 Supplier 是一个函数式接口,因此可以使用 lambda 表达式或方法引用来创建 Supplier 实例。

public static void supplier_test(){
        // 使用 lambda 表达式创建 Supplier 实例
        Supplier<String> helloSupplier = () -> "Hello, world!";

        // 使用 get 方法获取值
        String value = helloSupplier.get();
        System.out.println(value);

    }
Hello, world!

总的来说,Supplier 接口是 Java 中表示生产者的函数式接口,它定义了一个获取值的方法 get,适用于需要提供值但不接受参数的情况。

同样的,在 java.util.function 包下面看到许多其它类似的函数接口,原理也差不多

五、Operator 操作员

Java 中还有一系列 Operator 函数式接口,其中包括 UnaryOperatorBinaryOperator。这两个接口都是 Function 接口的子接口,用于表示接受一个或两个参数,并返回结果的操作。

UnaryOperator 接口

UnaryOperator 它继承自 Function 接口,自身有个 identity 方法,与 Function 接口中的方法 identity 类似。也是返回一个执行输入参数的函数。

UnaryOperator 接口

UnaryOperator 它继承自 BiFunction 接口,自身有两个方法,两个方法都是接收一个比较器 Comparator<? super T> 作为参数,并返回一个 BinaryOperator 对象。这个返回的 BinaryOperator 对象会根据给定的比较器返回对应值。

  • minBy:返回两个值中较小的那个值
  • maxBy():返回两个值中较大的那个值
public static void binaryOperator_test() {
        // 创建一个比较器,用于比较字符串的长度
        Comparator<String> byLength = Comparator.comparing(String::length);

        // 使用 minBy 方法创建 BinaryOperator 实例
        BinaryOperator<String> shorterString = BinaryOperator.minBy(byLength);

        // 使用 minBy 方法创建 BinaryOperator 实例,使用 apply 方法获取较短的字符串
        String result1 = BinaryOperator.minBy(byLength).apply("apple", "banana");
        // 使用 minBy 方法创建 BinaryOperator 实例,使用 apply 方法获取较短的字符串
        String result2 = BinaryOperator.maxBy(byLength).apply("apple", "banana");
        System.out.println("长度短的字符串:"+result1);
        System.out.println("长度长的字符串:"+result2);
    }
长度短的字符串:apple
长度长的字符串:banana

其他的接口感兴趣的可以自行看看

完结撒花。。。 。。。


文章来源:https://blog.csdn.net/laiyucannian/article/details/140033133
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!

标签:

相关文章

本站推荐

标签云