【问题标题】:Replacing switch by BinaryOperator用 BinaryOperator 替换开关
【发布时间】:2018-09-16 21:28:11
【问题描述】:

我正在尝试用BinaryOperator 功能接口替换算术运算的通用开关。

基本方法是:

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

据我了解,有必要这样写:

BinaryOperator<Integer> action = (a,b) -> computeExpression(a + operation + b);
action.apply(res, operand);

但我不明白如何避免 computeExpression 中的 switchcomputeOne 相同。

【问题讨论】:

  • 我不得不承认,我不明白这个问题,即使有一个公认的答案。 computeExpression 似乎只与 ComputeOne 模糊相关,操作数和操作都是字符串,原因不明。什么是限制(操作是变量?字符串类型?),目标是什么?将 String 转换为 Int 似乎不是问题,那么为什么会这样呢? a + operation + b 看起来会导致“42 * 14”。当您以后需要拆分它们时,为什么要合并它们?
  • @userunknown,我认为他的意思是computeExpression(a, operation, b) 使其类似于computeOne 的签名

标签: java java-8 functional-interface binary-operators


【解决方案1】:

您可以为每个算术运算定义一个BinaryOperator&lt;Integer&gt;

// a = operand 1
// b = operand 2
(a, b) -> a * b;
(a, b) -> a + b;
(a, b) -> a / b;
(a, b) -> a - b;

然后你可以应用一个传递 2 个参数:

// result = operation.apply(a, b);
int result = ((BinaryOperator<Integer>) ((a, b) -> a * b)).apply(2, 2);

我会使用枚举来枚举这些操作:

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

}

你也可以用BiFunction&lt;BinaryOperator&lt;?&gt;, Pair&lt;?, ?&gt;, ?&gt;“简化”它:

// 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

【讨论】:

    【解决方案2】:

    算术运算符不能是变量。
    通过在实际代码中使用或不使用功能接口,您将具有相同的约束:将String 运算符转换为算术运算符。

    此外,实际上在computeOne() 中,您接受一个int 和两个Strings 作为参数,然后返回一个int
    BinaryOperator&lt;Integer&gt; 接受两个Integer 并返回一个Integer
    所以它不兼容。
    您需要TriFunction,但它不存在。
    要么创建自己的功能接口,例如TriFunction&lt;T,U,V,R&gt; 或减少传递给函数的参数数量。

    这是一个使用枚举 Operator 结合 BiFunction 的示例,它执行的操作与您的实际方法相同。
    请注意,由于运算符现在由负责执行函数的枚举 Operator 表示,因此该函数现在只需要两个参数:IntegerString,您可以将它们转换为 int
    所以BiFunction&lt;Integer, String, Integer&gt; 很好。

    public enum Operator{
        ADD("+", (a,b) -> a + Integer.parseInt(b)), 
        SUBSTRACT("-", (a,b) -> a - Integer.parseInt(b)),
        MULTIPLY("*", (a,b) -> a * Integer.parseInt(b)),
        //       ...
        DEFAULT("", (a,b) -> 0);
    
        public BiFunction<Integer, String, Integer> function;
        private String symbol;
    
        Operator(String symbol, BiFunction<Integer, String, Integer> function){
            this.symbol = symbol;
            this.function = function;
        }
    
        public int compute(int actualValue, String operand){
            return function.apply(actualValue, operand);
        }
    
        public static Operator of(String symbol) {
            for (Operator value : values()) {
                if (symbol.equals(value.symbol)) {
                    return value;
                }
            }
    
            return Operator.DEFAULT;
        }
    
    }
    

    您可以创建这样的操作,例如:

    int res = 10;
    String operand = "15";
    String symbol = "+";
    res = Operator.of(symbol).compute(res, operand);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-29
      • 2021-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-24
      相关资源
      最近更新 更多