Java中为了将各种对象放在一块儿,提供了容器这种东东,但众所周知,Java里容器很多,每一种容器的存储结构都不一样,当我们需要遍历容器里的所有元素时便不可能只用一种或少有的几种方法去方便地完成遍历。那么在Collection接口里面定义了 iterator() 方法,而这个方法由各容器类去具体实现。Alei查看API文档和某些容器类的源码,发现此方法返回了一个Iterator接口对象,准确的说,是返回了一个可以专门迭代各容器类的迭代器对象。以ArrayList为例,iterator() 方法返回了一个属于容器类里面的私有内部类Itr的一个对象,并可能(当把返回值赋予一个迭代器引用)将这个对象的虚拟内存地址交给Iterator接口的一个引用:
1、当调用ArrayList类的 iterator() 的方法时:
public Iterator<E> iterator() {
return new Itr();
}
2、ArrayList里面又定义Itr内部类,你将看到,hasNext()、next()、remove()是在这个内部类里面重写的。
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;
}
@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();
}
}
其他各容器类对实现 iterator() 的方法并不相同,但最终都会返回一个属于自己的迭代器,且已经将Iterator接口里定义的方法重写过。这下Alei基本理解了迭代器,且不是那么懵逼了^_^!