I have a need to replace a comparison operator at runtime, where two Numbers would be compared GreaterThanOrEquals, LessThanOrEquals, Equals, etc. but ideally I don't replicate my code for Integers, Doubles, Longs, Shorts, Floats and Bytes. Part of my requirements is keeping the operation in lambdas as much as possible for performance.
Note: Both values will always be the same type. I have no intention of doing mixed-type comparisons.
Here is a rough of my code. I tried to just parameterize the last static method with Java.lang.Number, but >= won't work on 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;
}
}
Edit: This code duplication also means my GUI code will need to use a if (Param.value instanceof Integer) Expression.setOperator(GreaterOrEqual.Integers);
which is even more code duplication.
CodePudding user response:
Usage of Comparable Interface
public static <T extends Comparable<? super T>> int compare(T x, T y) {
return x != null ? x.compareTo(y) : -y.compareTo(x);
}
Possible Outcomes
-1
, whenx
is less thany
0
, whenx
is equal toy
1
, whenx
is greater thany
Possible Usage
compare(x, y) < 0
- x
is less than y
compare(x, y) <= 0
- x
is less than or equal y
compare(x, y) == 0
- x
equals y
compare(x, y) >= 0
- x
is greater than or equal y
compare(x, y) > 0
- x
is greater than y
If there is a mistake or an issue, please notify me!
CodePudding user response:
The first thing you have to understand that you are getting no benefit from writing Operator<Integer>
. Java uses auto-boxing to convert int
to the Integer
wrapper object. Then in your code ((v1, v2) -> v1 >= v2
) the Integer
object is converted back into an int
.
A more universal solution would use the Comparable
interface. Number
doesn't implement the interface, but all the important Number implementations like Double
support it.
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 if the parameter is smaller, 0 if it's the same size and -1 of it is bigger.