在以下情况下,if-else树是最好的方法吗?

时间:2011-01-28 16:26:35

标签: java optimization if-statement

我在做什么:

我正在用Java创建一个简单的计算器,它读取一个使用postfix notation编写的字符串(例如:3 4 +)。然后它接受字符串并从左到右开始读取它。它存储它找到的每个数字,然后应用以下运算符。例如:3 4 + - >存储3,存储4,运行3 + 4并存储结果。

我需要帮助:

应该以什么方式检查字符与预定义的运算符(if(c =='/')等)。在我的情况下,对于if-else树有哪些替代方案,如果我希望能够以最小的努力添加新的运算符(以及最低的性能损失),我应该选择哪一个。什么通常被认为是良好的做法?

6 个答案:

答案 0 :(得分:8)

如果这是一个供人类使用的计算器,请停止考虑性能(如执行速度)。没有人能够注意到if-tree和任何其他实现之间的区别。

也就是说,您可能想尝试实现某种类型的Operator类,它知道如何将自身应用于参数,然后使用运算符名称中的哈希值(字符串如“+”,“ - ”,“*”等等到适当的实例。

答案 1 :(得分:5)

我不担心性能,因为计算机可以解析/计算数据的速度比键入公式快100万倍(这不是夸大)

我接近它的方法是使用if / else或使用switch语句

switch(ch) {
  case '+':

     break;
  case '-':

     break;
  // etc.
}

答案 2 :(得分:5)

如果将操作封装为对象,则通常可以使用数据结构替换类似switch的语句,并希望将来只添加操作。

例如,这是将操作封装为对象的一种方法:使用Enum来表示操作:

http://download.oracle.com/javase/1.5.0/docs/guide/language/enums.html

public enum Operation {
  PLUS   { double eval(double x, double y) { return x + y; } },
  MINUS  { double eval(double x, double y) { return x - y; } },
  TIMES  { double eval(double x, double y) { return x * y; } },
  DIVIDE { double eval(double x, double y) { return x / y; } };

  // Do arithmetic op represented by this constant
  abstract double eval(double x, double y);
}

您可以扩展此示例以将符号与每个操作相关联,并提供静态方法来查找与符号关联的操作。 [[我已经把这个混合的UI /视图代码与逻辑/域代码撕裂了,但你提到你想要简单,所以也许这对你的程序来说没问题。]]

如果将操作封装为对象,则可以考虑使用数据结构来替换类似交换机的代码:

  • 如果会有很多操作,请考虑构建一个hashmap以将符号映射到操作。

  • 如果只有少量操作,它可能足够便宜,可以拥有所有操作的集合,并简单地遍历所有操作,询问每个操作是否对用户提供的符号起作用并使用第一个

答案 3 :(得分:4)

您正在寻找的是由Character个对象作为键的映射实现的Command Pattern,以及将处理接口实现为值的实例。

答案 4 :(得分:2)

我会通过创建一个由单个操作扩展的运算符超类来实现,遵循一个例子(原谅我的错误,我没有尝试这个)。

abstract class Operator {
    String simbol;
    abstract Double calculate(Double firstOperand, Double secondOperand)
}

class Sum extends Operator {
    simbol = "+";
    Double calculate(Double firstOperand, Double secondOperand){
        return firstOperand + secondOperand;
    }    
}

class OperatorRecognizer {
    List<Operator> operators;
    public Operator recognize(String readOperator){
        for(Operator operator : operators){
            if(operator.getSymbol().equals(readOperator)){
                return operator;
            }
        }
    }
}

在读一行时我会这样做:

OperatorFactory.recognize(readOperator).calculate(firstOperand, secondOperand);

这样,当您必须添加一个操作时,只需添加一个类。

编辑:大声笑好吧,似乎其他人也说了同样的话,我会留在这里,无论如何^^“

答案 5 :(得分:1)

有趣的问题。像这里的许多人一样,微观优化导致更多的邪恶而不是善。但是,如果没有任何设计模式或优化的想法,这就是我要做的。

我将为所有操作创建枚举。我还将在这个枚举中创建一个成员函数,它接受一个var args参数和一个操作枚举,并在争论中迭代地应用枚举操作。

我还将创建一个String实用程序类(用于输入处理),它迭代所有操作枚举值并对输入字符串执行正则表达式检查以标识由给定字符串指定的操作(正则表达式,因为我想要确定Postfix表示法)。一旦识别出操作,它就会委托enum的成员函数来执行操作。