Java BiFunction 接口实例( 二 )


combiner 的类型是 BiFunction , 设计的算法可以处理不同类型的输入和输出 。让我们试一下:
List<String> list1 = Arrays.asList("a", "b", "c");List<Integer> list2 = Arrays.asList(1, 2, 3);List<String> result = listCombiner(list1, list2, (a, b) -> a + b);assertThat(result).containsExactly("a1", "b2", "c3"); 
也可以用来处理完全不同类型的输入和输出 。
让我们加入一个算法 , 判断列表1中的值是否大于列表2 , 并生成一个 boolean 结果:
List<Double> list1 = Arrays.asList(1.0d, 2.1d, 3.3d);List<Float> list2 = Arrays.asList(0.1f, 0.2f, 4f);List<Boolean> result = listCombiner(list1, list2, (a, b) -> a > b);assertThat(result).containsExactly(true, true, false); 
4.3. BiFunction 方法引用
用上面抽取的方法和方法引用重写上面的代码:
List<Double> list1 = Arrays.asList(1.0d, 2.1d, 3.3d);List<Float> list2 = Arrays.asList(0.1f, 0.2f, 4f);List<Boolean> result = listCombiner(list1, list2, this::firstIsGreaterThanSecond);assertThat(result).containsExactly(true, true, false);private boolean firstIsGreaterThanSecond(Double a, Float b) { return a > b;} 
用方法引用加入算法 firstIsGreaterThanSecond 看起来代码更容易理解一些 。
4.4. 使用 this 调用 BiFunction 方法引用
改变一下要求 , 用上面基于 BiFunction 算法确认两个列表是否相等:
List<Float> list1 = Arrays.asList(0.1f, 0.2f, 4f);List<Float> list2 = Arrays.asList(0.1f, 0.2f, 4f);List<Boolean> result = listCombiner(list1, list2, (a, b) -> a.equals(b));assertThat(result).containsExactly(true, true, true); 
实际上可以简化成下面这样:
List<Boolean> result = listCombiner(list1, list2, Float::equals); 
这是因为 Float 中的 equals 与 BiFunction 函数签名相同 , 第一个隐式参数是 Float 类型 , 第二个参数是 Object 类型与第一个参数比值 。
5. BiFunctions 组合
如果通过方法引用实现数值比较该怎么实现?
如果使用方法引用实现数值列表比较示例会是怎样?
List<Double> list1 = Arrays.asList(1.0d, 2.1d, 3.3d);List<Double> list2 = Arrays.asList(0.1d, 0.2d, 4d);List<Integer> result = listCombiner(list1, list2, Double::compareTo);assertThat(result).containsExactly(1, 1, -1); 
这个例子与之前的很像 , 但是返回值类型为 Integer 而非原来的 Boolean 。这是因为 Double 中的 compareTo 方法返回类型为 Integer 。
这里可以使用 andThen 在原来的基础上增加额外的处理 。这会生成 BiFunction , 先对两个输入执行操作 , 然后接着执行另一个操作 。
接下来 , 新建一个函数来把 Double::compareTo 方法引用强制转换为 BiFunction:
private static <T, U, R> BiFunction<T, U, R> asBiFunction(BiFunction<T, U, R> function) { return function;} 
lambda 或者方法引用只在转换后才能变成 BiFunction 。可以使用下面 helper 函数把 lambda 显示转换为 BiFunction 对象 。
现在 , 使用 andThen 扩展现有函数的行为:
List<Double> list1 = Arrays.asList(1.0d, 2.1d, 3.3d);List<Double> list2 = Arrays.asList(0.1d, 0.2d, 4d);List<Boolean> result = listCombiner(list1, list2, asBiFunction(Double::compareTo).andThen(i -> i > 0));assertThat(result).containsExactly(true, true, false);

Java BiFunction 接口实例

文章插图
6. 总结
本文从 Java Stream 库与自定义函数两个角度探索了 BiFunction 和 BinaryOperator 的用法 , 了解了如何使用 lambda 和方法引用传递 BiFunction 以及组合函数 。
Java 库只提供单个参数和两个参数的函数式接口 。需要更多参数 , 请参阅柯里化获得更多想法 。完整的源代码可以在 GitHub 上找到 。

【Java BiFunction 接口实例】


推荐阅读