The object oriented way to do it would be to use an enumeration of the possible operations. That way each operation could only consume one object in memory.
public enum Operation {
ADD() {
public int perform(int a, int b) {
return a + b;
}
},
SUBTRACT() {
public int perform(int a, int b) {
return a - b;
}
},
MULTIPLY() {
public int perform(int a, int b) {
return a * b;
}
},
DIVIDE() {
public int perform(int a, int b) {
return a / b;
}
};
public abstract int perform(int a, int b);
}
To call such code, you would then do something like:
int result = Operation.ADD(5, 6);
Then you could create a map of Strings to Operations, like so:
Map<String, Operation> symbols = new Map<String, Operation>();
symbols.put("+", Operation.ADD);
symbols.put("-", Operation.SUBTRACT);
symbols.put("/", Operation.DIVIDE);
symbols.put("*", Operation.MULTIPLY);
...
Finally, to use such a system:
symbols.get(n.getString(1).apply(tmp1, tmp2));
One advantage to using enumerations in this manner is that you have the luxury of comparing the operations on the data, should you choose to do so
Operation operation = symbols.get("*");
if (operation != Operation.MULTIPLY) {
System.out.println("Foobar as usual, * is not multiply!");
}
In addition, you get a centralized location for all operations, the only downside to this is that the Operation.java file might grow large with a sufficiently large set of operators.
The only issues that might exist long-term is that while such a system is useful and easy to read and understand, it really doesn't take into account precedence. Assuming your formula are all evaluated in the order of precedence, such a problem doesn't matter. Examples of expressing the formula in the order of precedence can be found in Reverse Polish Notation, Polish Notation, etc.
Where precedence does matter is when you are allowed to express items like:
4 + 5 * 2
where according to typical convention, the 5 * 2 should be evaluated before the 4 + 5. The only correct way to handle precedence is to form an evaluation tree in memory, or to guarantee that all input handles precedence in a simple, unambiguous manner (Polish Notation, Reverse Polish Notation, etc).
I'm assuming you know about the precedence issues, but thank you for letting me mention it for the benefit of those who haven't had to write such code yet.