arraylist等记录修改次数modCount有什么作用?

下面是源码中的注释,可以参考。

大概意思就是说:在使用迭代器遍历的时候,用来检查列表中的元素是否发生结构性变化(列表元素数量发生改变)了,主要在多线程环境下需要使用,防止一个线程正在迭代遍历,另一个线程修改了这个列表的结构。好好认识下这个异常:ConcurrentModificationException。对了,ArrayList是非线程安全的。

This field is used by the iterator and list iterator implementation returned by the iterator and listIterator methods. If the value of this field changes unexpectedly, the iterator (or list iterator) will throw a ConcurrentModificationException in response to the next, remove, previous, set or add operations. This provides fail-fast behavior, rather than non-deterministic behavior in the face of concurrent modification during iteration.

public class TestArrayListIterator {
    public static void main(String[] args)  {
        ArrayList list = new ArrayList();
        list.add(10);
        Iterator iterator = list.iterator();
        while(iterator.hasNext()){
            Integer integer = iterator.next();
            if(integer==10)
                list.remove(integer);   //注意这个地方
        }
    }
}

题主可以调试下上面的这个程序,会报运行时异常 ConcurrentModificationException
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
	at java.util.AbstractList$Itr.next(Unknown Source)
	at  com.notify.TestArrayListIterator.main(TestArrayListIterator.java:17)
在使用迭代器遍历的时候,如果使用ArrayList中的remove(int index) remove(Object o) remove(int fromIndex ,int toIndex) add等方法的时候都会修改modCount,在迭代的时候需要保持单线程的唯一操作,如果期间进行了插入或者删除,就会被迭代器检查获知,从而出现运行时异常

事实上在我们remove掉这个元素之后 ,该ArrayList的size()的值就变为了0,而此时Iterator的游标cursor是 1 ,在ArrayList迭代器的hasNext()方法中
public boolean hasNext() {
            return cursor != size();
	}
当中判断出cursor 确实不等于 size() 哭cry!!!!
然后循环又继续跑了!!!



如果我们不进行modCount和expectedModCount(创建迭代器的时候将当时的modCount赋值给expectedModCount),这个程序肯定会报ArrayIndexOutOfBoundsException,这样的异常显然不是应该出现的(这些运行时错误都是使用者的逻辑错误导致的,我们的JDK那么高端,不会出现使用错误,我们只抛出使用者造成的错误,而这个错误是设计者应该考虑的),为了避免出现这样的异常,定义了检查。


又想,为什么不把hasNext()的判断改为cursor <=size()呢?但是我们还有可能 add()这样的话就会导致数据混乱,事实上线程安全本身就不允许读的时候被修改





曾经在霸面大众点评时,面试官就出了一道题:

		ArrayList list = new ArrayList();
		for(int i =0;i<1000;i++){
			list.add("sh"+i);
		}

		for(int i= 0;list.iterator().hasNext();i++){
			list.remove(i);
			System.out.println("秘密"+list.get(i));		
		}

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 500, Size: 500
	at java.util.ArrayList.rangeCheck(ArrayList.java:635)
	at java.util.ArrayList.remove(ArrayList.java:474)
	at com.test.StringTest.main(StringTest.java:26)

会报什么错,当时仔细回忆分析了一下remove()的源码,但还是傻逼一样说报空指针错误。。。。。。。。。。。。。

你可能感兴趣的:(jdk源码分析)