Skip to main content
added 5 characters in body
Source Link
oopexpert
  • 3.2k
  • 11
  • 17

Try to use the standard implementation of a stack like java.util.StackArrayDeque. You have reinvented the wheel here.

Try to use the standard implementation of java.util.Stack. You have reinvented the wheel here.

Try to use the standard implementation of a stack like java.util.ArrayDeque. You have reinvented the wheel here.

Source Link
oopexpert
  • 3.2k
  • 11
  • 17

Standard Stack

Try to use the standard implementation of java.util.Stack. You have reinvented the wheel here.

State Pattern

Introduce the state pattern. I here provide you an example.

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;

public class NumberParser {

    
    public static void main(String[] args) {
        
        List<BigInteger> parse = new NumberParser("   10   22  32  ").parse();
        
        for (BigInteger bigInteger : parse) {
            System.out.println(bigInteger);
        }
        
    }
    
    
    private List<BigInteger> numbers;
    
    
    private final StringBuffer stringToParse;
    private final StringBuffer buffer;
    
    
    private State state;
    
    
    public NumberParser(String string) {
        this.stringToParse = new StringBuffer(string);
        this.buffer = new StringBuffer();
        this.setState(new Unknown());
    }
    
    
    private boolean hasCurrentChar() {
        return this.stringToParse.length() > 0;
    }

    
    private char removeCurrentChar() {
        if (hasCurrentChar()) {
            char ch = this.stringToParse.charAt(0);
            this.stringToParse.deleteCharAt(0);
            return ch;
        } else {
            throw new NoSuchElementException();
        }
    }
    
    private char currentChar() {
        if (this.stringToParse.length() > 0) {
            return this.stringToParse.charAt(0);
        } else {
            throw new NoSuchElementException();
        }
    }
    
    
    private void clearBuffer() {
        buffer.setLength(0);
    }
    

    private void recognizeNumber() {
        numbers.add(new BigInteger(buffer.toString()));
        clearBuffer();
    }


    public List<BigInteger> parse() {
        
        if (numbers == null) {
            
            this.numbers = new ArrayList<>();
            
            while (!(getState() instanceof End)) {
                getState().parse();
            }

        }
        
        return this.numbers;
        
    }

    
    private State getState() {
        return state;
    }


    private void setState(State state) {
        System.out.println(state.getStateInfo());
        this.state = state;
    }


    private interface State {
        public String getStateInfo();
        public void parse();
    }

    
    private interface End extends State {
    }

    
    private class Error implements End {

        @Override
        public String getStateInfo() {
            return "Something went wrong ...";
        }

        @Override
        public void parse() {
        }
        
    }
    

    private class NoMoreChars implements End {

        @Override
        public String getStateInfo() {
            return "No chars left.";
        }

        @Override
        public void parse() {
        }
        
    }


    private class RemoveWhiteSpaces implements State {

        @Override
        public String getStateInfo() {
            return "Removing white spaces.";
        }

        @Override
        public void parse() {
            
            if (hasCurrentChar()) {
                
                if (Character.isWhitespace(currentChar())) {
                    removeCurrentChar();
                } else {
                    setState(new Unknown());
                }
                
            } else {
                setState(new NoMoreChars());
            }
            
        }
        
    }

    
    private class Number implements State {

        @Override
        public String getStateInfo() {
            return "Parse digits.";
        }

        @Override
        public void parse() {
            
            if (hasCurrentChar()) {
                
                if (Character.isDigit(currentChar())) {
                    buffer.append(currentChar());
                    removeCurrentChar();
                } else {
                    recognizeNumber();
                    setState(new Unknown());
                }
                
            } else {
                recognizeNumber();
                setState(new NoMoreChars());
            }
            
        }

    }
    

    private class Unknown implements State {
        
        @Override
        public String getStateInfo() {
            return "Search ...";
        }

        @Override
        public void parse() {
            
            if (hasCurrentChar()) {
                
                if (Character.isWhitespace(currentChar())) {
                    setState(new RemoveWhiteSpaces());
                } else if (Character.isDigit(currentChar())){
                    setState(new Number());
                } else {
                    setState(new Error());
                }
                
            } else {
                setState(new NoMoreChars());
            }
            
        }
        
    }
    
}

This parser searches for numbers and returns them. Whitespaces separate numbers as whitespaces are allowed to occur multiple times. If you input alphanumeric characters the machine goes into the Error-State.

The main point is to avoid nested if-statements and have clear responsibilities during parsing. Furthermore your solution lacks extendability. If new requirements occur the state pattern helps you to manage them in a well-defined way.

First I suggest to have a state chart. UML state machines are appropriate.