java迭代器

本文源码基于JDK1.7

Iterable获取迭代器接口

Iterable接口中只有一个iterator方法,用来获取迭代器

package java.lang;

import java.util.Iterator;

public interface Iterable<T> {
    Iterator<T> iterator();
}

Iterator迭代器行为定义接口

迭代器定义接口,有三个抽象方法

hashNext():获取下一个元素

next():遍历到下一个接口

remove():移出当前遍历到的元素

package java.util;

public interface Iterator<E> {
    boolean hasNext();

    E next();

    void remove();
}

java集合中的迭代器

ArrayList相关类图

Collection接口继承Iterable接口同时也继承了iterator方法,

public interface Collection<E> extends Iterable<E>

 List接口继承Collection接口同时也继承了iterator方法

public interface List<E> extends Collection<E> 

 实现类ArrayList实现了List接口,具体实现了iterator方法

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable

在学习ArrayList中的iterator方法之前,我们首先要学习ArrayList中的一些变量,这样方便我们理解iterator方法的源码

modCount:该变量定义在AbstractList当中,默认初始化为0,被protected修饰能被子类访问同时不能被序列化,用于,ArrayList继承了AbstractList,便继承了其中的成员变量modCount,也就是修改次数。

protected transient int modCount = 0;

 

ArrayList中iterator方法返回的迭代器实例是ArrayList的内部私有类Itr实例化返回的

Itr私有类中使用cursor、lastRet来标识迭代元素,cursor总是指向当前迭代将操作元素的下一个元素的位置,而lastRet指向cursor的上一个位置,next和remove操作的均是lastRet位置上的元素,使用expectedModCount来进行并发控制,确保同一时间只有一个迭代器对集合进行操作,但是我们不能完全依赖迭代器的快速失败机制来做线程安全控制。

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

   private class Itr implements Iterator<E> {
        //游标,指向当前迭代到的元素,作为成员变量初始化为0
        int cursor;
        //当前迭代到的元素的上一个元素
        int lastRet;
        //期望的修改次数,作为成员变量初始化为0
        int expectedModCount;

        private Itr() {
            this.lastRet = -1;
            //将期望修改次数初始化为当前ArrayList的修改次数
            this.expectedModCount = ArrayList.this.modCount;
        }

        //判断当前迭代器是否还有下一个元素
        public boolean hasNext() {
            //通过当前游标与当前ArrayList的大小来判断是否还有下一个元素
            return this.cursor != ArrayList.this.size;
        }

        //返回迭代器的下一个元素
        public E next() {
            //快速失败检查
            this.checkForComodification();

            //赋值var1为当前游标
            int var1 = this.cursor;

            //若当前游标大于等于当前ArrayList的大小
            if (var1 >= ArrayList.this.size) {
                //抛出无此元素错误
                throw new NoSuchElementException();
            } else {
                //否则获取到当前ArrayList的内置数组
                Object[] var2 = ArrayList.this.elementData;

                //再一次判断了游标是否大于等于ArrayList数组长度
                if (var1 >= var2.length) {
                    throw new ConcurrentModificationException();
                } else {
                    //将游标+1
                    this.cursor = var1 + 1;

                    //lastRet赋值为游标的前一个元素的下标,且返回游标的前一个元素
                    return var2[this.lastRet = var1];
                }
            }
        }

        //删除当前迭代到的元素
        public void remove() {
            //如果lastRet小于0,有两种情况,1:Itr中被初始化为-1;2:Itr中remove后没有next
            if (this.lastRet < 0) {
                throw new IllegalStateException();
            } else {
                //快速失败检查
                this.checkForComodification();

                try {
                    //调用ArrayList中的remove方法来移出lastRet位置上的元素
                    ArrayList.this.remove(this.lastRet);

                    //当lastRet下标的元素被删除,游标移到lastRet位置
                    this.cursor = this.lastRet;

                    //再将lastRet赋值为-1,如果下一次remove之前没有进行next操作,则报错
                    this.lastRet = -1;

                    //期望修改次数等于ArrayList的修改次数,ArrayList中remove方法中会将modCount+1,在Itr中的remove方法中,保证expectedModCount等于modCount,这样快速失败检查不会报错
                    this.expectedModCount = ArrayList.this.modCount;
                } catch (IndexOutOfBoundsException var2) {
                    throw new ConcurrentModificationException();
                }
            }
        }

        //快速失败检查,通过比较modCount和expectedModCount来判断
        final void checkForComodification() {
            if (ArrayList.this.modCount != this.expectedModCount) {
                throw new ConcurrentModificationException();
            }
        }
    }

    //ArrayList中的remove方法
    public E remove(int var1) {
        //有效范围判断
        this.rangeCheck(var1);
        
        //修改次数+1
        ++this.modCount;

        //获取到要删除的元素
        Object var2 = this.elementData(var1);

        int var3 = this.size - var1 - 1;
        if (var3 > 0) {
            //使用System.arraycopy来截取数组,达到删除元素的效果
            System.arraycopy(this.elementData, var1 + 1, this.elementData, var1, var3);
        }

        //释放数组空间
        this.elementData[--this.size] = null;
        return var2;
    }

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值