ArrayList、LinkedList的迭代器问题

不知道大家遇到过这样 的代码段没有

List<String> list = new LinkedList<String>();
list.add("A");
list.add("B");
list.add("C");
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
    list.add("D");   /*   list.set(0,"AA");*/    System.out.println(iterator.next());
}

我就曾经无意之中写过这样的代码段,程序在运行的时候报错java.util.ConcurrentModificationException。打开源码发现,每次在迭代器生成之后,要是用list.add() list.remove()方法改变链表或者数组的结构,迭代器操作都会报这个错误。我们贴出来源码看看为啥。

public E next() {
    checkForComodification();(0)
    if (!hasNext())
        throw new NoSuchElementException();
    lastReturned = next;(1)
    next = next.next;
    nextIndex++;(2)
    return lastReturned.item;
}

(0)这个过程就是跑错的地方,也就是说迭代器不允许我们再修改被引用的链表结构。  next、nextIndex都是初始化迭代器的时候赋值的。

ListItr(int index) {
    // assert isPositionIndex(index);
    next = (index == size) ? null : node(index);
    nextIndex = index;
}

如果没有(0),我们用list.add("D"); 这样的代码改变了原来的list结构,那么(2)中的
nextIndex
不会是原来的值了。这样就会导致取值混乱。
举个栗子
链表
1--》2--》3--》4
在迭代器到达2的时候,用add方法在2之前给链表添加一个值
1--》D-->2--》3--》4而此时nextIndex依然在2,下次获取值又获取到了数据2,导致遍历链表数据混乱。所以在迭代器创建之后,不允许再修改被引用链表的结构。另外,迭代器是非线程安全的,api建议我们使用 List list = Collections.synchronizedList(new LinkedList(...))
保证线程安全。

时间: 2024-11-06 10:19:52

ArrayList、LinkedList的迭代器问题的相关文章

List ArrayList LinkedList vector简介与区别

ArrayList,LinkedList,Vestor这三个类都实现了java.util.List接口,但它们有各自不同的特性,主要如下: ArrayList:底层用数组实现的List 特点:查询效率高,增删效率低 轻量级 线程不安全 LinkedList:底层用双向循环链表 实现的List 特点:查询效率低,增删效率高 Vector: 底层用数组实现List接口的另一个类 特点:重量级,占据更多的系统开销 线程安全 一.同步性 ArrayList,LinkedList是不同步的,而Vestor

ArrayList LinkedList Vector

ArrayList是基于数组实现的,没有容量的限制. 在删除元素的时候,并不会减少数组的容量大小,可以调用ArrayList的trimeToSize()来缩小数组的容量. ArrayList,LinkedList,Vestor这三个类都实现了java.util.List接口,但它们有各自不同的特性,主要如下: ArrayList:底层用数组实现的List 特点:查询效率高,增删效率低 轻量级 线程不安全 LinkedList:底层用双向循环链表 实现的List 特点:查询效率低,增删效率高 Ve

ArrayList,LinkedList源码解析

在java中,集合这一数据结构应用广泛,应用最多的莫过于List接口下面的ArrayList和LinkedList; 我们先说List, 1 public interface List<E> extends Collection<E> { 2 //返回list集合中元素的数量,若数量大于Integer.MAX_VALUE,则返回Integer.MAX_VALUE 3 int size(); 4 5 //判读集合内是否没有元素,若没有元素返回true 6 boolean isEmpt

描述一下 ArrayList,LinkedList,Vestor各自实现和区别

ArrayList,LinkedList,Vestor这三个类都实现了java.util.List接口,但它们有各自不同的特性,主要如下: 一.同步性 ArrayList,LinkedList是不同步的,而Vestor是同步的.所以如果不要求线程安全的话,可以使用ArrayList或LinkedList,可以节省为同步而耗费的开销.但在多线程的情况下,有时候就不得不使用Vector了.当然,也可以通过一些办法包装ArrayList,LinkedList,使他们也达到同步,但效率可能会有所降低.

ArrayList,LinkedList的对比

ArrayList,LinkedList都是Collection接口的通用实现方式,两者采用了不用的存储策略,用来适应不同场合的需要. 实现方式 ArrayList的内部采用集合的方式存储数据 唯一需要注意的是对于容量超过阈值的处理逻辑,数组的默认容量大小是10,最大容量是Integer.Max_Value,超过最大容量会抛内存溢出异常, 扩容机制看下面 扩容后的容量是原有容量的1.5倍 LinkedList的实现方式 内部采用双向链表Node内部类来存储数据,由于采用了双向链表,LinkedL

Android ArrayList LinkedList Set HashMap的介绍.

在Android开发中我们经常需要对数据进行分类和操作,对于轻量级的数据存储我们可能不需要动用SQLite或效率以及类库不完善的XML,由于 SharedPreferences不具备数据枚举方法,如果仅仅是一个String或Int数组可以通过一个标记分割设计外,我们还是主要来看看 Android或者说Java提供的基础数据类型辅助类ArrayList LinkedList Set HashMap的介绍. 在Java中提供了Collection和Map接口.其中List和Set继承了Collect

安卓 ArrayList,LinkedList,HashSet,Vector,TreeSet的区别和使用

java的集合就那么几种 总体为:List,Set,Map (都是接口由其子类去实现具体的方法) ArrayList,LinkedList,Vector都属于List List:元素是有顺序的,元素可以重复因为每个元素有自己的角标(索引)  |-- ArrayList:底层的数据结构是数组结构,特点是:查询很快,增 删 稍微慢点,线程不同步 |-- LinkedList:底层使用的是链表数据结构,特点是:增 删很快,查询慢. |--Vector:底层是数组数据结构,线程同步,被ArrayList

ArrayList,LinkedList,Vestor

Collection是最基本的集合接口,声明了适用于JAVA集合的通用方法,list和set都继承自collection接口. Collection接口的方法 boolean add(Object o):向集合中加入一个对象的引用 void clear():删除集合中所有的对象,即不再持有这些对象的引用 boolean isEmpty():判断集合是否为空 boolean contains(Object o): 判断集合中是否持有特定对象的引用 Iterartor iterator():返回一个

ArrayList&amp;LinkedList&amp;Map&amp;Arrays

Java集合框架 1:集合接口 1.1:Collection接口 Collection接口是构造集合框架的基础.它声明所有类集合都将拥有的核心方法 Boolean add(Object obj) 将obj加入到调用类集合中,加入返回true 否则 返回 false Boolean addAll(Collection c) 将c中所有元素都加入到类集合中,都加入返回true否则 false Void clean() 从调用类集合中删除所有元素 Boolean contains(Object obj