action) { Objects.requireNo_.iterator().next()">
赞
踩
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());
}
使用方法:
ArrayList list=new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
Iterator iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
迭代器通常被称为轻量级对象(lightweight object):创建它的代价小。因此,经常可以看到一些对迭代器有些奇怪的约束。例如,Java 的 Iterator 只能单向移动。–摘自《java编程思想》
我们拿ArrayList举例,它实现了Collection接口中的Iterator iterator();方法
实现:
public Iterator<E> iterator() {
return new Itr();
}
new Itr()是ArrayList里面的内部类,该内部类实现了Iterator接口,重写了上面写的Iterator中的四个方法
事实上还有一个方法
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
这个方法在next()方法一开始就被调用:
public E next() {
checkForComodification();
......
}
expectedModCount是预计修改次数,在我们一开始创建iterator的时候就会赋值,后面就不会改变
modCount 是修改次数
ArrayList中,当我们添加元素的时候,modCount++,这时候modCount != expectedModCount,checkForComodification抛出异常,这就是为什么,迭代器遍历的时候不能添加元素的原因。如果想添加元素,可以使用ListIterator(下面会提到)
iterator.next()方法可以理解为从起始位置 越过 第一个元素 来到到 第一个元素与第二个元素之间的位置,返回刚刚越过的元素的引用也就是AAA
remove方法会删除上次调用next方法时返回的元素,所以如果要想删除一个元素实现要越过它。
如果我们要删除BBB和CCC我们需要
Iterator iterator = list.iterator();
iterator.next();
iterator.next();//来到BBB和CCC中间
iterator.remove();//删除BBB
iterator.next();//来到CCC右边
iterator.remove();//删除CCC
使用iterator不需要知道它所遍历的序列的类型信息
有一点需要注意:ArrayList,LinkedList是有序集合,迭代器从头遍历到尾,这也就意味着,像add这种依赖位置的方法可以实现,并且依赖于迭代器来实现。而像Set,Map这样的无序集合就不能add,只能使用Iterator,为了让list实现迭代器的add,我们有提供了ListIterator。
ListIterator的add方法添加的元素位置在迭代器前面
ListIterator还可以从尾往头遍历
boolean hasPrevious();
E previous();
当从尾往头遍历时,remove()删除的是右边的元素(也是刚刚越过的元素)
add方法只依赖迭代器的位置,而remove方法不同,它依赖迭代器的状态
所以add方法可以连续调用多次,而remove方法不可以连续调用两次
另外ListIterator还有一个方法:
void set(E e);
是用一个新元素替换调用next或preivous方法返回的上一个元素
public Iterator<E> iterator() {
return new Itr();
}
返回的是一个Itr内部类,它实现了Iterator接口
private class Itr implements Iterator<E> {
int cursor; // 要返回的下一个元素的索引
int lastRet = -1; // 返回的最后一个元素的索引; 如果最后一个元素被删除了就返回-1(在remove中会被赋值为-1)
int expectedModCount = modCount; //判断是否更改list结构(通过list.add()添加,list.remove()删除,注意:list里面的修改set(index,value)不改变表结构)
Itr() {}
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;
//把当前元素(也就是刚刚越过去的元素)的位置赋值给lastRet
return (E) elementData[lastRet = i];
}
public void remove() {
//确保删除前已经next()了
if (lastRet < 0)
throw new IllegalStateException();
//迭代器remove前会做是否更改list结构的判断
checkForComodification();
try {
//迭代器中的remove也是使用list.remove()
ArrayList.this.remove(lastRet); //lastRet刚刚越过去元素的下标
cursor = lastRet;
//删除后就被赋值为-1,上面是if (lastRet < 0)
//这就是为什么迭代器不能连续删除元素的原因
//lastRet 也可以理解为迭代器的状态,-1为删除元素后的状态
lastRet = -1;
//这段代码改变了expectedModCount
//只许州官放火,不许百姓点灯声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/145600
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。