1. 程式人生 > >淺談Java中Collection、Iterable、List、ArrayList間的關係

淺談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語言描述》       馬克.艾倫.維斯