当前位置:   article > 正文

Iterator-迭代器使用和原理_android iterator

android iterator

迭代器简介(Iterator)

迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。

import java.util.Iterator;

为什么要使用迭代器

迭代模式是访问(Collection)集合类的通用方法,只要集合类实现了Iterator接口,就可以用迭代的方式来访问集合类内部的数据,Iterator访问方式把对不同集合类的访问逻辑抽象出来,使得不用暴露集合内部的结构而达到循环遍历集合的效果。Iterator模式总是用同一种逻辑来遍历集合。

Map映射如何使用迭代器?

迭代器只针对集合类型的数据,但map集合提供了keySet()方法和value()方法,可以通过先将键值输出到一个集合,可以是list集合或者set集合,再使用迭代器去获取元素。

迭代器的优点

优点:

  1. 可以不了解集合内部的数据结构,就可以直接遍历;
  2. 不暴露内部的数据,可以直接外部遍历,提高安全性;
  3. 适用性强,基本上的集合都能使用迭代器;

Iterator和ListIterator区别:

  1. ListIterator有add()方法,可以向List中添加对象,而Iterator不能
  2. ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
  3. ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
  4. 都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。

Iterator的API

关于Iterator主要有三个方法:hasNext()、next()、remove()

  • hasNext: 没有指针下移操作,只是判断是否存在下一个元素
  • next:游标指针下移,返回 lastRet 所指向的元素
  • remove:删除lastRet 指针所指向的元素,一般和next方法一起用,这时候的作用就是删除next方法返回的元素。并将游标前移,lastRet复位。 cursor = lastRet; lastRet = -1;

Iterator.remove()是唯一安全的方式来在迭代过程中修改集合。

如果在使用迭代器的过程中有其他的线程修改了List就会抛ConcurrentModificationException,这就是Fail-Fast机制。
foreach 本质上就是 Iterator。 实际上Iterator.remove内部也调用了ArrayList.remove 只不过后面又执行了 expectedModCount=modCount 防止移除元素后next取值变成第i+2个元素。

使用iterator.remove()方法前,一定先调用next()

使用迭代器iterator.remove()方法前,一定先调用next()方法来给变量lastRet进行赋值操作。否则lastRet = -1,会抛出 IllegalStateException()异常。

fail-fast策略–从线程安全的角度考虑

所谓fail-fast策略。这一策略在源码中的实现是通过 modCount 域,modCount 顾名思义就是ArrayList修改次数,对ArrayList 内容的修改都将增加这个值,那么在迭代器初始化过程中会将这个值赋给迭代器的 expectedModCount。在迭代过程中,判断 modCount 跟 expectedModCount 是否相等,如果不相等就表示已经有其他线程修改了 list:注意到 modCount 声明为 volatile,保证线程之间修改的可见性。

迭代器源码

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

    /**
     * An optimized version of AbstractList.Itr
     */
    private class Itr implements Iterator<E> {
        int cursor;//当前所指向元素的游标,初始iterator的游标为0
        int lastRet = -1; //上个元素的索引,默认是-1
        int expectedModCount = modCount;//modCount为ArrayList修改次数,

        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        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;
            return (E) elementData[lastRet = i];//给变量lastRet进行赋值操作。
        }

        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        final void checkForComodification(){
            if(expectedModCount != modCount)
             throw new ConcurrentModificationException();
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/179612
推荐阅读
相关标签
  

闽ICP备14008679号