如何制作一个通用的 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较大。
我需要在运行时替换比较运算符,其中两个数字将比较 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较大。