集合---list
Posted xp0813
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了集合---list相关的知识,希望对你有一定的参考价值。
Iterable 是所有集合的超类, collection继承了iterable ,而list和set又继承了 collection,而在Iterable中定义了一个iterator()方法返回一个迭代器Iterator
而 Iterator是一个超类接口,为各种容器提供了公共的操作接口,里边有 hasNext(),next(),remove()三个方法
有子接口ListIterator和XMLEventReader
在ArrayList中的使用
List<String> list=new ArrayList<>();
list.add("abc");
list.add("edf");
list.add("ghi");
for(Iterator<String> it=list.iterator();it.hasNext();)
System.out.println(it.next());
在ArrayList内部定义了一个内部类Itr,该类实现了Iterator接口。
在Itr中,有三个变量分别是,cursor:表示下一个元素的索引位置,lastRet:表示上一个元素的索引位置,expectModCount:预期被修改的次数
关于遍历是不就可以删除集合中元素的问题:
如果在上边的for循环中增加list.remove(“abc”),会出现ConcurrentModificationException异常。
因为在你迭代之前,迭代器已经被通过list.itertor()创建出来了,如果在迭代的过程中,又对list进行了改变其容器大小的操作,那么Java就会给出异常。
因为此时Iterator对象已经无法主动同步list做出的改变,Java会认为你做出这样的操作是线程不安全的,就会给出善意的提醒(抛出 ConcurrentModificationException异常)
ArrayList中的源码实现
private class Itr implements Iterator<E>
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext()
return cursor != size; //当cursor不等于size时,表示仍有索引元素
@SuppressWarnings("unchecked")
public E next()
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
public void remove()
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
catch (IndexOutOfBoundsException ex)
throw new ConcurrentModificationException();
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer)
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size)
return;
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
while (i != size && modCount == expectedModCount)
consumer.accept((E) elementData[i++]);
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
final void checkForComodification()
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
通过查看源码发现原来检查并抛出异常的是checkForComodification()方法。在ArrayList中modCount是当前集合的版本号,
每次修改(增、删)集合都会加1;expectedModCount是当前迭代器的版本号,在迭代器实例化时初始化为modCount。我们看到在 checkForComodification()方法中就是在验证modCount的值和expectedModCount的值是否相等,
所以当你在调用了ArrayList.add()ArrayList.remove()时,只更新了modCount的状态,而迭代器中的expectedModCount未同步,
因此才会导致再次调用Iterator.next()方法时抛出异常。
但是为什么使用Iterator.remove()就没有问题呢?通过源码高亮的行发现,在Iterator的remove()中同步了expectedModCount的值,所以当你下次再调用next()的时候,检查不会抛出异常。
for循环与迭代器的对比:
* 效率上各有各的优势:
> ArrayList对随机访问比较快,而for循环中使用的get()方法,采用的即是随机访问的方法,因此在ArrayList里for循环快。
> LinkedList则是顺序访问比较快,Iterator中的next()方法采用的是顺序访问方法,因此在LinkedList里使用Iterator较快。
> 主要还是要依据集合的数据结构不同的判断。
以上是关于集合---list的主要内容,如果未能解决你的问题,请参考以下文章