java集合系列05 Iterable Iterator ListIterator

来源:互联网 发布:php 清空文件 编辑:程序博客网 时间:2024/06/05 16:52

费话不多说,还是先上uml图
这里写图片描述
Java集合框架中绝大多数的类都间接或直接的实现并依赖于Iterable

Iterable

文档介绍

实现此接口允许此类的实例成为for-each循环语句的目标

源码

public interface Iterable<T>{    //返回一个迭代器,可遍历整个集合元素    Iterator<T> iterator();}

Iterator

文档介绍

一个遍历整个集合迭代器,Iterator替换了Java集合框架的Enumeration类,迭代器与枚举有两点不同:

  1. 迭代器在迭代集合期间可以删除集合的元素
  2. 方法全名更加精简

源码

public iterface Iterator<E>{    //判断集合是否有下一个元素    boolean hasNext();    //返回集合的下一个元素    E next();    //删除next()返回的元素,    //每调用一次next()方法只能调用一次remove()方法    //如果在迭代集合期间,调用了此方法这外的其他方式修改了该迭代器所指向的collection,则迭代器的行为是不确定的    default void remove(){        throw new UnsupportedOperationException("remove");    }

ListIterator

文档介绍

列表迭代器,允许程序员按任意方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。ListIterator没有当前元素;它的光标位置始终位于调用previous()所返回的元素和调用next()所返回的元素之间。

源码

public iterface ListIterator<E> extends Iterator<E>{    boolean hasNext();    E Next();    boolean hasPrevious();    E previous();    int nextIndex();    int prevouseIndex();    //修改操作    //删除next()或previous()方法最后返回的元素,此方法只能在每次调用next()或previouse()方法之后并且没有调用add方法时使用    void remove();    //修改next()或previous()方法最后返回的元素,此方法只能在    //每次调用next()或previouse()方法,并且没有调用remove()或add()方法时使用    void set(E e);    //将指定的元素插入列表(可选操作)。该元素直接插入到 next 返回的下一个元素的前面(如果有),或者 previous 返回的下一个元素之前(如果有);如果列表没有元素,那么新元素就成为列表中的唯一元素。新元素被插入到隐式光标前:不影响对 next 的后续调用,并且对 previous 的后续调用会返回此新元素(此调用把调用 nextIndex 或 previousIndex 所返回的值增加 1)。    void add(E e);

我研究到这的时候,虽然明白怎么使用,但是对其源码还不了解,所以等到讲解ArrayList的源码时,再详细说明吧。

也许下面这张图可以说清ListIterator()的使用原理
^Element(0) ^ Element(1) ^ Element(2) ^ … ^Element(n-1)^
^代表指针 remove()会删除指针后面的一个元素,add()会在当前指针插入元素,
previous()返回当前指定的前一个元素,next()返回当前指定的后一个元素,previousIndex()返回要返回前一个元素的索引,nextIndex()返回要返回的下一个元素的索引

AbstractList里关于Iterator 和 ListIterator的具体实现

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>{...private class Itr implements Iterator<E>{    //后续调用next方法返回元素的索引    int cursor = 0;    //最近调用next或previous方法返回元素的索引    //如果元素被调用方法remove删除,lastRet被重置为-1    //lastRet  是 lastReturn的简写    int lastRet = -1;    //期待的元素数量,如果此变量的值与数组的元素的数量不一致,则在迭代期间发生了并发的添加或删除    int expectedModCount = modCount;    //检测是否并发的添加或删除    final void checkForComodificaton(){        if(modCount != expectedModCount){            throw new ConcurrentModificationException();        }    }    //如果指针不等于List的元素数量,说明有下一个    public boolean hasNext(){        return cursor != size();    }    //返回当前指针所代表的元素    //此方法采用了checkForComodificaton(), 捕获数组越界异常来检测数组并发删除或添加元素    public E next(){        checkForComodificaton();        try{            int i = cursor;            E next = get(i); //获取元素            lasRet = i; //相当于+1            cursor = i + 1; //相当于+1            return next;    }catch(IndexOutOfBoundsException e){ //如果cursor越界,抛出NoSuchElementException        checkForComodificaton();        throw new NoSuchElementException();    }
    public void remove(){        if(lastRet < 0){            throw new IllegalStateException():        }        checkForComodificaton();        try{            AbstractList.this.remove(lastRet);            if(lastRet < cursor){//判断上次调用是next(lastRet < cursor) 还是 previous(lastRet == cursor)                cursor--; //因为删除list当前指针的前一个元素,所以cursor要 -1以正确的指向下一个元素的位置            }            lastRet = -1; //重置为-1            expectedModCount = modCount;        }catch(IndexOutOfBoundsException e){            throw new ConcurrentModificationException();        }    }
    private class ListItr extends Itr implements ListIterator<E>{        //构造器 支持指定索引        ListItr(int index) {            cursor = index;        }

返回指针的前一个元素
并把lastRet 和 cursor设置为 cursor-1
如果cursor-1小于0捕获IndexOutOfBoundsException 并抛出 NoSuchElementException

        public E previous(){            checkForComodificaton();            try{                int i = cursor - 1;                E previous = get(i);                lastRet = cursor = i;                return previous;            }catch(IndexOutOfBoundsException e){                checkForComodificaton();                throw new NoSuchElementException();            }        }

两个简单的返回下一个元素或上一个元素的方法

        public int nextIndex(){            return cursor;        }        public int previouseIndex(){            return cursor - 1;        }

此set方法以lastRet为中心
设置lastRet指向的元素(可以多次重复设置)

        public void set(E e) {            if (lastRet < 0)                throw new IllegalStateException();            checkForComodification();            try {                AbstractList.this.set(lastRet, e);                expectedModCount = modCount;            } catch (IndexOutOfBoundsException ex) {                throw new ConcurrentModificationException();            }        }

此add方法以cursor为中心的方法
调用完add方法重置lastRet,所以不能调用remove, set方法了

        //添加操作        //在当前指针处添加元素,当前指针向后移一位,lastRet重置为-1,重新设置expectedModCount        public void add(E e) {            checkForComodification();            try {                int i = cursor;                AbstractList.this.add(i, e); //调用List自身的add方法添加元素                lastRet = -1; //重置lastRet                cursor = i + 1; //指针加1                expectedModCount = modCount; //重新设置expectedModCount            } catch (IndexOutOfBoundsException ex) {                throw new ConcurrentModificationException();            }        }    }}

这里写图片描述

0 0
原创粉丝点击