Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacing switch by BinaryOperator

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.

like image 523
Roman Vinokurov Avatar asked Apr 06 '18 19:04

Roman Vinokurov


People also ask

How does BinaryOperator relate to BiFunction in Java?

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.

What is BinaryOperator java8?

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.

What is a binary operator in Java?

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 on Java generic types?

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.


1 Answers

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
like image 54
Andrew Tobilko Avatar answered Sep 30 '22 12:09

Andrew Tobilko