2015-02-11 70 views
5

我试图让我的代码更有效率,并替换了我写的一堆if语句。到目前为止,我的程序主要检查输入的操作符(如+, - 等),然后计算它。例如1 + 5给出6.当程序评估数字之间的符号(在我的例子中为“+”)时,它将检查操作员是什么,然后相应地进行。例如,如果这是一个“+”,将采取1,并添加5的代码是这样的:更换If语句?

switch (op) { 
    case "+": // Addition 
     return args[0] + args[1]; 
    case "-": // Subtraction 
     return args[0] - args[1]; 
    case "*": // Multiplication 
     return args[0] * args[1]; 
    case "/": // Division 
     return args[0]/args[1]; 

我想知道是否有可能以某种声明,即会取代这整块从String中检测操作符并将其转换为操作?我认识到,对于少数几个操作员来说,使用switch语句可能更容易,但是我有很多这样的操作,并且在评估switch语句顶部的操作符和底部之间有5-10ms的差异。

+0

有很多案件switch语句已经被编译器优化的东西,同等进行到基于散列的查找,或者至少比线性if/else搜索更好。 – The111 2015-02-11 19:41:04

回答

10

在Java 8中,您可以使用地图的拉姆达功能:

Map<String, IntBinaryOperator> operators = new HashMap<>(); 

operators.put("+", (a, b) -> a + b); 
operators.put("-", (a, b) -> a - b); 
operators.put("*", (a, b) -> a * b); 
operators.put("/", (a, b) -> a/b); 

... 

return operators.get(op).apply(args[0], args[1]); 

这里还有更多间接的,但它会给你O(1)摊销查找时间。

+0

感谢您的帮助,我会在今天晚些时候进行测试。有没有一种方法可以与函数一起使用?就像操作符是“sqrt”,我希望它调用Math.sqrt(args [0])。 – 2015-02-11 17:31:19

+0

@ThomasPaine对于平方根,你可以试试operators.put(“sqrt”,(a,b) - > Math.sqrt(args [0])。尽管你应该尝试寻找一个不同的函数接口来使用IntBinaryOperator。 – CKing 2015-02-11 18:15:50

+0

这个哈希查找会比编译器优化的开关查找更有效吗? – The111 2015-02-11 19:46:07

2

答案是Strategy Pattern - 你已经有很好的Java 8的例子,所以这里是拉姆达之前的版本(这也说明了为什么这些急需的lambda表达式):

public class CodeTest { 

    private static interface ArithmeticStrategy { 
     public double apply(double arg1, double arg2); 
    } 

    private static class AddArithmeticStrategy implements ArithmeticStrategy { 
     @Override 
     public double apply(double arg1, double arg2) { 
      return arg1 + arg2; 
     } 
    } 

    // ... other operations 

    private static Map<String, ArithmeticStrategy> OPS = new HashMap<>(); 
    static { 
     OPS.put("+", new AddArithmeticStrategy()); 
    } 

    public static void main(String[] args) { 
     // Add two numbers and print the result 
     System.out.println(
       OPS.get("+").apply(22.3, 35.4)); 
    } 
} 
0

,如果你不打算与Java 8,你可以做这样的事情

public interface Op{ 
     int execute(int[] values); 
    } 
    public class Add implements Op{ 
     public int execute(int[] values){ 
      return values[0] + values[1]; 
     } 
    } 

那么所有你需要的是定义你的操作映射和填充它

private final Map<String, Op> operations = new HashMap<>(); 
operations.put("+", new Add()); 

,那么你可以通过调用operations.get(op).execute(args)

使用这种结构可以让你以支持业务与一个,两个或甚至100个参数