I'm trying to replace the common switch for arithmetical operations by BinaryOperator
functional interface.
The base method is:
private static int computeOne(int res, String operand, String operation) {
int number = Integer.parseInt(operand);
switch (operation) {
case "+":
res += number;
break;
case "-":
res -= number;
break;
case "*":
res *= number;
break;
case "/":
res = (number != 0 ? res / number : Integer.MAX_VALUE);
break;
default:
res = 0;
System.out.println("unknown operation");
}
return res;
}
As I understand it's nesessary to write something like:
BinaryOperator<Integer> action = (a,b) -> computeExpression(a + operation + b);
action.apply(res, operand);
But I don't understand how to avoid switch
in computeExpression
that would be the same as computeOne
.
Interface BinaryOperator<T> Represents an operation upon two operands of the same type, producing a result of the same type as the operands. This is a specialization of BiFunction for the case where the operands and the result are all of the same type.
The BinaryOperator Interface<T> is a part of the java. util. function package which has been introduced since Java 8, to implement functional programming in Java. It represents a binary operator which takes two operands and operates on them to produce a result.
A binary operator is an operator that operates on two operands and manipulates them to return a result. Operators are represented by special characters or by keywords and provide an easy way to compare numerical values or character strings.
Can you use any binary operator in Java generic types? Java doesn't support using the + operator for anything but primitive numeric types and Strings . Here, you can't use the + operator between any arbitrary objects.
You can define a BinaryOperator<Integer>
for each arithmetic operation:
// a = operand 1
// b = operand 2
(a, b) -> a * b;
(a, b) -> a + b;
(a, b) -> a / b;
(a, b) -> a - b;
Then you can apply one passing 2 arguments:
// result = operation.apply(a, b);
int result = ((BinaryOperator<Integer>) ((a, b) -> a * b)).apply(2, 2);
I would use an enum to enumerate these operations:
class Test {
public static void main(String[] args) {
System.out.println(computeOne(4, "2", "/")); // 2
System.out.println(computeOne(4, "2", "*")); // 8
System.out.println(computeOne(4, "2", "-")); // 2
System.out.println(computeOne(4, "2", "+")); // 6
}
private static int computeOne(int res, String operand, String operation) {
return Operation.getOperationBySymbol(operation)
.getBinaryOperator()
.apply(res, Integer.parseInt(operand));
}
private enum Operation {
// operation = symbol, action
MULTIPLICATION("*", (a, b) -> a * b),
ADDITION("+", (a, b) -> a + b),
SUBTRACTION("-", (a, b) -> a - b),
DIVISION("/", (a, b) -> a / b);
private final BinaryOperator<Integer> binaryOperator;
private final String symbol;
Operation(String symbol, BinaryOperator<Integer> binaryOperator) {
this.symbol = symbol;
this.binaryOperator = binaryOperator;
}
public BinaryOperator<Integer> getBinaryOperator() {
return binaryOperator;
}
public String getSymbol() {
return symbol;
}
public static Operation getOperationBySymbol(String symbol) {
for (Operation operation : values()) {
if (operation.getSymbol().equals(symbol)) {
return operation;
}
}
throw new IllegalArgumentException("Unknown symbol: " + symbol);
}
}
}
You also can "simplify" it with a BiFunction<BinaryOperator<?>, Pair<?, ?>, ?>
:
// BiFunction<Operator, Operands, Result>
// Operator = BinaryOperator<?>
// Operands = Pair<?, ?>
BiFunction<BinaryOperator<Integer>, Pair<Integer, Integer>, Integer> f =
(operator, operands) ->
operator.apply(operands.getKey(), operands.getValue());
f.apply((a, b) -> a + b, new Pair<>(2, 2)); // 4
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With