调用.next()后迭代器抛出IllegalStateException异常

3
//This method compares two ArrayLists of strings and compares whether the words in one array list contain the letters in the other.

    public static void remove()
    {
        //Create iterators for both stringList and letterList
        Iterator<String> iterWords = stringList.iterator();
        Iterator<String> iterLetters = letterList.iterator();

        //First while loop will go over all strings in stringList via the iterWords iterator
        while(iterWords.hasNext())
        {
            //iterWords now has a .next() call

            String word = iterWords.next();
            //Second while loop that should run over each letter in letterList and compare it to each word in stringList
            while(iterLetters.hasNext())
            {
                //iterLetter now has a .next() call
                String letter = iterLetters.next();
                //if statement to remove the entry in stringList if it does not contain the current letter.  It is this part that throws the illegalstateexception
                if(word.contains(letter) == false)
                {
                    //This is the line that is causing the illegalstateexceptions
                    iterWords.remove();
                }           
            }
        }
    }

大家好,我正在寻求关于迭代两个ArrayList时遇到的异常的见解。我已经简化了上述的ArrayList并删除了与问题无关的任何方法。 在最后一个iterWords.remove()上我得到了一个illegalstateexception异常。在外部while循环中,我已经执行了iterWords.next(),所以iterWords.remove()应该可以看到要删除的东西。
我猜想这是因为我从内部while循环中调用iterWords.remove()而引起的异常。你认为这可能是原因吗? 感谢您能带来的任何见解。

嗯...一个用于“比较”事物的方法不应该被称为remove - Jim Garrison
是的,你说得很对。我只是为了发帖方便读者知道这就是出现.remove()问题的方法而给它起了这个名字。 - user2714543
1个回答

4

首先,您应该阅读并发布异常信息。

其次:您在仅调用一次next()之后多次调用remove():与单词中不包含的字母数量相同。

第三:由于您始终使用相同的字母迭代器,因此一旦完成第一个单词,您就不再迭代字母了。

因此,您必须:

  • stop iterating on letters as soon as you've removed the word
  • recreate the letter iterator at each iteration of the outer loop. Or better, just use a foreach loop: you don't need an iterator for the inner loop. Your code would be much simpler, readable and safer if you used methods:

    for (Iterator<String> it: words; it.hasNext(); ) {
        String word : it.next();
        if (anyLetterNotInWord(letters, word) {
            it.remove();
        }
    }
    

如果您使用的是Java 8,则可以将其简化为

words.removeIf(word -> anyLetterNotInWord(letters, word));

其中anyLetterNotInWord()可以被定义为

return letters.stream().anyMatch(letter -> !word.contains(letter));

非常感谢!是的,那绝对是问题所在。现在它工作得很好。关于Java 8的信息非常有趣。与我混乱的方法相比,那似乎更容易使用 :)。再次感谢你! - user2714543
不客气。如果您不知道,这里说谢谢的方式是通过点赞和/或接受答案。这也向其他人表明您的问题已得到解决。 - JB Nizet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接