Java8之函数式接口

时间:2022-01-15 19:10:39

在我的上一篇java8基础入门的文章中说了函数式接口的基本概念,这里介绍下JDK提供的一些重要的函数式接口:

重要的函数式接口

接口名称 参数 返回值
Function T, R R
Consumer T void
BiFunction T,U R
Predicate T boolean
Supplier None T

Function 接口:

1,apply方法, 抽象的方法: 输入一个参数,得到一个结果。
java8之前,我们代码老的方式,是先定义好行为,再调用。
现在的方式,行为不需要先定义,通过方法引用的方式,把行为作为参数传递
如老的方式可以这样定义一个方法,然后调用:

public int method1(int a){
    return 2*a;
}

采用java8新的方式:

Function<Integer,Integer> function = value->2*value;
System.out.println(function.apply(100)); //打印返回的结果

2,compose方法, 非抽象的default方法.
根据源代码,我们可以知道这个方法的作用:
当前function实例和另一个function参数进行组合, 先应用参数的apply, 再应用当前的apply

default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
    Objects.requireNonNull(before);
    return (V v) -> apply(before.apply(v));
}

看个例子就更清楚了:

Function<Integer,Integer> function1 = value->2*value;
Function<Integer,Integer> function2 = value->3+value;
//看下面的组合:先应用参数的apply,也就是function2的操作=5+3=8; 再应用function1的操作=2*8=16
Integer result = function1.compose(function2).apply(5);
System.out.println(result);

程序输出的最终结果为:16

3,andThen方法:
也是组合操作,先应用当前的apply, 再应用参数的apply。

default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
    Objects.requireNonNull(after);
    return (T t) -> after.apply(apply(t));
}

看个例子, 注意和上面的compose的结果对比一下。

Function<Integer,Integer> function1 = value->2*value;
Function<Integer,Integer> function2 = value->3+value;
//先应用当前对象的的apply,也就是function1的操作=2*5=10; 再应用参数function2的操作=3+10=13
Integer result = function1.andThen(function2).apply(5);
System.out.println(result);

程序输出的最终结果为:13

Consumer接口:

1,官方文档的说明:抽象方法void accept(T t),接受一个参数,没有返回结果,有可能会产生副作用。
可以这么理解呢:在参数T上执行操作,不返回值,有可能改变传入的T的值。

Consumer<String> consumer = str -> System.out.println(str);
consumer.accept("hello world!");

2,Consumer除了accept的抽象方法外,还有个default方法: andThen
这个方法有什么用呢?我们看一下源码:

default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    return (T t) -> { accept(t); after.accept(t); };
}

接受一个Consumer返回一个Consumer;
先调用当前Consumer对象的accept方法,再调用参数的accept方法;
相当于把两个Consumer的操作组合起来。

Consumer<String> consumer1 = str -> System.out.println("hello "+str);
Consumer<String> consumer2 = str -> System.out.println("bye "+str);
consumer1.andThen(consumer2).accept("Tom");

输出的结果是:
hello Tom
bye Tom

BiFunction接口:

1,先看jdk说明:输入两个参数,得到一个结果。

BiFunction<Integer,Integer,Integer> biFunction = (value1,value2) -> value1 + value2;//两个数相加,返回结果
Integer biresult = biFunction.apply(2,3);
System.out.println(biresult);

结果为: 5

2,同样有一个andThen方法:
接收Function参数,返回BiFunction,把BiFunction和Function操作组合:
先调用BiFunction的操作,再调用Function的操作。下面是源码:

default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
    Objects.requireNonNull(after);
    return (T t, U u) -> after.apply(apply(t, u));
}

看个例子:

Function<Integer,Integer> function3 = value->3*value;
BiFunction<Integer,Integer,Integer> biFunction3 = (value1,value2) -> value1 + value2;
//调用BiFunction的操作=4+5=9;在调用Function操作:3*9=27
Integer biAndThenResult = biFunction3.andThen(function3).apply(4,5);
System.out.println(biAndThenResult);

结果为: 27

这里就有个问题了,为什么andThen方法参数是Function而不是BiFunction?
仔细分析就能很快得出结论:那是因为BiFunction返回值只有一个值, 而BiFunction必须接收两个参数,所有没有办法把两个BiFunction进行足额组合。 只能传给Function,和Function操作进行组合。

3, 为什么没有compose方法?
我们的Function都有compose方法,为什么BiFunction没有呢?
我们知道compose方法是先应用参数的apply, 在应用当前对象的apply, 问题就来了:
先执行参数的apply, 其返回值一定只有一个, 不满足BiFunction要两参数的条件。

Predicate

判断输入的对象是否符合某个条件。
1,抽象test方法:

//判断输入的数值是否大于100
Predicate<Integer> predicate = value -> value>100;
System.out.println(predicate.test(90));
System.out.println(predicate.test(101));

结果为:
false
true
2,and方法:两个条件组合 && 判断

default Predicate<T> and(Predicate<? super T> other) {
    Objects.requireNonNull(other);
    return (t) -> test(t) && other.test(t);
}

3,or方法:两个条件 || 判断

default Predicate<T> or(Predicate<? super T> other) {
    Objects.requireNonNull(other);
    return (t) -> test(t) || other.test(t);
}

4,negate方法:非条件的判断

default Predicate<T> negate() {
    return (t) -> !test(t);
}

and,or,negate方法一起看个例子:

Predicate<Integer> predicate1 = value -> value>100;
Predicate<Integer> predicate2 = value -> value<1000;
System.out.println(predicate1.and(predicate2).test(300)); // value 大于100 and value <1000
System.out.println(predicate1.or(predicate2).test(300));// value 大于100 or value <1000
System.out.println(predicate1.negate().test(300));//value 不 大于100

结果:
true
true
false

Supplier

只有一个抽象方法: T get();
不接受参数,返回一个结果。
我们上面看了那么多实例,这个接口应该很容易理解了。
下面例子,打印hello world:

Supplier supplier = () -> "hello world";
System.out.println(supplier.get());

本文仅仅是简单介绍了一下jdk自带的常用的函数式接口。
更深入的东西还是需要大家多读多写代码。