OO design of Reverse Polish Notation Calculator - follow-up This is a revised version of my previous code.

This application will take input string like "3 2 + 1 -" and output 4 because it is the reverse Polish notation for (3+2)-1 = 4. This solution focuses on the design of classes.The current code has 2 operators (plus and minus) in default.  There are 2 constructors. 1 will create the default calculator. The other can take an additional HashMap that will map a string to an Operator.

The code works. Any further recommendations are much appreciated! Questions I have:


Do I need to write getters for fields that I didn't use, such as public String getInput().
I didn't write any setters for the non-static variables. Do I need them?




 import java.util.*;
 public class RPNCalculator {

    public Stack&lt;Integer&gt; stack;
    private String input;
    public Map&lt;String, Operator&gt; map;
    private String operators="";

    public RPNCalculator(String userInput){
        input = userInput;
        stack = new Stack&lt;Integer&gt;();
        // default hashmap initialization 
        map = new HashMap&lt;String, Operator&gt;();
        map.put("+", new Plus());
        map.put("-", new Minus());
        // this string is constructed for later use in processInput()
        for(String key: map.keySet()){
            operators+= key;
        }
    }
    public RPNCalculator(String userInput, HashMap&lt;String, Operator&gt; mapInput){
        input = userInput;
        stack = new Stack&lt;Integer&gt;();
        this.map = mapInput; 
        for(String key: map.keySet()){
            operators+= key;
        }
    }

    public Stack&lt;Integer&gt; getStack(){
        return this.stack;
    }
    public String getInput(){
        return this.input;
    }
    public void processInput(){
        StringTokenizer st = new StringTokenizer(input, " ");
        while (st.hasMoreTokens()){
            String str = st.nextToken();
            if(!operators.contains(str)){               //test whether the token is an operator 
                stack.push(Integer.parseInt(str));
            }
            else{
                map.get(str).calc(this);
            }
        }
        if(stack.size()!=1){
            System.out.println("The input expression is not the correct format");
        }else{
            System.out.println(stack.pop());
        }
    }
}


Other supporting classes and driver (contains main):

public abstract class Operator {
    abstract void calc(RPNCalculator rpn);
}
public class Minus extends Operator {
    @Override
    void calc(RPNCalculator rpn) {
        int a = rpn.getStack().pop();
        int b = rpn.getStack().pop();
        rpn.getStack().push(b-a);

    }
}
public class Plus extends Operator {
    @Override
    void calc(RPNCalculator rpn) {
        int a = rpn.getStack().pop();
        int b = rpn.getStack().pop();
        rpn.getStack().push(a+b);

    }
}
public class RPNDriver {
       public static void main(String[] args) {
           System.out.println("starting calculator...");
           RPNCalculator rpn = new RPNCalculator("1 21 + 2 -");
           rpn.processInput();
       }
}
Do I need to write getters for fields that I didn't use? such as
  public String getInput(). I didn't write any setters for the
  non-static variables. do I need them?


It depends. If you want to expose the field to the classes's clients, then you need a getter. For instance, it makes sense to write a getter for the stack in the calculator so that operators can use it (sure, you could have design it differently and pass a stack to an operator directly). It's really about the design of your class. There's no definitive answer. I don't think that you need a getter for the input here. 

The operators String is redundant. You can check if a string is in the map using map's containsKey method.   

I also think that the input should be passed as an argument to the processInput method, not to the constructor. I just makes more sense to me to build one calculator for a specific sets of operators and then run it on as many different inputs as you need. I don't think that the input is the essential part of the calculator entity. It's more like something the calculator can processes, not something it consists of. 

I'd also recommend to decouple the computations from the output. Each method should do one focused thing. The processInput should do exactly this: process the input and return the result (or throw an exception). Printing it is a different concern. It also makes your code more reusable: if you just return the value, you can still use the class if just need to evaluate the expression without printing it or if your need to display it differently.   

The comments should not repeat the code so something like is // default hashmap initialization is even worse than no comments as it clutters the code. It just creates more noise. It's clear that a new HashMap&lt;&gt;(); creates a new empty map. They should rather explain why specific decisions were made. It's also a good practice to write doc comments for your classes and methods to specify it's behavior (including what kind of exceptions it throws) so that one doesn't need to read the code of the method to figure out what it does and how it (and shouldn't) be used.

I'd also suggest to create a copy of the mapInput in this public RPNCalculator(String userInput, HashMap&lt;String, Operator&gt; mapInput) constructor (so that the map used by the calculator doesn't change even if the mapInput is later changed by the client). Either way, you need to document this kind of decisions so that the users of your class know if it's safe to change the map passed to the constructor later in their code.