unitsofmeasurement / indriya

JSR 385 - Reference Implementation
Other
115 stars 40 forks source link

Implement `Quantity.compareTo` #389

Closed GregJohnStewart closed 1 year ago

GregJohnStewart commented 1 year ago

It would be great if the Quantity class implemented Comparable in order to bring all the benefits of being comparable.

Would probably want to throw an exception if a Quantity of an incompatible unit is given.

Otherwise, one must do the following to compare units:

        Quantity total = this.getTotal();
        Quantity lowStockThreshold = this.getLowStockThreshold();

        if(!total.getUnit().equals(lowStockThreshold.getUnit())){
            lowStockThreshold = lowStockThreshold.to(total.getUnit());
        }

        if (
            total.getValue().doubleValue() < lowStockThreshold.getValue().doubleValue()
        ) {
//...

I noticed some methods in QuantityFunctions that seemed on the right path but wasn't clear how to use them, outside a lambda perhaps.

keilw commented 1 year ago

That's what ComparableQuantity is for. You will notice, that e.g. the abstract Number also does not implement Comparable yet, but the concrete types like BigDecimal do. We have the abstract base interface here in the RI but Quantity does not implement it, we may ask the question in the API to decide, if we'd like that for the upcoming MR2, but here it already exists.

Would probably want to throw an exception if a Quantity of an incompatible unit is given.

That is not how equals() or compareTo() work, unless you pass maybe a null, which also happens if you try with BigDecimal:

Exception in thread "main" java.lang.NullPointerException
    at java.math.BigDecimal.compareTo(BigDecimal.java:2628)

For different unit types with the same semantic value (e.g. 1000m vs. 1km, etc.) please use isEquivalentTo(), which also internally uses compareTo() in AbstractQuantity btw, so either of these should work, only equals() is rather strict. That difference is a bit like BigDecimal where equals() also differs a bit from compareTo().