Search code examples
javaenumsjava-8bigdecimalbinary-operators

Set MathContext to BinaryOperator reference methods


I have this enum:

public enum Operator {
    add("+", BigDecimal::add),
    subtract("-", BigDecimal::subtract),
    multiply("*", BigDecimal::multiply),
    divide("/", BigDecimal::divide),
    mod("%", BigDecimal::remainder);

    Operator(final String symbol, final BinaryOperator<BigDecimal> operation) {
        this.symbol = symbol;
        this.operation = operation;
    }

    public BinaryOperator<BigDecimal> getOperation() {
        return operation;
    }
}

I want to use the some MathContext, one can easily do that when performing an operation like this:

MathContext mc = MathContext.DECIMAL32;
BigDecimal t0 = new BigDecimal(100);
BigDecimal t1 = new BigDecimal(2); 
BigDecimal result = t0.add(t1, mc);

However if I want to use the reference to the BinaryOperator in the enum I can't see a way of giving it the MathContext:

BigDecimal result = enum.getOperation().apply(t0, t1);

In the documentation nor the methods available for apply I see any option.


Solution

  • Depending on the use case, you can keep the scope of the custom functional interface at a minimum:

    public enum Operator {
        add("+", BigDecimal::add),
        subtract("-", BigDecimal::subtract),
        multiply("*", BigDecimal::multiply),
        divide("/", BigDecimal::divide),
        mod("%", BigDecimal::remainder);
    
        private interface TriFunc {
            BigDecimal apply(BigDecimal a, BigDecimal b, MathContext c);
        }
        private String symbol;
        private TriFunc operation;
    
        Operator(String symbol, TriFunc operation) {
            this.symbol = symbol;
            this.operation = operation;
        }
    
        public BinaryOperator<BigDecimal> getOperation(MathContext c) {
            return (a, b) -> operation.apply(a, b, c);
        }
    
        // you can also provide a direct method:
        public BigDecimal apply(BigDecimal a, BigDecimal b, MathContext c) {
            return operation.apply(a, b, c);
        }
    }
    

    So anyone using the Operator enumeration, doesn’t have to know anything about the internally used TriFunc interface. Operator can be use either, directly like

    BigDecimal result = Operator.add
        .apply(new BigDecimal(100), new BigDecimal(2), MathContext.DECIMAL32);
    

    or getting the standard BinaryOperator<BigDecimal> like

    BigDecimal result = Operator.add.getOperation(MathContext.DECIMAL32)
        .apply(new BigDecimal(100), new BigDecimal(2));