-1

I am trying to see if the next token in a string is equivalent to map key, and adding a message to an array list.

ArrayList<String> trace = new ArrayList<String>();
if(!element.startsWith("PRINT")) {
            while(st.hasMoreTokens()) {
                tokens.add(st.nextToken());
            }

            for(String key: expression.keySet())
                if(st.nextToken() == key)
                    trace.add(key + "Changed from " + expression.get(key) + " to " + tokens.get(2));

            expression.put(tokens.get(0),Integer.parseInt(tokens.get(2)));
            tokens.clear();
}

ERROR MESSAGE

    Exception in thread "main" java.util.NoSuchElementException
    at java.util.StringTokenizer.nextToken(StringTokenizer.java:349)
    at Commander.main(Commander.java:45)
Imran
  • 429
  • 9
  • 23
Mutating Algorithm
  • 2,604
  • 2
  • 29
  • 66
  • 1
    Replace if(st.nextToken() == key) with if(st.hasMoreTokens() && st.nextToken() == key), i think it would solve your problem. – dReAmEr Sep 17 '14 at 04:33
  • 1
    Outside of the fact that you can't compare strings with `==` (which is what `st.nextToken() == key` is doing; don't do that), you don't specify what your tokenizer is breaking things up by, nor do you specify what your initial input string is. – Makoto Sep 17 '14 at 04:34
  • You shouldn't use [`StringTokenizer`](http://docs.oracle.com/javase/7/docs/api/java/util/StringTokenizer.html), the Javadoc reads (in part) *`StringTokenizer` is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the `split` method of `String` or the `java.util.regex` package instead.* – Elliott Frisch Sep 17 '14 at 04:34

1 Answers1

3

The problem is with st.nextToken() call.

You are checking st.hasMoreTokens() only once but calling st.nextToken() twice. And it is throwing the error.

During 1st while loop you are reading all the tokens:

while(st.hasMoreTokens()) {
    tokens.add(st.nextToken());
}

Since 'all' the tokens are already read, now when you try to read the token again inside the for loop you will get the error.

if(st.nextToken() == key) {
    trace.add(key + "Changed from " + expression.get(key) + " to " + tokens.get(2));
}

There is also another potential problem. You are trying to convert the 3rd token to an Integer. It might fail there as well:

// Value of tokens.get(2) is "string"
Integer.parseInt(tokens.get(2))

You will get error here also. It would be good to check if tokens.get(2) is of numeric type or not. like:

int value = 0;
if (StringUtils.isNumeric(tokens.get(2))) {
    value = Integer.parseInt(tokens.get(2));
}
// Default value will be 0.
expression.put(tokens.get(0), value);

Reference: StringUtils.isNumeric()

So, the modified code will be like:

ArrayList<String> trace = new ArrayList<String>();
if(!element.startsWith("PRINT")) {
    List<String> tokens = new ArrayList<String>();
    while(st.hasMoreTokens()) {
        tokens.add(st.nextToken());
    }

    // Size of tokens has to be more then 3, otherwise you will get another error.
    if (tokens.size() >= 3) {
        for(String key: expression.keySet()) {
            if(tokens.get(0).equals(key)) {
                 // Do your other operations...
                 trace.add(key + "Changed from " + expression.get(key) + " to " + tokens.get(2));
            }
        }

        // Do some more operations ...
        int value = 0;
        if (StringUtils.isNumeric(tokens.get(2))) {
            value = Integer.parseInt(tokens.get(2));
        }
        // Default value will be 0.
        expression.put(tokens.get(0), value);
    }
    tokens.clear();
}
kmario23
  • 57,311
  • 13
  • 161
  • 150
Ambrish
  • 3,627
  • 2
  • 27
  • 42