1、Iterator介绍
Iterator 用同一种逻辑来遍历集合。使得客户端自身不需要来维护集合的内部结构,所有的内部状态都由Iterator来维护。客户端从不直接和集合类打交道,它总是控制Iterator,向它发送"向前","向后","取当前元素"的命令,就可以间接遍历整个集合。
在Java中Iterator为一个接口,它只提供了迭代了基本规则,在JDK中他是这样定义的:对 collection 进行迭代的迭代器。
接口定义为:
public interface Iterator{
boolean hasNext();
Object next();
void remove();
}
其中:
Object next():返回迭代器刚越过的元素的引用,返回值是Object,需要强制转换成自己需要的类型
boolean hasNext():判断容器内是否还有可供访问的元素
void remove():删除迭代器刚越过的元素
2、ArrayList的Iterator实现。
在 ArrayList 内部首先是定义一个内部类 Itr,该内部类实现 Iterator 接口,如下:
private class Itr implements Iterator<E> {
//....
}
//....
}
在内部类实现了Iterator接口,而ArrayList的Iterator是返回的它的内部类Itr,所以我们主要看看Itr是如何实现的。
public Iterator<E> iterator() {
return new Itr();
return new Itr();
}
private class Itr
implements Iterator<E> {
int cursor;
//
下一个元素的索引位置
int lastRet = -
1;
//
上一个元素的索引位置
; -1 if no such
int expectedModCount = modCount; //修改的次数
modCount,记录了ArrayList结构性变化的次数
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();
}
}
final void checkForComodification() {
if (expectedModCount != ArrayList. this.modCount)
throw new ConcurrentModificationException();
}
if (expectedModCount != ArrayList. this.modCount)
throw new ConcurrentModificationException();
}
}
1、expectedModCount的初值为modCount
2、hasNext的判断条件为cursor!=size,就是当前迭代的位置不是数组的最大容量值就返回true
3、next和remove操作之前都会先调用checkForComodification来检查expectedModCount和modCount是否相等
如果没checkForComodification去检查expectedModCount与modCount相等,这个程序肯定会报ArrayIndexOutOfBoundsException
3 测试Iterator
public static void main(String[] args) {
List<String> stringList= new ArrayList<String>();
stringList.add( "a");
stringList.add( "b");
stringList.add( "c");
stringList.add( "d");
Iterator<String> it = stringList.iterator();
while(it.hasNext()){
List<String> stringList= new ArrayList<String>();
stringList.add( "a");
stringList.add( "b");
stringList.add( "c");
stringList.add( "d");
Iterator<String> it = stringList.iterator();
while(it.hasNext()){
String str = it.next();
if(str.contains(
"c")){
stringList.remove(str);
}
else {
logger.info(
"str:==========={}",str);
}
}
}
输出结果为:
str:===========a
str:===========b
d并没有输出, 因为在删除 c 的时候cursor为3,size也变成了3。所以hasNext就返回为false了,循环结束,从而后面的元素也不会输出了.
将stringList.remove(str); 改为 it.remove()
输出结果为:
str:===========a
str:===========b
str:===========d
因为iterator 的remove 方法,在删除当前元素的同时,将 cursor 置为了 2 并且将 expectedModCount 设为 modCount
; 维护了索引的一致性,而当前的size=3 所以 hasNext方法返回为true,循环继续,所以将d正常输出了。
整个过程 cursor、lastRet 、expectedModCount、size 的值变化为 (0 -1 4 4 ) ——>(1 0 4 4)输出a ——> (2 1 4 4)输出b——> (3 2 4 4 )删除c ——>(2 -1 5 3 )——>(3 2 5 3 )输出d——>cursor=size 循环结束