源码解析之迭代器

今天看了迭代器的源码,发现并不难,接下来记录讲解

我们直到迭代器Iterator是一个接口,它的接口与本身并没有全部实现方法。

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());
    }
}

最下面的方法我没看,以后有时间看了再更

既然没有实现next等常用方法,我们知道迭代器是服务与集合类Collection中,那么我们集合类Collection中找找看。

Iterator<E> iterator();

我们发现collection中只有一个迭代器类型的属性,既然找不到我们继续向下找

我们直接去ArrayList类里去找:


我们发现iterator方法继承自AbstractList抽象类

public Iterator<E> iterator() {
        return new Itr();
    }

那我们去找itr类。

private class Itr implements Iterator<E> {
      //这个属性记录上一次遍历的结点的下一个结点的索引
        int cursor = 0;

      //这个属性记录上一次遍历的结点的索引。如果这个结点被删除则设这个属性为-1
        int lastRet = -1;

/*这两个属性与快速失败有关,代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。
集合在被遍历期间如果内容发生变化,就会改变modCount的值。每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值,是的话就返回遍历;否则抛出异常,终止遍历。*/
       
  int expectedModCount = modCount;

         //判断是否遍历到末尾
        public boolean hasNext() {
             
//这里说下因为索引是从0开始的,所以应该到size()-1结束,但是cursor存的是下一个结点的索引,所以这么写
            return cursor != size();
        }
//获取下一个结点的操作
        public E next() {
             //每次遍历每个元素的时候都要知道是否更改了集合类
            checkForComodification();
            try {
                int i = cursor;//获取索引坐标
                E next = get(i);//这个get是ArrayList实现的方法
                lastRet = i;//记录当前结点的索引
                cursor = i + 1;//记录cursor的值,用于下次计算
                return next;//返回这个元素
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

//移除方法
        public void remove() {
           //因为迭代器的remove方法是移除上一个遍历的元素,
            if (lastRet < 0)//当上一个遍历的元素被移除且没遍历新的元素抛出异常
                throw new IllegalStateException();
            checkForComodification();//每次操作集合时都要确定集合是否被更改

            try {
                //删除集合元素
                AbstractList.this.remove(lastRet);
		//索引-1
                if (lastRet < cursor)
                    cursor--;
		//因为删了这个结点所以lastRet赋值为-1
                lastRet = -1;
		//因为这操作允许,所以我们更改expectedModCount的值
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }
       //这个方法就是判断集合是否再迭代过程中被非法更改
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

AbstractList.this.remove(lastRet);

看这句,我们的Itr 是AbstractList的内部类,用外部类.this.方法访问外部类的方法


猜你喜欢

转载自blog.csdn.net/Sunmeok/article/details/81051581
今日推荐