问题
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