【问题标题】:Java: `iterator.remove` throws IllegalStateExceptionJava:`iterator.remove` 抛出 IllegalStateException
【发布时间】:2020-05-17 22:52:43
【问题描述】:

我在thread 中有一个iterator,我正在尝试删除重复的记录。

 Runnable readingThread = new Runnable() {
        @Override
        public void run() {

            Iterator<Demand> iterator = null;
            for (iterator = demandListFromFile.iterator(); iterator.hasNext();) {
                Demand demand = iterator.next();

                /**
                 * Find and assign the Item ID
                 */
                if (itemListHashMap.containsValue(demand.getItem().getItemName())) {
                    demand.getItem().setIditem(itemListHashMapReversed.get(demand.getItem().getItemName()));

                } else {
                    unavailableItemsList.add(demand.getItem().getItemName());
                }


                /**
                 * Find and remove duplicate records
                 */
                for (Map.Entry<Date, String> entry : demandListHashMap.entries()) {

                    if (demand.getDueDate().equals(entry.getKey()) && demand.getItem().getItemName().equals(entry.getValue())) {

                        iterator.remove();
                    }

                }

            }

        }

删除一些项目后,iterator.remove 抛出以下异常

Exception in thread "Thread-0" java.lang.IllegalStateException
    at java.base/java.util.ArrayList$Itr.remove(ArrayList.java:1009)
    at com.xxx.xxx.ui.Home$7.run(Home.java:455)
    at java.base/java.lang.Thread.run(Thread.java:834)

为什么会这样?请注意,我已经删除了迭代器前后的代码,以保持这篇文章的简短。

【问题讨论】:

  • 只是因为你的应用程序。有图形用户界面,并不意味着添加swing 标签是合适的。保留与问题相关的标签。
  • 你是否试图从迭代器中删除 (iterator.remove();) ?还是来自收藏?如需更多帮助,请发布minimal reproducible example 并标记引发异常的行。
  • 由于.remove() 在嵌套循环中被调用,您可以多次调用它吗?如果是这样,这将导致异常被抛出。您应该在调用 remove 后立即跳出循环。是的,@c0der 是对的——您需要创建并发布一个minimal reproducible example 以充分允许在不猜测的情况下回答问题。

标签: java iterator illegalstateexception


【解决方案1】:

Iterator.java 删除方法:

    @throws IllegalStateException if the next method has not
              yet been called, or the remove method has already
              been called after the last call to the next method
    void remove() {
        ..
    }

问题出在您的 for 循环“查找并删除重复记录”中,您可能不止一次调用 iterator.remove。 remove 方法会删除您正在查看的当前元素,因此您每次使用 next() 只能调用它一次。为确保只调用一次,请在iterator.remove(); 下方添加break 语句

【讨论】:

  • 是的,这也是我的想法。 1+
【解决方案2】:

@CausingUnderflowsEverywhere 所说的理由完全正确。

此外,在看到实现之后,iterator.remove 元素在内部调用了ArrayList.remove 方法。

ArrayList 正在维护一个名为 lastRet 的变量中返回的最后一个元素的索引 移除元素后,ArrayList.remove 方法将 lastRet 设置为 -1。

ArrayList.remove 的第一个检查是

if (lastRet < 0)
{
     throw new IllegalStateException();
}

这就是在后台发生的事情。

【讨论】:

    猜你喜欢
    • 2019-05-29
    • 2014-04-17
    • 1970-01-01
    • 2014-09-11
    • 1970-01-01
    • 2019-06-10
    • 2015-02-15
    • 1970-01-01
    相关资源
    最近更新 更多