共同学习Java源代码--数据结构--ArrayList类(八)

来源:互联网 发布:安装至u盘 ubuntu 编辑:程序博客网 时间:2024/06/05 01:07
    public ListIterator<E> listIterator(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException("Index: "+index);
        return new ListItr(index);

    }

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

这两个方法一起看,都是获取ListItr实例的方法,第一个方法参数为下标,第二个方法指定了默认下标0。这个类后面会看。

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

这个方法返回一个Itr实例。这个类在下面看:

    private class Itr implements Iterator<E> {
这个类实现了Iterable接口。

        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;
这三个成员变量第一个是游标。第二个是上个返回的元素下标,默认为-1也就是没有返回。第三个变量是期待的修改次数,默认为外部类的引用,是为了检测并发修改异常的。

        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];
        }
这个方法是获取下一个元素的方法,首先先判断是否出现并发修改异常。然后将cursor赋值给临时变量i。

如果i或者说cursor已经遍历完毕,则抛出无此元素异常。将外部类的底层数组赋引用给一个临时的数组变量elementData。

如果i大于这个临时数组变量的长度,则抛出并发修改异常。

然后cursor赋值为i+1,最后返回临时数组变量的第i个元素,其实就是把游标指向的元素取出来,然后游标自增。

返回值那里lastRet=i这个有些人可能看不习惯,其实这个没什么,只要方括号内的表达式最后是个int就可以,同样类似于if(flag=true)这类的表达式也是合法的。

        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();
            }
        }
这个方法是删除元素的方法。

首先判断lastRet是否小于0,也就是是否返回过元素,如果没返回过说明游标没有移动,此时删除元素就抛出异常。

然后检查并发修改异常。

进入try块中,调用外部类对象的删除方法将lastRet指代的元素删除,然后将游标和lastRet同步,然后将lastRet赋值为-1,也就是代表游标没有再动,不能删除元素。
最后将两个modCount同步。

        @Override
        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer<? super E> consumer) {
            Objects.requireNonNull(consumer);
            final int size = ArrayList.this.size;
            int i = cursor;
            if (i >= size) {
                return;
            }
            final Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) {
                throw new ConcurrentModificationException();
            }
            while (i != size && modCount == expectedModCount) {
                consumer.accept((E) elementData[i++]);
            }
            // update once at end of iteration to reduce heap write traffic
            cursor = i;
            lastRet = i - 1;
            checkForComodification();
        }
这个方法是函数式编程的方法,为每个元素执行同样的操作,暂时先不看这个方法。


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

这个方法是判断并发修改异常的方法。就看两个modCount是否一致。
    }

后面的ListItr以及SubList内部类就不看了,和以前的大同小异。

0 0
原创粉丝点击