浅谈Java中Collection、Iterable、List、ArrayList间的关系

        Java是一个高级语言,它提供了很多现成的数据结构,给我们的编程带来了极大的遍历。这都是由Java编程的高手给出的,学习这里面的实现方式无论是对于我们使用这些工具还是对于掌握Java的编程之道都是很有帮助的。本文主要讲述Java中的表的实现方式。

        首先来介绍Collection接口:Collection位于Java的java.util包中。顾名思义,Collection就是用来实现集合的接口;集合的种类有很多,Collection接口抽象出来了集合都具有的特性。例如添加、删除、得到集合中的元素个数、检测某一元素是否存在在该集合... ...

public interface Collection<AnyType> extends Iterable<AnyType> {
	int size( );
	boolean isEmpty( );
	void clear( );
	boolean contains( AnyType x );
	boolean add( AnyType x );
	boolean remove( AnyType x );
	java.util.Iterator<AnyType> iterator( );
}
        这里的方法都不难理解,方法名都很直白,但是Collection继承的Iterable接口以及要实现的Iterator方法并没有那么简单。Iterable的意思是可迭代的,说白了就是用来存储数据的集合都是要能够实现遍历的,因为遍历一个集合是一个集合所必备的。这个接口要求所有继承了该接口的类都要能够得到一个迭代器也就是iterator方法,它返回一个Iterator接口类型的数据,而Iterator接口要求实现三个方法:

public interface Iterator<AnyType> {
	boolean hasNext( );
	AnyType next( );
	void remove( );
}
         看到这里也许有些人会感到疑惑,这只是一个迭代器,只要关心遍历的问题就好了,为什么还要多此一举加一个删除的方法呢?光从迭代器要实现遍历集合这个功能来讲remove()方法确实没有存在的必要,但是如果我们仔细想一想我们究竟要用什么样的方式来遍历集合的话就可以理解remove()方法存在的必要性了。Iterator中的remove()方法是用来删除上一次next()方法返回的元素的。这一机制的好处是这样的删除不需要额外的定位工作,如果我们想通过循环的方式找到一些特定的元素并删除他们,那么用迭代器中的remove()方法是最明智的选择。另一方面,如果在用迭代器遍历集合的过程中删除了之前遍历的元素使得集合总体元素个数变少,这样就有可能导致hasNext()方法失败。如果这样的情况发生了,那么Iterator就不是一个完备的接口,因此remove()方法是必不可少的。

        有了前面的论述,我们知道了Iterator的实现原理和运行机制,但是具体是如何实现的呢?真正的Java代码中是如何实现删除上一次遍历到的元素又不影响遍历的正常运行的呢?

        先来看一下ArrayList的实现方式:ArrayList是以数组为基础的类,继承了List接口,而List接口又继承了Collection接口。List接口在Collection的基础上又增加了一些属于表这种数据结构专有的一些操作,比如get()和set()方法,可以通过给定下标得到或修改该位置的元素,但这些实现原理较为简单,我们不做过多的论述,重点放在迭代器的remove()方法上。

public class MyArrayList<AnyType> implements Iterable<AnyType> {
    private int theSize;
    private AnyType [ ] theItems;

    public MyArryList( ) {...}
    ... ...
    public int size( ) {...}
    public boolean isEmpty( ) {...}
    public AnyType get( int index ) {...};
    public AnyType set( int index, AnyType newData) {...};
    public boolean add( AnyType x ) {...};
    public void add( int index, AnyType x ) {...};
    public AnyType remove( int index ) {
        AnyType removeItem = theItem[ index ];
        for( int i = index; i < this.size( ); i++ ) {
            theItem[ i ] = theItems[ i + 1 ];  
        }
        this.theSize--;
        return removeItem;
    }

    private java,util.Iterator<AnyType> iterator( ) {
        return new ArrayListIterator( );
    }

    private class ArrayListIterator implements java.util.Iterator<AnyType> {
        private int count = 0;

        public boolean hasNext( ) {
            return count < size( );
        }

        public AnyType next( ) {
            if( !hasNext( )) {
                throw new java.util.NoSuchElementExcption( );
            }
            return theItems[ current++ ];
        }

        public void remove( ) {
            MyArrayList.this.remove( --current );
        }
    }
}
        这里对于iterator()方法是用一个内部类实现的,这样做的好处在于可以使用之前程序写好的remove()代码,使得代码得以复用。

        总结:Collection是所有集合类都要继承的一个借口,它保证了集合一定存在增加和减少元素的方法,而且它还继承了Iterable接口,这使得所有集合类都拥有一个迭代器,都可以用迭代器来进行结合中的元素的遍历;Iterator接口提供了一套较为完整的遍历集合的机制,使得对集合的遍历更加方便与快捷;List是表的意思,通过字面意思我们就不难理解,表当然是一种集合,是“集合”这个概念的真子集,那么它当然应该继承Collection接口,也自然应该拥有一个迭代器。而ArrayList则是用数组方式实现的表,它自然应该继承List接口,它是一个真真正正的实体,是真正用来表示“表”这一数据结构的,而它的实现,在Collection、Iterator、List给出后,我们就只需要写每一个方法里面的代码就好,其他的架构不需要过多的思考,而它也自然而然的属于List,属于Collection。


参考文献:《数据结构与算法----Java语言描述》       马克.艾伦.维斯






猜你喜欢

转载自blog.csdn.net/judy_c/article/details/78230222