简体   繁体   中英

Exception in thread “main” java.util.NoSuchElementException

I'm practice to write java code and i try to fix this but i don't know how to fix it anymore. I'll show you my code.

In my Fortunecookie.java is:

public class FortuneCookie {
    private String subjectList;
    private String objectList;
    private String verbList;
    private int sWord;
    private int oWord;
    private int vWord;
    private Random random = new Random() enter code here;

    public FortuneCookie() {
        subjectList = "I#You#He#She#It#They";
        objectList = "me#you#him#her#it#";
        verbList = "hate#love#deny#find#hear#forgive#hunt#win#teach";
    }

    public String getFortuneMsg() {
        StringTokenizer subSt = new StringTokenizer(subjectList,"#");
        StringTokenizer objSt = new StringTokenizer(objectList,"#");
        StringTokenizer verbSt = new StringTokenizer(verbList,"#");
        sWord = subSt.countTokens();
        oWord = objSt.countTokens();
        vWord = verbSt.countTokens();
        int c1 = random.nextInt(sWord);
        String line1 = " ";
        String line2 = " ";
        String line3 = " ";
        while(subSt.hasMoreTokens()) {
            line1 = subSt.nextToken("#");
            for (int i=0;i<sWord;i++)
                if (i == c1) {
                    break;
                }
                else{
                    line1 = subSt.nextToken("#");
                }
        }
        int c2 = random.nextInt(oWord);
        while(objSt.hasMoreTokens()) {
            line2 = objSt.nextToken("#");
            for (int i=0;i<sWord;i++)
                if (i == c2) {
                    break;
                }
                else{
                    line2 = objSt.nextToken("#");
                }
        }
        int c3 = random.nextInt(vWord);
        while(verbSt.hasMoreTokens()) {
            line3 = verbSt.nextToken("#");
            for (int i=0;i<sWord;i++)
                if (i == c3) {
                    break;
                }
                else{
                    line3 = verbSt.nextToken("#");
                }
        }
        return line1+line2+line3;
    }

    public void setSubjectList(String aSubjectList) {
        subjectList = aSubjectList;
    }

    public void setObjectList(String aObjectList) {
        objectList = aObjectList;
    }

    public void setVerbList(String aVerbList) {
        verbList = aVerbList;
    }

    public void print() {
        StringTokenizer subSt = new StringTokenizer(subjectList,"#");
        StringTokenizer objSt = new StringTokenizer(objectList,"#");
        StringTokenizer verbSt = new StringTokenizer(verbList,"#");
        sWord = subSt.countTokens();
        oWord = objSt.countTokens();
        vWord = verbSt.countTokens();
        System.out.println("Subject List : "+subjectList);
        System.out.println("Object List : "+objectList);
        System.out.println("Verb List : "+verbList);
    }

And in my FortuneCookieTest.java is

public class FortuneCookieTest {
    public static void main(String[] args) {
        FortuneCookie ck = new FortuneCookie();
        System.out.println(ck.getFortuneMsg());
    }
}

And when I compile and run it:

//Exception in thread "main" java.util.NoSuchElementException
        at java.util.StringTokenizer.nextToken(Unknown Source)
        at java.util.StringTokenizer.nextToken(Unknown Source)
        at CS_111_Homework_2.FortuneCookie.getFortuneMsg(FortuneCookie.java:39)
        at CS_111_Homework_2.FortuneCookieTest.main(FortuneCookieTest.java:6)

How can I solve it?

In this part of the code, you can call objSt.nextToken("#") twice, and if the first calls gets the last element, on the second call you'll get the NoSuchElementException as no more elements are available.

while (objSt.hasMoreTokens()) {
    line2 = objSt.nextToken("#");
    for (int i = 0; i < sWord; i++)
        if (i == c2) {
            break;
        } else {
            line2 = objSt.nextToken("#");
        }
}

This is a different use case, but has the same problem

Actually there are several issues with the code, specially with this method getFortuneMsg() :

  1. you are using sWord for all the loops, instead you should use sWord for the first loop oWord for the second and vWord and for the last.
  2. Also you are calling line1 = subSt.nextToken("#"); before starting the loop so you have consumed one token already, this could produce NoSuchElementException i suggest to change this for (int i=0; i<sWord; i++) to this for (int i=0; i<sWord - 1; i++) to take in consideration the consumed token.
  3. And for this loop while(subSt.hasMoreTokens()) it will be started all over again if not all tokens are consumed (it could be happen when c1 < sWord ) .

Note: The code need some refactoring to prevent duplication and use loops wisely.

Edit: I didn't understand exactly what you are trying to achieve but if I were you I would like to change this method getFortuneMsg() to something like this:

 public String getFortuneMsg() {

    StringTokenizer[] tokenizers = {new StringTokenizer(subjectList, "#"), new StringTokenizer(objectList, "#"), new StringTokenizer(verbList, "#")};

    StringBuilder sb = new StringBuilder();
    for (StringTokenizer tokenizer : tokenizers) {

        int rCount = random.nextInt(tokenizer.countTokens());

        for (int i = 0; i < rCount; i++) {
            tokenizer.nextToken();
        }
        sb.append(tokenizer.nextToken());
    }
    return sb.toString();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM