集合迭代器iterator

很久之前在我使用ArrayList进行for循环删除元素的时候,发现总会抛出数组下标越界的错误,那时候我似乎还不知道iterator进行迭代删除,好像是使用for循环处理的。在工作当中几乎很少用到集合的循环删除,现在重新学习一下迭代器iterator。

Iterator接口

迭代器接口中有三个抽象方法。

hasNext:判断容器内是否还有可供访问的元素;

next:返回迭代器刚越过的元素的引用;

remove:删除迭代器刚越过的元素。

package java.util;

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

    E next();

    void remove();
}

 Iterable接口

Iterable接口中定义了一个获取迭代器类的方法

package java.lang;

import java.util.Iterator;

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

Collection接口

Collection集合接口继承了Iterable接口的iterator方法,同时定义了集合抽象方法

package java.util;

public interface Collection<E> extends Iterable<E> {
    int size();

    boolean isEmpty();

    boolean contains(Object var1);

    Iterator<E> iterator();

    Object[] toArray();

    <T> T[] toArray(T[] var1);

    boolean add(E var1);

    boolean remove(Object var1);

    boolean containsAll(Collection<?> var1);

    boolean addAll(Collection<? extends E> var1);

    boolean removeAll(Collection<?> var1);

    boolean retainAll(Collection<?> var1);

    void clear();

    boolean equals(Object var1);

    int hashCode();
}

List接口

List接口继承了Collection的抽象方法(包含iterator方法),也定义了List的一些抽象方法

package java.util;

public interface List<E> extends Collection<E> {
    int size();

    boolean isEmpty();

    boolean contains(Object var1);

    Iterator<E> iterator();

    Object[] toArray();

    <T> T[] toArray(T[] var1);

    boolean add(E var1);

    boolean remove(Object var1);

    boolean containsAll(Collection<?> var1);

    boolean addAll(Collection<? extends E> var1);

    boolean addAll(int var1, Collection<? extends E> var2);

    boolean removeAll(Collection<?> var1);

    boolean retainAll(Collection<?> var1);

    void clear();

    boolean equals(Object var1);

    int hashCode();

    E get(int var1);

    E set(int var1, E var2);

    void add(int var1, E var2);

    E remove(int var1);

    int indexOf(Object var1);

    int lastIndexOf(Object var1);

    ListIterator<E> listIterator();

    ListIterator<E> listIterator(int var1);

    List<E> subList(int var1, int var2);
}

ArrayList中的iterator

ArrayList实现了List接口,所以要实现其中的iterator方法。ArrayList中定义了一个私有类Itr来实现Iterator接口,Itr类中有cursor、lastRet和expectedModCount成员变量。cursor代表下一元素索引位置,lastRet代表上一元素索引位置,cursor总是比lastRet多1,Itr依据cursor和lastRet来对ArrayList进行迭代。

    public Iterator<E> iterator() {
        //返回私有类实例
        return new ArrayList.Itr();
    }

    //定义私有类Itr实现Iterator接口
    private class Itr implements Iterator<E> {
        //游标,指向下一元素下标,初始化默认值为0
        int cursor;
        //指向上一元素索引位置
        int lastRet;
        
        int expectedModCount;

        //构造方法,给lastRet赋默认值为-1
        private Itr() {
            this.lastRet = -1;
            this.expectedModCount = ArrayList.this.modCount;
        }

        //是否有下一元素
        public boolean hasNext() {
            //如果游标不等于当前ArrayList容量大小,则还有可供访问的元素
            return this.cursor != ArrayList.this.size;
        }

        //获取容器内下一元素
        public E next() {
            //快速失败检查
            this.checkForComodification();
            //用var1暂存cursor
            int var1 = this.cursor;
            //如果当前游标位置是大于或等于ArrayList的容量大小
            if (var1 >= ArrayList.this.size) {
                //抛错,没有这样的元素
                throw new NoSuchElementException();
            } else {
                //用var2暂存ArrayList的Object数组
                Object[] var2 = ArrayList.this.elementData;
                //这里是一个快速失败机制,因为在并发环境下数组的大小可能会被改变
                if (var1 >= var2.length) {
                    throw new ConcurrentModificationException();
                } else {
                    //将游标+1
                    this.cursor = var1 + 1;
                    //将lastRet赋值本方法内迭代过的游标索引var1,并且返回该位置上的元素
                    return var2[this.lastRet = var1];
                }
            }
        }
        
        //移除元素方法
        public void remove() {
            //因为lastRet初始化值为-1,如果没有调用过next方法,这里的lastRet就还是-1
            if (this.lastRet < 0) {
                throw new IllegalStateException();
            } else {
                //快速失败检查
                this.checkForComodification();

                try {
                    //调用ArrayList的remove方法来移除迭代过(调用了next方法)的当前元素
                    ArrayList.this.remove(this.lastRet);
                    //将cursor赋值为lastRet,因为lastRet是上一次迭代的元素位置
                    this.cursor = this.lastRet;
                    //再将lastRet赋值为-1,这里赋值的主要目的是限制只能移除当前迭代过的元素
                    this.lastRet = -1;
                    this.expectedModCount = ArrayList.this.modCount;
                } catch (IndexOutOfBoundsException var2) {
                    throw new ConcurrentModificationException();
                }
            }
        }

        //快速检查失败机制
        final void checkForComodification() {
            if (ArrayList.this.modCount != this.expectedModCount) {
                throw new ConcurrentModificationException();
            }
        }
    }

