首页 > 基础资料 博客日记
Java 函数式接口详解及使用
2024-10-15 04:00:06基础资料围观84次
在 Java 中,函数式接口(Functional Interface)是指只包含一个抽象方法的接口。函数式接口是 Java 8 引入的概念,用于支持函数式编程,并且可以通过 lambda 表达式来实例化。
函数式接口具有以下特点:
-
只包含一个抽象方法,但可以包含多个默认方法或静态方法。
-
用
@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
方法以及默认方法 andThen
和 compose
:
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
函数式接口,其中包括 UnaryOperator
和 BinaryOperator
。这两个接口都是 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
其他的接口感兴趣的可以自行看看
完结撒花。。。 。。。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签:
上一篇:Java之反射
下一篇:2024年Java最新面试题总结(三年经验)