简体   繁体   English

并发修改异常-子列表中列表迭代器的下一个操作中无法访问的情况

[英]Concurrent Modification Exception - unreachable case in next operation of list iterator in sublist

Consider the snippet extracted from the list iterator of the sub list inside an arraylist 考虑从arraylist内子列表的列表迭代器中提取的代码片段

                @SuppressWarnings("unchecked")
                public E next() {
                    checkForComodification();
                    int i = cursor;
                    if (i >= SubList.this.size)
                        throw new NoSuchElementException();
                    Object[] elementData = ArrayList.this.elementData;
                    if (offset + i >= elementData.length)
                        throw new ConcurrentModificationException();
                    cursor = i + 1;
                    return (E) elementData[offset + (lastRet = i)];
                }

cursor initially is set to 0. Imagine the arraylist and its sub list as below- 最初将游标设置为0。想象一下arraylist及其子列表如下-

el      original    sublist
0       a[0]
10      a[1]
20      a[2]        s[0]
30      a[3]        s[1]
40      a[4]        s[2]
50      a[5]        s[3]
60      a[6]        s[4]
70      a[7]
80      a[8]
90      a[9]

I see that the condition used in the above next method 我看到上面的下一个方法中使用的条件

if (offset + i >= elementData.length)
                            throw new ConcurrentModificationException();

will never hold true. 永远不会成立。

Because 因为

1) If you perform an add operation to the sublist, it will internally call the add method on the main arraylist and increments its size by 1. After performing the adding operation on the main list, it will increments the sub list size. 1)如果对子列表执行添加操作,它将在内部调用主数组列表的add方法,并将其大小增加1。在主列表上执行添加操作后,它将增加子列表的大小。 if the expansion is needed on the main list, it(internally backed up by an array ) will grow to the necessary size. 如果需要在主列表上进行扩展,则该扩展(内部由数组备份)将增长到所需的大小。

offset is the diff b/w the starting positions of the arraylist and sublist. 偏移量是数组列表和子列表的起始位置的差异。 Since the condition for i in the above snippet is already checked (i >= SubList.this.size ), the condition offset + i >= elementData.length is never going to be true. 由于已经检查了以上代码段中i的条件(i> = SubList.this.size ),因此条件offset + i >= elementData.length永远不会为真。

2) Similarly for the remove operation. 2)类似的删除操作。 The backing array never shrinks. 支持阵列永远不会缩小。 The removal is tracked by reducing the size by 1. And backing array length and size are two different things. 通过将大小减小1来跟踪删除情况。后备阵列的长度和大小是两件事。 size is not equal to backing array length. 大小不等于后备数组长度。

/**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;

What am I missing. 我想念什么。 Please suggest. 请提出建议。

The clue is ConcurrentModificationException rather than NoSuchElementException . 提示是ConcurrentModificationException而不是NoSuchElementException

If another thread removes an element during execution of this code, the condition may be true. 如果在执行此代码期间另一个线程删除了一个元素,则条件可能为true。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM