Home > Software design >  How to make a generic lambda that compares any Number of identical type
How to make a generic lambda that compares any Number of identical type

Time:11-23

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, when x is less than y
  • 0, when x is equal to y
  • 1, when x is greater than y

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.

  • Related