如何制作一个通用的 lambda 来比较任意数量的相同类型

How to make a generic lambda that compares any Number of identical type

我需要在运行时替换比较运算符,其中两个数字将比较 GreaterThanOrEquals、LessThanOrEquals、Equals 等,但理想情况下我不会为 Integers、Doubles、Longs、Shorts、Floats 复制我的代码和字节。我的部分要求是为了性能尽可能保持在 lambda 中的操作。

注意:两个值将始终是同一类型。我无意进行混合类型比较。

这是我的代码的粗略。我试图用 Java.lang.Number 参数化最后一个静态方法,但 >= 对 Number:

不起作用
public class Expression {
    public Param p1;
    public Operator o;
    public Param p2;

    public Object eval() {
        return o.eval(p1.getValue(),p2.getValue());
    }
}


public interface Operator<T>{
    Object eval(T p1,T p2);
}


public interface GreaterOrEqual extends Operator<Number>{
    static Operator<Integer> Integers() {
        return (v1, v2) -> v1 >= v2;
    }

    static Operator<Double> Doubles() {
        return (v1, v2) -> v1 >= v2;
    }

    static Operator<Long> Longs() {
        return (v1, v2) -> v1 >= v2;
    }

    static Operator<Number> generic() {
        // this one won't compile as ">= can't be applied to Java.lang.Number"
        return (v1, v2) -> v1 >= v2;
    }

}

编辑:此代码重复还意味着我的 GUI 代码将需要使用 if (Param.value instanceof Integer) Expression.setOperator(GreaterOrEqual.Integers);,这是更多的代码重复。

可比接口的使用

public static <T extends Comparable<? super T>> int compare(T x, T y) {
    return x != null ? x.compareTo(y) : -y.compareTo(x);
}

可能的结果

  • -1,当x小于y
  • 0,当x等于y
  • 1,当x大于y

可能的用法

compare(x, y) < 0 - x 小于 y
compare(x, y) <= 0 - x 小于或等于 y
compare(x, y) == 0 - x 等于 y
compare(x, y) >= 0 - x 大于或等于 y
compare(x, y) > 0 - x 大于 y


如果有错误或问题,请通知我!

首先你必须明白,写作 Operator<Integer> 对你没有任何好处。 Java 使用自动装箱将 int 转换为 Integer 包装器对象。然后在您的代码 ((v1, v2) -> v1 >= v2) 中,Integer 对象被转换回 int.

更通用的解决方案是使用 Comparable 接口。 Number 没有实现该接口,但所有重要的 Number 实现如 Double 都支持它。

Operator<Comparable<?>> gt = (v1, v2) -> v1.compareTo(v2) > 0;
Operator<Comparable<?>> ge = (v1, v2) -> v1.compareTo(v2) >= 0;
Operator<Comparable<?>> ge = (v1, v2) -> v1.compareTo(v2) = 0;
Operator<Comparable<?>> le = (v1, v2) -> v1.compareTo(v2) <= 0;
Operator<Comparable<?>> lt = (v1, v2) -> v1.compareTo(v2) < 0;

compareTo returns如果参数较小则为1,如果大小相同则为0,其中-1较大。