企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
### 缺少基本类型的函数 让我们重温一下`BiConsumer`,看看我们如何创建缺少的针对**int**,**long**和**double**的各种排列: ~~~java // functional/BiConsumerPermutations.java import java.util.function.*; public class BiConsumerPermutations { static BiConsumer<Integer, Double> bicid = (i, d) -> System.out.format("%d, %f%n", i, d); static BiConsumer<Double, Integer> bicdi = (d, i) -> System.out.format("%d, %f%n", i, d); static BiConsumer<Integer, Long> bicil = (i, l) -> System.out.format("%d, %d%n", i, l); public static void main(String[] args) { bicid.accept(47, 11.34); bicdi.accept(22.45, 92); bicil.accept(1, 11L); } } ~~~ 输出结果: ~~~ 47, 11.340000 92, 22.450000 1, 11 ~~~ 这里使用`System.out.format()`来显示。它类似于`System.out.println()`但提供了更多的显示选项。 这里,`%f`表示我将`n`作为浮点值给出,`%d`表示`n`是一个整数值。 这其中可以包含空格,输入`%n`会换行 — 当然使用传统的`\n`也能换行,但`%n`是自动跨平台的,这是使用`format()`的另一个原因。 上例简单使用了包装类型,装箱和拆箱负责它与基本类型之间的来回转换。 又比如,我们可以将包装类型和`Function`一起使用,而不去用各种针对基本类型的预定义接口。代码示例: ~~~java // functional/FunctionWithWrapped.java import java.util.function.*; public class FunctionWithWrapped { public static void main(String[] args) { Function<Integer, Double> fid = i -> (double)i; IntToDoubleFunction fid2 = i -> i; } } ~~~ 如果没有强制转换,则会收到错误消息:“Integer cannot be converted to Double”(**Integer**无法转换为**Double**),而使用**IntToDoubleFunction**就没有此类问题。**IntToDoubleFunction**接口的源代码是这样的: ~~~java @FunctionalInterface public interface IntToDoubleFunction { double applyAsDouble(int value); } ~~~ 因为我们可以简单地写`Function <Integer,Double>`并产生正常的结果,所以用基本类型的唯一原因是可以避免传递参数和返回结果过程中的自动装箱和自动拆箱,进而提升性能。 似乎是考虑到使用频率,某些函数类型并没有预定义。 当然,如果因为缺少针对基本类型的函数式接口造成了性能问题,你可以轻松编写自己的接口( 参考 Java 源代码)——尽管这里出现性能瓶颈的可能性不大。