迭代器Iterator和ListIterator

  • Iterator迭代器

属于设计模式,提供了一个方法,对集合/容器内的元素进行遍历,而不用关注底层实现细节,达到数据与上层遍历解耦的目的.(解耦: 访问逻辑从不同类型的集合类中抽取出来,接触两者间的联合关系。)

  • Iterator迭代器提供的三种方法:(迭代器直接操作集合中的数据)

    boolean hasNext();//判断集合中是否还有数据,有数据返回true;

    E next();//获取当前遍历的元素

    void remove();//删除元素

  • Iterable接口(返回一个迭代器)
public interface Iterable<T> {//接口实现   返回一个迭代器
    /**
     * Returns an iterator over a set of elements of type T.
     * @return an Iterator.
     */
    Iterator<T> iterator();
}
  • 自定义实现Iterator中的三种方法

public class MyArrayList<T> implements Iterable<T>{
    private T[] arr;
    private  int size;
    public MyArrayList(){
        this(10);
    }
    public MyArrayList(int n){
        size = 0;
        arr = (T[])new Object[n];
    }
    public boolean isEmpty () {
        return size == 0;
    }
    public boolean isFull () {
        return size == arr.length;
    }
    public void grow () {
        arr = Arrays.copyOf(arr, arr.length * 2);
    }
    public void add ( T data){
        if (isFull()) {
            grow();
        }
        arr[size++] = data;
    }
    public T get ( int index){
        if (index < 0 || index > arr.length) {
            return null;
        }
        return arr[index];
    }
    public int index(T data){
        for(int i = 0;i < size ;i++){
            if(arr[i] == data)
                return i;
        }
        return -1;
    }
    public void remove ( T data){
        if(isEmpty()){
            return;
        }
        int index = index(data);
        for(int i = index;i < size-1;i++){
            arr[i] = arr[i+1];
        }
        arr[size--] = null;
    }
    public void show () {
        for (T i : arr) {
            System.out.println(i);
        }
    }

    @Override
    public Iterator<T> iterator() {
        return new DIYItr();
    }
    class DIYItr implements Iterator<T>{
        int before;
        int after;
        public DIYItr(){
            before = after = 0;
        }
        @Override
        public boolean hasNext() {
            return after != size;
        }
        @Override
        public T next() {
            int i = after;
            after = i+1;
            before = i;
            T result = arr[before];
            return result;
        }
        @Override
        public void remove() {
            T r = arr[before];
            MyArrayList.this.remove(r);
        }
    }
    public static void main(String[] args){
        MyArrayList<Integer> list = new MyArrayList<>();
        list.add(3);
        list.add(4);
        list.add(6);
        list.add(8);
        list.add(9);
        Iterator<Integer> itr = list.iterator();
        while(itr.hasNext()){
            Integer value = itr.next();
            if(value == 6) {
                itr.remove();
            }
        }
        for(Integer i : list){
            System.out.print(i+"  ");
        }
    }
}

在程序运行中会发现:如果在迭代器进行遍历时,进行改变集合大小结构的操作(增加,删除等操作),会抛出ConcurrentModificationException(并发异常);    

  • 抛出并发性异常的原因是什么呢?

        在迭代之前,迭代器已经被创建出来了,如果此时改变容器的大小结构,IIterator对象无法同步list,Java会认为这样的操作不安 全,就会进行提醒,抛出异常。从Iterator的实现源码可以看出:modCount是当前集合的版本号,每次add,remove,都会+1,expectedModCount是当前集合的版本号,迭代器初始化为modCount,而调用ArrayList.add(),或ArrayList.remove()时,只对modCount进行了操作,迭代器中的expectedModCount并未同步,导致在进行检查时,抛出异常。而使用Iterator.remove()就不会抛出异常:源码发现,该方法会将modCount与expectedModCount同步。

  • 快速失败机制(fail-fast)和安全失败机制(fail-safe)
  • 快速失败机制(fail-fast)

在迭代器进行遍历时,不能删除集合中的元素(改变集合大小结构的操作),否则会抛出ConcurrentModificationException

原理:使用迭代器进行集合遍历时,遍历过程有一个modCount变量,对集合进行remove,add等操作时,对modCount都会进行改变,每当使用hasNext()或next()遍历下一个元素时,都进行版本检查checkForComidification(),当modCount==expectedModCount时,继续遍历,否则,抛出异常,终止遍历。

  • 安全失败机制:(fail-safe)

采用安全失败机制的容器,在遍历时,不是在原集合上直接操作,而是拷贝一份原集合,对拷贝的集合进行操作。

原理:由于操作的对象不是原集合,迭代器不能检测到,所以不会抛出并发异常。

缺点:由于遍历操作的是初始拷贝的集合,所以无法对修改后的集合进行操作/访问。

  • ListIterator提供双向遍历(有hasPrevious(),previous()),方法相对于Iterator迭代器提供了多个方法

  • Iterator和ListIterator的异同?(适用范围和继承结构)

异:适用范围:Iterator可以适用于所有集合类型,而ListIterator只能用于List及其子类型。

      涵盖方法:ListIterator中有add(),可以添加元素,双向遍历,而Iterator不能添加元素,单向遍历。

同:二者都是迭代器,当需要对容器进行遍历且不需要干涉遍历过程,都可以用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值