ListIterator接口

ArrayList的扩展迭代器接口继承了Iterator,新增了多个抽象方法,便于迭代操作ArrayList中的元素。

package java.util;

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

    E next();

    boolean hasPrevious();

    E previous();

    int nextIndex();

    int previousIndex();

    void remove();

    void set(E var1);

    void add(E var1);
}

ListItr私有类

ArrayList提供了listIterator方法来获取List扩展的迭代器实例,ListItr继承了ArrayList中的Itr私有类并且继承了ListIterator接口。这里的方法如果使用不当很容易报错,比如迭代器中add方法是从当前游标位置添加元素,游标后面的原来的元素都往后排,而set方法是替换某一位置上的元素,set方法里有lastRet值判断。

    public ListIterator<E> listIterator() {
        return new ArrayList.ListItr(0);
    }

    private class ListItr extends ArrayList<E>.Itr implements ListIterator<E> {
        //构造方法,入参为游标值
        ListItr(int var2) {
            //调用父类Itr的构造方法,父类构造方法初始化
            super(null);
            //将游标赋值为var2,此处是0
            this.cursor = var2;
        }

        //判断是否有前置元素,如果当前游标不为0,则这个迭代器肯定是有前置元素的
        public boolean hasPrevious() {
            return this.cursor != 0;
        }

        //获取下一个元素的索引位置,也就是当前游标的索引位置
        public int nextIndex() {
            return this.cursor;
        }

        //获取前一元素的下标索引位置,当前游标位置-1
        public int previousIndex() {
            return this.cursor - 1;
        }

        //获取迭代器前一元素
        public E previous() {
            //快速失败检查
            this.checkForComodification();
            //var1等于游标-1
            int var1 = this.cursor - 1;
            //如果var1小于0,抛错
            if (var1 < 0) {
                throw new NoSuchElementException();
            } else {
                //var2等于ArrayList里的对象数组elementData
                Object[] var2 = ArrayList.this.elementData;
                //快速失败机制
                if (var1 >= var2.length) {
                    throw new ConcurrentModificationException();
                } else {
                    //游标等于var1,这里就是等于上一元素的位置了
                    this.cursor = var1;
                    //然后这里再将lastRet赋值为var1,返回上一元素
                    return var2[this.lastRet = var1];
                }
            }
        }

        //设置元素
        public void set(E var1) {
            //lastRet小于0代表还没有开始循环迭代
            if (this.lastRet < 0) {
                throw new IllegalStateException();
            } else {
                //快速失败机制
                this.checkForComodification();

                try {
                    //在lastRet位置上设置元素
                    ArrayList.this.set(this.lastRet, var1);
                } catch (IndexOutOfBoundsException var3) {
                    throw new ConcurrentModificationException();
                }
            }
        }

        public void add(E var1) {
            //快速失败机制
            this.checkForComodification();

            try {
                //var2赋值为当前cursor
                int var2 = this.cursor;
                //在当前cursor位置上设置var1
                ArrayList.this.add(var2, var1);
                //游标+1
                this.cursor = var2 + 1;
                //这里在添加完元素后将lastRet赋值为-1
                this.lastRet = -1;
                this.expectedModCount = ArrayList.this.modCount;
            } catch (IndexOutOfBoundsException var3) {
                throw new ConcurrentModificationException();
            }
        }
    }

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值