Function 接口
- JDK8新增的函数式接口
- 接口只有一个抽象方法apply, 接受一个T类型参数, 返回一个R类型参数, T, R表示泛型, 可以相同
- 除了一个抽象的apply方法之外, Function存在两个默认的default方法, compose和andThen, 这两个方法都是用来组合不同的Function的
- 这个函数式接口被大量应用于集合以及Stream(流)中
apply 方法
/**
* 输入一个T类型的参数
* 返回一个R类型的值
*/
R apply(T t);
compose 方法
/**
* 接口默认方法
* 组合两个函数方法, 返回一个新的函数
* before的apply方法输入一个V类型的参数, 返回一个T类型的参数
* 当前的Funtion的apply方法是输入一个T类型的参数, 返回一个R类型的参数
* 两个函数组合之后, 返回一个新的Function, 新的Function输入一个V类型的参数, 返回一个R类型的参数
* 简单来说, 入参功能 : V -> T, 当前函数功能 : T -> R, 返回函数功能 : V -> R
*/
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
// 非空判断
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
andThen 方法
/**
* 组合两个函数方法, 返回一个新的函数
* after的apply方法输入一个R类型的参数, 返回一个V类型的参数
* 当前的Funtion的apply方法是输入一个T类型的参数, 返回一个R类型的参数
* 两个函数组合之后, 返回一个新的Function, 新的Function输入一个T类型的参数, 返回一个V类型的参数
* 简单来说, 入参功能 : R -> V, 当前函数功能 : T -> R, 返回函数功能 : T -> V
*/
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
// 非空判断
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
API使用样例
public static void main(String[] args) {
Function<Integer, Integer> function1 = value -> value * 2;
Function<Integer, Integer> function2 = value -> value + 3;
Function<Integer, Integer> function3 = function1.compose(function2);
Function<Integer, Integer> function4 = function1.andThen(function2);
// function3,先执行function2的apply方法再执行function1的apply方法, 所以结果为(2 + 3) * 2 = 10
System.out.println("function3 : " + function3.apply(2));
// function4,先执行function1的apply方法再执行function2的apply方法, 所以结果为2 * 2 + 3 = 7
System.out.println("function4 : " + function4.apply(2));
Function<Integer, String> function5 = value -> "Hello World " + value;
Function<String, List<String>> function6 = value -> new ArrayList<>(Arrays.asList(value));
Function<Long, Integer> function7 = value -> value.intValue();
// function8 是function6调用compose组合function5
// function6是String->List<String>, function5是Integer->String, 所以组合之后,Function8是Integer->List<String>
Function<Integer, List<String>> function8 = function6.compose(function5);
// function9 是function7调用andThen方法组合function5
// function7是Long->Integer, function5是Integer->String, 所以组合之后,Function9是Long->String
Function<Long, String> function9 = function7.andThen(function5);
// 输出: [Hello World 1]
System.out.println(function8.apply(1));
// 输出: Hello World 100
System.out.println(function9.apply(100L));
}
Stream中使用举例
Funtion接口大量被用于集合和流中, 下面就简单举一个例子, 看下Function在Stream中的应用
场景 :
- 遍历一个List, 将其中小写字母都转换成大写字母进行输出
- Function 接口的实现负责将小写转换成大写, 代码如下:
List<String> list = new ArrayList<>(Arrays.asList("biluo", "huangquan", "hongchen", "zimo"));
Function<String, String> function = item -> item.toUpperCase();
list.stream().map(function).forEach(item -> System.out.println(item));
输出 :
BILUO
HUANGQUAN
HONGCHEN
ZIMO
更多的用法, 需要进一步了解一下Stream了, 这里只是简单举个栗子
BiFunction接口
- JDK8新增函数式接口
- 可以理解为Function的一种扩展, Function接口接收一个参数, 返回一个参数; BiFunction接口接受两个参数, 返回一个参数
- 唯一的抽象方法apply, 接收两个参数, 返回一个参数
- 存在一个默认方法addThen, 由于apply方法接收两个参数, 所以不存在compose方法
- 和Function一样, 在集合与Stream流中均有应用
apply 方法
/**
* 输入两个参数, 类型分别是T和U, 返回一个结果, 类型为R
* @param t 函数第一个输入参数
* @param u 第二个输入参数
* @return 返回结果
*/
R apply(T t, U u);
andThen 方法
/**
* 传入一个Function类型,该Function类型输入参数为R, 返回结果类型为V
* 当前BiFunction的apply函数输入参数类型为T, U; 返回结果类型为R
* 将两个参数组合之后返回一个新的BiFunction方法, 输入参数是T,U,返回结果类型为V
* 简单来说就是当前的BiFunction是(T, U) -> R, 传入的Function是R -> V
* 所以组合后的新的Function是(T, U) -> V, 即把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));
}
BiFunction没有Compose方法是因为BiFunction的apply方法要接收两个参数, 而不管是Function还是BiFunction乃至所有的Java方法, 返回结果都只有一个
API代码样例
public static void main(String[] args) {
BiFunction<Integer, Integer, Integer> biFunction = (num1, num2) -> num1 + num2;
// 输出 : 5
System.out.println(biFunction.apply(2, 3));
Function<Integer,Integer> function = num -> num * num;
// newBiFunction的apply(num1, num2)方法等于function.apply(biFunction(num1, num2))
BiFunction<Integer, Integer, Integer> newBiFunction = biFunction.andThen(function);
// 输出 : 25
System.out.println(newBiFunction.apply(2, 3));
BiFunction<Integer, Integer, List<Integer>> biFunction2 = (num1, num2) -> new ArrayList<>(Arrays.asList(num1, num2));
Function<List<Integer>,String> function2 = list -> list.toString();
BiFunction<Integer, Integer, String> newBiFunction2 = biFunction2.andThen(function2);
System.out.println(newBiFunction2.apply(1, 2));
}
集合中使用举例
HashMap中的compute方法接收一个BiFunction类型的参数
Map<String, String> map = new HashMap<>();
map.put("name", "qiyexue");
BiFunction<String, String, String> biFunction = (k, v) -> k + " : " + map.get(k).toUpperCase();
System.out.println(map.compute("name", biFunction));
输出 :
name : QIYEXUE