我应该使用哪个FunctionalInterface?

7

我正在学习如何将一些lambda表达式表示为FunctionalInterface。因此,为了将两个整数相加,我使用了以下代码:

BiFunction<Integer, Integer, Integer> biFunction = (a, b) -> a + b;
System.out.println(biFunction.apply(10, 60));

给出的输出是70。但如果我这样写:
BinaryOperator<Integer, Integer, Integer> binaryOperator = (a, b) -> a + b;

我收到一个错误信息,内容如下:

类型参数数量错误:需要1个,实际提供了3个

BinaryOperator 不是 BinaryFunction 的子类吗?我该如何改进它呢?

3个回答

10

BinaryOperator

BinaryOperator是一种作用于单一类型的操作数和结果的函数,即BinaryOperator<T>

BinaryOperator不是BinaryFunction的子类吗?

是的,BinaryOperator确实extends BiFunction。但请注意文档中的说明(格式由我调整):

这是BiFunction的一个特化,适用于操作数和结果都是相同类型的情况。

完整的表示如下:

BinaryOperator<T> extends BiFunction<T,T,T>

因此你的代码应该与以下内容兼容:
BinaryOperator<Integer> binaryOperator = (a, b) -> a + b;
System.out.println(binaryOperator.apply(10, 60));

IntBinaryOperator

如果你要处理两个原始整数,可以使用IntBinaryOperator函数接口(在你的例子中使用了“加上两个整数”)。

IntBinaryOperator intBinaryOperator = (a, b) -> a + b;
System.out.println(intBinaryOperator.applyAsInt(10, 60));

表示对两个int数值操作并生成一个int数值结果。这是针对int的BinaryOperator的原始类型专用。


我正在使用Integer,我仍然可以使用IntBinaryOperator吗?

是的,您仍然可以使用它但是请注意IntBinaryOperator的表示方式。

Integer first = 10;
Integer second = 60;
IntBinaryOperator intBinaryOperator = new IntBinaryOperator() {
    @Override
    public int applyAsInt(int a, int b) {
        return Integer.sum(a, b);
    }
};
Integer result = intBinaryOperator.applyAsInt(first, second); 

如果你将firstsecond拆箱为基本类型,然后将它们相加作为Integer类型的result输出,这将会给你带来额外的开销。

注意:在使用Integer时要小心使用null-safe values,否则可能会出现NullPointerException


谢谢您的回答。我正在使用Integer,我还能使用IntBinaryOperator吗? - Mani
1
@Mani 在这种情况下,最好使用BinaryOperator,因为IntBinaryOperator会增加自动装箱和拆箱的开销。请参见答案中的编辑。 - Naman
1
好的。再次感谢您的回答和解释。 - Mani

6
BiFunction<Integer, Integer, Integer> biFunction = (a, b) -> a + b;

可以表示为:
BinaryOperator<Integer> binaryOperator = (a, b) -> a + b;

通常情况下,为了避免拆箱计算(从 Integer 转换为 int)和再次装箱返回结果(从 int 转换为 Integer),您应该对 int 进行算术运算,而不是 Integer。

IntBinaryOperator intBinaryOperator = (a, b) -> a + b;

顺便提一下,你也可以使用方法引用而不是lambda来计算两个int之间的和。
Integer.sum(int a, int b)就是你要找的:

IntBinaryOperator biFunction = Integer::sum;

谢谢您的回答。我正在使用Integer,我还能使用IntBinaryOperator吗?另一个答案和文档中提到了它是针对原始类型操作的。 - Mani

4

BinaryOperator不是BinaryFunction的子类吗?

是的,它是。如果您查看BinaryOperator的源代码,您会看到:

public interface BinaryOperator<T> extends BiFunction<T,T,T> {
    // ...
}

所以你只需要修复你的语法:
BinaryOperator<Integer> binaryOperator = (a, b) -> a + b;
System.out.println(binaryOperator.apply(10, 60));

如何改进它?

您可以使用 IntBinaryOperator。这会更简化语法:

IntBinaryOperator binaryOperator = (a, b) -> a + b;
System.out.println(binaryOperator.applyAsInt(10, 60));

谢谢您的回答。我正在使用Integer,我还能使用IntBinaryOperator吗?另一个答案和文档中提到了它是针对原始类型操作的。 - Mani
1
@Mani 是的,它将自动从 Integer 转换为 int - oleg.cherednik
我明白了。再次感谢您的回答。 - Mani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接