Java Collections API中的表

Iterator接口

  1. 每次对next的调用都给出集合的(尚未见到的)下一项。因此,第1次调用next给出第1项,第2次调用给出第2项,等等。
  2. 当直接使用Iterator(而不是通过一个增强的for循环间接使用)时,重要的是要记住一个基本法则:如果对正在被迭代的集合进行结构上的改变(即对该集合使用add、remove或clear方法),那么迭代器就不再合法(并且在其后使用该迭代器时将会有ConcurrentModificationException异常被抛出)。
  3. 然而,如果迭代器调用了它自己的remove方法,那么这个迭代器就仍然是合法的。这是有时候我们更愿意使用迭代器的remove方法的第二个原因。

3.3.3 List接口、ArrayList类和LinkedList

  1. LinkedList类则提供了List ADT的双链表实现。
  2. 这里,ArrayList的运行时间是O(N),但对于LinkedList来说,其运行时间则是O(N2),因为在LinkedList中,对get的调用为O(N)操作。可是,要是使用一个增强的for循环,那么它对任意List的运行时间都是O(N),因为迭代器将有效地从一项到下一项推进。

3.3.4 例:remove方法对LinkedList类的使用

删除表中的偶数:由于ConcurrentModificationException异常而无法运行:

publicstaticvoidremoveEvensVer2(List<Integer> lst) {

    for (Integer x :lst)

        if (x % 2 == 0)

           lst.remove(x);

}

该程序产生一个异常,因为当一项被删除时,由增强的for循环所使用的基础迭代器是非法的。 
所以,我们不用Listremove方法,而使用Iteratorremove方法。

publicstaticvoidremoveEvensVer3(List<Integer> lst) {

   Iterator<Integer> itr = lst.iterator();

    while(itr.hasNext())

        if(itr.next() % 2 == 0)

            itr.remove();

}

3.3.5 关于ListIterator接口

  1. ListIterator扩展了List的Iterator的功能。方法previous和hasPrevious使得对表从后向前的遍历得以完成。add方法将一个新的项以当前位置放入表中。当前项的概念通过把迭代器看做是在对next的调用所给出的项和对previous的调用所给出的项之间而抽象出来的。
  2. void set(E e) 
    Replaces the last element returned by next() or previous() with the specified element (optional operation). This call can be made only if neither remove() nor add(E) have been called after the last call to next or previous. 
    修改next()和previous()返回的对象,并且是和remove()以及add(E)互斥的,不能同时使用。

3.4 ArrayList类的实现

publicclassMyArrayList<AnyType> implementsIterable<AnyType> {

    privatestaticfinalintDEFAULT_CAPACITY = 10;

    privateint theSize;

    private AnyType[]theItems;

    ...

    publicjava.util.Iterator<AnyType> iterator() {

        returnnewArrayListIterator();

    }

    privateclassArraListIteratorimplementsjava.util.Iterator<AnyType> {

        privateint current = 0;

        publicboolean hasNext() {

            returncurrent<size();

        }

        public AnyType next(){

            if(!hasNext())

                thrownewjava.util.NoSuchElementException();

            returntheItems[current++];

        }

        publicvoid remove() {

           MyArrayList.this.remove(--current);

        }

    }

}

迭代器用一个内部类实现。嵌套类是在内部类前加一个static修饰符。内部类可以看到外部类的所有成员,包括private成员,而嵌套类,因为是static的,所以只能访问外部类的static成员。嵌套类因为是static的,所以即使没有外部类的instance,它也可以被访问。

3.5 LinkedList类的实现

publicclassMyLinkedList<T> implementsIterable<T> {

    // 节点定义

    privatestaticclassNode<T> {

        public Node( T d,Node<T> p, Node<T> n ){

            data =d; prev = p; next = n;

        }

        public T data;

        public Node<T>prev;

        public Node<T>next;

    }

    // LinkedList的成员。使用头节点和尾节点的优点是排除了许多特殊情形。每次对一个迭代器方法的调用都将用到该链表内的当前modCount检测在迭代器内存储的modCount,并且当这两个计数器不匹配时抛出一个ConcurrentModificationException异常。

    privateint theSize;

    privateint modCount = 0;

    private Node<T>beginMarker;

    private Node<T>endMarker;

    // 初始化

    public MyLinkedList(){

        clear();

    }

    publicvoid clear() {

        beginMarker= new Node<T>(null, null, null);

        endMarker =new Node<T>(null, beginMarker, null);

       beginMarker.next = endMarker;

        theSize = 0;

        modCount++;

    }

    //插入节点

    privatevoidaddBefore(Node<T> p, T x) {

       Node<T> newNode = new Node<T>(x,p.prev, p);

       newNode.prev.next = newNode;

        p.prev =newNode;

        theSize++;

        modCount++;

    }

    //删除节点

    private Tremove(Node<T> p) {

        p.prev.next= p.next;

        p.next.prev= p.prev;

        theSize--;

        modCount++;

        return p.data;

    }

    //链表的get

    private Node<T>getNode(int idx) {

       Node<T> p;

        if( idx<0 || idx >size())

            thrownew IndexOutOfBoundsException();

        if(idx <size()/2) {

            p =beginMarker.next;

            for(int i=0;i<idx;i++)

                p =p.next;

        }

        else {

            p =endMarker;

            for(inti=size();i>idx;i--)

                p =p.prev;

        }

        return p;

    }

    //迭代器

    publicjava.util.Iterator<T> iterator() {

        returnnewLinkedListIterator();        }

    privateclassLinkedListIteratorimplementsjava.util.Iterator<T> {

        private Node<T>current = beginMarker.next;

        privateintexpectedModCount = modCount;

        privateboolean okToRemove = false;

        publicboolean hasNext() {

            return current !=endMarker;

        }

        public Node<T>next() {

            if(modCount!=expectedModCount)

                thrownewjava.util.ConcurrentModificationException();

            if(!hasNext())

                thrownewjava.util.NoSuchElementException();

            TnextItem = current.data;

            current= current.next;

           okToRemove = true;

            return nextItem;

        }

        publicvoid remove() {

            if(modCount!=expectedModCount)

                thrownewjava.util.ConcurrentModificationException();

            if(!okToRemove)

                thrownewIllegalStateException();

           MyLinkedList.this.remove(current.prev);

           okToRemove = false;

           expectedModCount++;

        }

    }

}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值