2015-02-11 94 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個參數