从ArrayList中删除随机项导致ConcurrentModificationException

时间:2015-06-26 19:55:22

标签: java arraylist concurrentmodification

所以,我的代码遇到了一些麻烦,我不知道为什么,或者如何绕过它。我正在编写一个方法,它将获取对象列表并根据某些规则对其进行过滤。应用所有规则后,如果列表仍然超过一定的大小,我需要从特定子列表中随机选择项目然后丢弃其余的。我遇到的问题来自这段代码:

List<Group> filteredList = groupList.subList(0, firstMatch);

if(filteredList.size() < MAX_NUM_RETURNED){
    //This sub list is where I need to pull random items from
    List<Group> subList = new ArrayList<Group>();
    subList = groupList.subList(firstMatch, lastMatch); 

    Random rand = new Random();

    while(filteredList.size() < MAX_NUM_RETURNED){
        int randPos = rand.nextInt(subList .size());
        //remove a random group from the sublist and add it to the filtered list
        filteredList.add(subList.remove(randPos));      
    }
}

filteredList以0 - n组开头,如果它的大小小于一个子集中的最大随机组,则直到它达到该数字为止。

问题是当调用filteredList.add(subList.remove(randPos));行时出现ConcurrentModificationException错误,程序停止。

我查找了导致此错误的原因,但我看到的所有示例似乎都不适用于此情况。我没有迭代任何一个列表,我只是根据其中一个的大小运行循环。我见过的大多数修复ConcurrentModificationException的建议都是创建一个迭代器并使用remove()但是只删除了迭代器中的下一个项目,我每次都需要删除一个随机项

我的问题是,我是否需要做出一些明显的改变以避免并发问题,或者整个方法是否存在根本缺陷?

P.S。可能存在一些低效的代码或一些尚未处理的边缘情况。我正在做TDD并且尚未完成所有测试用例。目前的测试结果是,当filteredList的大小为0时,subList包含原始groupList.中的每个组一旦此测试停止破坏,我将重构并继续工作其他测试案例。

1 个答案:

答案 0 :(得分:1)

修改subList时,您还修改了groupList。因此,如果您在此过程中迭代groupList,您将获得ConcurrentModificationExceptions。

听起来你不需要修改groupList(因为你所追求的是filteredList)。因此,尝试将subList列为自己的列表而不是groupList的视图:

List<Group> subList = new ArrayList<>(groupList.subList(firstMatch, lastMatch));