Iterator接口
Iterator有两个必须实现的方法。
hasNext用于判断是否包含下一位;
next用于返回当前值,同时光标向后移。
另外两个默认方法是否实现是可选的
因此要想判断一个数据结构支持remove?那么必须看它的remove()如何实现。
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() {
throw new UnsupportedOperationException("remove");
}
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
AbstractList的内部类Itr实现了Iterator接口,如下:
private class Itr implements Iterator<E> {
/**元素的下标
* Index of element to be returned by subsequent call to next.
*/
int cursor = 0;
/**上一个元素的下标。如果元素已被删除就设置为-1
* Index of element returned by most recent call to next or
* previous. Reset to -1 if this element is deleted by a call
* to remove.
*/
int lastRet = -1;
/**允许修改的次数,违规操作会抛异常
* The modCount value that the iterator believes that the backing
* List should have. If this expectation is violated, the iterator
* has detected concurrent modification.
*/
int expectedModCount = modCount;
/*检查是否还有下一个元素*/
public boolean hasNext() {
return cursor != size();
}
/*光标下移,并且返回当前的元素*/
public E next() {
checkForComodification();
try {
int i = cursor;
E next = get(i);
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
/*移除元素*/
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
AbstractList.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
从下面的代码可以看出,iterator.remove()是删除的游标的上一个元素。因此必须要把游标推到下一位,才能删除上一位。这也就导致了为什么下面的代码报错,而加上注释的代码才不报错
public static void linkedHashSetTest() {
LinkedHashSet<Integer> set = new LinkedHashSet<>();
set.add(2);
set.add(2);
set.add(3);
set.add(1);
Iterator<Integer> it = set.iterator();
int i = 0;
while (it.hasNext()) {
//System.out.println(it.next()); // 输出值,并且游标下移
if(i == 1)
it.remove();
i++;
}
it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}