Iterable
Iterable的作用就是获取一个新的迭代器
,每次获取的都是cursor重新开始的迭代器。而Iterable接口的iterator()
方法的作用就是每次专门创建一个新的迭代器。
Iterable接口是顶级父接口,声明一个可以获取迭代器的特性,他是Collection接口的父接口,List和set是Collection的子接口。
Iterator
Iterator是具体的迭代器类,负责定义如何迭代。一般由集合类自定义,例如ArrayList的源码:
public Iterator<E> iterator() {
return new Itr(); //内部类
}
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;
Itr() {}
....
}
iterator.remove()和 list.remove(item);区别
后者有可能报ConcurrentModificationException
正例:
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (删除元素的条件) {
iterator.remove();
}
}
反例:
for (String item : list) {
if ("1".equals(item)) {
list.remove(item);
}
}
源码因是每次next()会执行checkForComodification(),进行检查,即modCount != expectedModCount
判断,如果是 iterator.remove(),会重置2个变量的置,保证相同,如果是 list.remove(item),导致不相同,会报错
我们以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;
Itr() {}
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 (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
Iterator 和 ListIterator 区别
区别在于:
- 1.ListIterator 只能对 List 迭代,而 Iterator 不仅可以对 List 迭代,还可以迭代 Set
- 2.ListIterator 可以
双向迭代
,而 Iterator 只能单向迭代。
ListIterator 继承 Iterator 接口并增加了更多的方法,如下图: