Function、BiFunction、BinaryOperator是java提供的函数式编程接口,适合用于多操作数的链式调用(A Func -> B Func -> C Func)。
Function是一个函数式接口,其中有三个方法apply
, compose
, andThen
。
// 输入一个类型为R的值,返回另一个值
R apply(T t);
//下面两个方法是Function组合调用
// 先执行输入的Function,其结果作为参数再作为调用者的Function的参数
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
// 先执行调用者的Function,其结果作为参数再作为输入的Function的参数
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
用法示例:
public static void main(String[] args) {
int res1 = compute1(1, e -> e + 1); // 结果:2
int res2 = compute2(1, e -> e + 1, e -> e * 3); // 结果:4
int res3 = compute3(1, e -> e + 1, e -> e * 3); // 结果:4
System.out.println(res1 + ", " + res2 + ", " + res3);
}
public static int compute1(int x, Function<Integer, Integer> function) {
return function.apply(x);
}
public static int compute2(int x, Function<Integer, Integer> after, Function<Integer, Integer> before) {
// x作为before的参数,其结果再作为after的参数
return after.compose(before).apply(x);
}
public static int compute3(int x, Function<Integer, Integer> after, Function<Integer, Integer> before) {
// x作为after的参数先执行after的计算,其结果再作为before的参数
return before.andThen(after).apply(x);
}
BiFunction与Function类似,其中有方法:apply
,andThen
,可以传递两个参数用来计算。
BiFunction之所以没有compose
方法,因为apply
的返回值只有一个,而BiFunction的参数有两个,没法用啊。
// 输入两个分别为T、U类型的值,返回R类型的值
R apply(T t, U u);
// 先执行调用者的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));
}
用法示例:
public static void main(String[] args) {
int res1 = compute1(1, 2, (e1, e2) -> e1 * e2); // 结果:2
int res2 = compute2(1, 2, e -> e + 1, (e1, e2) -> e1 * e2); // 结果:3
System.out.println(res1 + ", " + res2);
}
public static int compute1(int x, int y, BiFunction<Integer, Integer, Integer> function) {
return function.apply(x, y);
}
public static int compute2(int x, int y,
Function<Integer, Integer> after,
BiFunction<Integer, Integer, Integer> before) {
// x和y作为before先执行before逻辑,其结果再作为after的参数执行after逻辑
return before.andThen(after).apply(x, y);
}
BinaryFunction是BiFunction的子接口,其中有方法minBy、maxBy。通常用于求两个值的最小值和最大值。BinaryFunction 中 BiFunction 的两个参数类型一致。
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
// 返回两个数中的最小值
public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
}
// 返回两个数中的最大值
public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
Objects.requireNonNull(comparator);
return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
}
}
用法示例:
public static void main(String[] args) {
int res1 = compute(1, 2, BinaryOperator.maxBy((e1, e2) -> e1 >= e2 ? 1 : -1)); // 结果:2
int res2 = compute(1, 2, BinaryOperator.minBy((e1, e2) -> e1 >= e2 ? 1 : -1)); // 结果:1
System.out.println(res1 + ", " + res2);
}
public static int compute(int x, int y, BinaryOperator<Integer> function) {
return function.apply(x, y);
}
reduce就是利用了BiFunction和BinaryOperator进行结果的组装。
reduce是一个迭代累加器,接收一系列输入元素,并通过迭代某种操作组合成一个简单的结果。
// 初始值identity + 多个输入元素累加值
T reduce(T identity, BinaryOperator<T> accumulator);
// 多个输入元素累加值
Optional<T> reduce(BinaryOperator<T> accumulator);
// stream().reduce:初始值identity + 多个输入元素累加值
// parallelStream().reduce:迭代累加(并行计算(identity + 每个输入元素)的值)
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
用法示例:
System.out.println(Arrays.asList(1, 2, 3, 4, 5).stream()
.reduce(5, (x, y) -> x + y,
(x, y) -> x + y)); // (((((5 + 1) + 2) + 3) + 4) + 5) = 20,串行相加
System.out.println(Arrays.asList(1, 2, 3, 4, 5).parallelStream()
.reduce(5, (x, y) -> x + y,
(x, y) -> x + y)); // (5 + 1) + (5 + 2) + (5 + 3) + (5 + 4) + (5 + 5) = 40,并行计算并相加