有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java无法理解为何抛出ConcurrentModificationException

我有ConcurrentModificationException,不知道为什么。我知道尝试使用for循环遍历列表并删除循环块中的元素是个坏主意,可能会引发这样的异常,但我不知道如何在我的情况下修复它

 private static final List<Integer> originalList = new ArrayList<>();

    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            originalList.add(i);
        }


        final int MAX_GROUP_SIZE = 5;
        int partitionSize = 4;

        List<List<Integer>> partitions = new LinkedList<>();

        for (int i = 0; i < originalList.size(); i += partitionSize) {
            partitions.add(originalList.subList(i,
                    Math.min(i + partitionSize, originalList.size())));
        }

        int lastGroupSize = partitions.get(partitions.size() - 1).size();

        if (lastGroupSize < partitionSize && partitions.size() > lastGroupSize){
            List<Integer> lastGroup = partitions.remove(partitions.size() - 1);
            for (int i = 0; i < lastGroupSize; i++) {
                partitions.get(i).add(lastGroup.get(i));
            }
        }
        System.out.println("GROUPS: " + partitions.size());
        printGroups(new LinkedList<>(partitions));
    }

共 (1) 个答案

  1. # 1 楼答案

    问题是对^{}的调用不会创建新列表。正如javadoc所说:

    Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive.

    javadoc还说:

    The semantics of the list returned by this method become undefined if the backing list (i.e., this list) is structurally modified in any way other than via the returned list.

    当您调用partitions.get(i).add(...)时,您是在结构上修改originalList,从而导致错误

    我相信你不是有意的,所以要解决这个问题,你只需要确保你的子列表独立于原始列表,即副本,这很容易做到:

    new ArrayList<>(originalList.subList(...))
    

    使用^{}构造函数将创建子列表的副本

    所以,改变这个说法:

    partitions.add(originalList.subList(i,
            Math.min(i + partitionSize, originalList.size())));
    

    为此:

    partitions.add(new ArrayList<>(originalList.subList(i,
            Math.min(i + partitionSize, originalList.size()))));