Set MathContext to BinaryOperator reference methods

霸气de小男生 提交于 2021-02-08 04:27:10

问题


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.


回答1:


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));



回答2:


First option would be to implement something like a TriFunction<P1, P2, P3, R> and modify your code as following:

public enum Operator {
    add("+", (t0, t1, mc) -> t0.add(t1, mc)),
    subtract("-", (t0, t1, mc) -> t0.subtract(t1, mc)),
    multiply("*", (t0, t1, mc) -> t0.multiply(t1, mc)),
    divide("/", (t0, t1, mc) -> t0.divide(t1, mc)),
    mod("%", (t0, t1, mc) -> t0.remainder(t1, mc));

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

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

But you would have to implement the TriFunction by yourself (or find it online) to use, as java doesn't offer something like this from the scratch.

A simpler (IMO quick and dirty) way could be this:

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

    // Attributes and constructors

    public BigDecimal apply(BigDecimal t1, BigDecimal t2, MathContext mc) {
        switch (this) {
            case add:      return t1.add(t2, mc);
            case subtract: return t1.subtract(t2, mc);
            case multiply: return t1.multiply(t2, mc);
            case divide:   return t1.divide(t2, mc);
            case mod:      return t1.remainder(t2, mc);
        }
        return null; // never reached
    }
}

And you could call it even easier by

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


来源:https://stackoverflow.com/questions/42473859/set-mathcontext-to-binaryoperator-reference-methods

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!