【问题标题】:Deleting and adding objects to list while iterating迭代时删除和添加对象到列表
【发布时间】:2016-01-02 00:38:58
【问题描述】:

我正在尝试从列表中删除对象,但出现以下异常:

failure:java.util.ConcurrentModificationException null

这就是我尝试从列表中删除对象的方式:

private List<testVO> removeDuplicateEntries(List<testVO> sessionList,List<testVO> dbList){


        for (Iterator<testVO> dbIterator = dbList.listIterator(); dbIterator.hasNext(); ) {
            testVO voDB = dbIterator.next();

            for (Iterator<testVO> sessionIterator = sessionList.iterator(); sessionIterator.hasNext();) {
                testVO voSession = (testVO) sessionIterator.next();

                if(voDB.getQuestionID().intValue() == voSession.getQuestionID().intValue()){
                    //remove the object from sesion list
                    sessionIterator.remove();
                    //Add the object from DB to session list
                    sessionList.add(voDB);
                }

            }

        }

        return sessionList;
    }

我想删除当前在sessionList 中的重复项,并添加来自dbList 的重复项。

【问题讨论】:

标签: java listiterator


【解决方案1】:

您无法在迭代时添加到 sessionList。

    for (Iterator<testVO> dbIterator = dbList.listIterator(); dbIterator.hasNext(); ) {
        testVO voDB = dbIterator.next();

        List<testVO> toBeAdded = new LinkedList<>();
        for (Iterator<testVO> sessionIterator = sessionList.iterator(); sessionIterator.hasNext();) {
            testVO voSession = (testVO) sessionIterator.next();

            if(voDB.getQuestionID().intValue() == voSession.getQuestionID().intValue()){
                //remove the object from sesion list
                sessionIterator.remove();
                //Add the object from DB to session list
                //CANNOT DO: sessionList.add(voDB);
                toBeAdded.add(voDB);
            }
        }
        Collections.addAll(sessionList, toBeAdded);
    }

【讨论】:

  • (@Dariusz 对 addAll 的使用更好。)
【解决方案2】:
List<testVO> toRemove = ...
List<testVO> toAdd = ...

// in loop
toRemove.add(removed);
toAdd.add(added);

//after appropraite loops
yourList.addAll(toAdd);
yourList.removeAll(toRemove);

这里添加了toRemove,以防使用for循环的for-each版本;最好通过迭代器从集合中移除一个元素,因为它不会消耗更多的搜索资源。

【讨论】:

  • 添加很容易,但删除却很难——每个项目都必须线性搜索,因为没有迹象表明它可能在哪里。最好在实际找到项目时删除 - 使用迭代器。
【解决方案3】:

正如其他答案中所解释的,您无法在迭代时添加到集合中。您必须使用迭代器本身来修改信息 - 或者等到您完成迭代。

但是,普通的Iterator 只允许您删除项目。使用ListIterator,您还可以添加 到列表中。因此,如果您使用sessionList.listIterator() 而不是sessionList.iterator(),您将能够在迭代时添加项目。

不过,这与添加到列表(如果可能的话)的结果不同。假设你有一个列表:

[ A, B, C, D, E ]

您想用c 替换C 和用d 替换D。如果您使用列表迭代器,您的结果将是:

[ A, B, c, d, E ]

虽然将项目添加到列表中会导致:

[ A, B, E, c, d ]

因此,如果您希望将项目附加到末尾,您应该按照其他答案的指示进行操作,收集您要添加的所有项目,并在完成迭代 sessionListaddAll

但如果你想替换它们 ([ A, B, c, d, E ]),你可以使用列表迭代器:

for (ListIterator<testVO> sessionIterator = sessionList.listIterator(); sessionIterator.hasNext();) {
    testVO voSession = (testVO) sessionIterator.next();

    if(voDB.getQuestionID().intValue() == voSession.getQuestionID().intValue()){
        //remove the object from sesion list
        sessionIterator.remove();
        //Add the object from DB to the session list 
        sessionIterator.add(voDB);
    }

}

不同之处在于 sessionIterator 现在被声明为 ListIterator 并使用 sessionList.listIterator() 进行初始化,而且您使用的是 sessionIterator.add() 而不是 sessionList.add()

请注意,ListIterator 上的 add 操作是可选的,因此,根据列表实现,此方法可能不起作用并抛出 UnsupportedOperationException

【讨论】:

    猜你喜欢
    • 2019-02-12
    • 2012-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-10
    • 2012-11-11
    • 2016-12-02
    • 1970-01-01
    相关资源
    最近更新 更多