Java集合(3)——ListIterator接口源码 & ListIterator接口与Iterator接口辨析

本文详细介绍了ListIterator接口的功能和实现原理,包括如何实现双向遍历、修改列表和获取当前位置等特性。此外,还对比了ListIterator与Iterator接口的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ListIterator接口

这里写图片描述

官方文档描述:

An iterator for lists that allows the programmer to traverse the list in either direction, modify the list during iteration, and obtain the iterator’s current position in the list. A ListIterator has no current element; its cursor position always lies between the element that would be returned by a call to previous() and the element that would be returned by a call to next(). An iterator for a list of length n has n+1 possible cursor positions, as illustrated by the carets (^) below:
这里写图片描述
翻译: 允许开发人员遍历任意方向的集合的迭代器,可以在迭代过程中修改列表,也可以获取迭代器当前位置。一个ListIterator没有当前的元素,它的cursor位置总是在两个元素之间。这两个元素可以一个被previous()方法返回,一个被next()返回。长度为n的集合有n+1个可能的cursor位置。

ListIterator接口中的成员方法

这里写图片描述


package java.util;

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

    E next();

    boolean hasPrevious();

    E previous();

    int nextIndex();

    int previousIndex();

    // Modification Operations

    void remove();

    void set(E e);

    void add(E e);
}

ListIterator是一个更加强大的Iterator子接口,它只能用于各种List接口的子类访问。因为ListIterator没有实现类,只有List接口中有一个返回值类型为ListIterator的listIterator()方法。而AbstractList作为List的直接子类,实现了listIterator()方法。

在AbstractList中实现Iterator接口使用了一个方法,一个内部类。实现ListIterator接口使用了两个方法,两个内部类。

AbstractList抽象类中实现Iterator接口源码解析

使用了一个Public Iterator<E> iterator()方法和private class Itr implements Iterator<E>

Public Iterator<E> iterator()方法源码
    public Iterator<E> iterator() {
        return new Itr();
    }

可以看出在这个方法中只是创建了Itr类的对象,所以主要的实现过程还要看Itr类。

private class Itr implements Iterator<E>类源码

该类包含3个成员变量,4个需要实现Ietrator接口的方法。(该部分涉及到fail-fast机制,也叫ConcurrentModificationException异常)

    protected transient int modCount = 0;
    private class Itr implements Iterator<E> {

        int cursor = 0;    //游标位置,初始设置为0
        int lastRet = -1;  //当前游标位置的前一个位置,初始设置为-1
        int expectedModCount = modCount;  //游标中的ModCount值,如果与集合中的ModCount值不同就会抛出异常!

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

        public E next() {
            checkForComodification();
            try {
                int i = cursor;
                E next = get(i);
                lastRet = i;
                cursor = i + 1;
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

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

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

AbstractList抽象类中实现ListIterator接口源码解析

实现该方法有两种方式,一种是无参数的,一种是有参数的

    public ListIterator<E> listIterator() {
        return listIterator(0);
    }

    public ListIterator<E> listIterator(final int index) {
        rangeCheckForAdd(index);

        return new ListItr(index);
    }

从上述源码中可以看出,无参数的listIterator()方法调用的是有参数的listIterator(fianl int index)方法,只不过将参数值设置为0。有参数的方法先判断Index值是否符合范围,如果符合范围,就调用内部类ListItr

private class ListItr extends Itr implements ListIterator<E>类源码
    private class ListItr extends Itr implements ListIterator<E> {
        ListItr(int index) {
            cursor = index;
        }

        public boolean hasPrevious() {
            return cursor != 0;
        }

        public E previous() { //注意:向前操作也是两步,第一步是得到游标的前一个元素,第二步是将游标的当前位置赋值给游标的下一个位置
            checkForComodification();
            try {
                int i = cursor - 1;
                E previous = get(i); 
                lastRet = cursor = i;
                return previous;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }

        public int nextIndex() {
            return cursor;
        }

        public int previousIndex() {
            return cursor-1;
        }

        public void set(E e) {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.set(lastRet, e);//这个`set()`方法在抽象类中没有具体实现,方法体只是抛出了异常,具体操作需要子类自己实现

                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        public void add(E e) {
            checkForComodification();

            try {
                int i = cursor;
                AbstractList.this.add(i, e);  //这个`add()`方法在抽象类中没有具体实现,方法体只是抛出了异常,具体操作需要子类自己实现
                lastRet = -1;
                cursor = i + 1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }

可以看出该类继承了刚刚的内部类Itr,然后实现了ListIterator接口,实现了接口中的方法。

Iterator接口和ListIterator接口的主要区别

  • ListIterator有add()方法,可以向List中添加对象,而Iterator不能添加对象
  • Iterator只能向前遍历,但是ListIterator可以双向移动,它还可以产生相对于迭代器在列表中指向的前一个和后一个元素的位置索引。最主要的是ListIterator可以反向迭代List
  • ListIterator可以使用set()方法替换他访问过的最后一个元素。但是Iterator只能遍历集合,不能修改集合。

感谢

http://blog.youkuaiyun.com/u011240877/article/details/52752589
http://blog.youkuaiyun.com/a597926661/article/details/7679765
https://docs.oracle.com/javase/8/docs/api/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值