List的有用實現
1.ArrayList
2.LinkedList
3.Vector
4.Stack
討論1:底層機制(牽扯到的數據結構的知識請讀者自行復習)
ArrayList與Vector都是基於數組實現的,這就說明ArrayList與Vector適合做遍歷而不適合做頻繁的插入和刪除。
LinkedList是基於鏈表實現的,所以它生來就是為了頻繁插入與刪除對象。
討論2:特殊功能
Stack是一個後進先出(LIFO)對象堆棧,而LinkedList除可以被用作堆棧外,還可以被用作隊列或雙端隊列。
不同的是Stack繼承自Vector,也就是說它也是基於數組實現的。
討論3:內存占用
基於數組實現的List,在動態擴展時會產生新的數組,然後把舊數組裡的內容復制到新數組裡,
這會產生大量的不再被使用的對象引用變量等待系統回收。而基於鏈表實現的List就不會有這種問題。
討論4:同步問題
Vector與Stack生來就是同步的,而ArrayList與LinkedList需要使用Collections.synchronizedList(List list)方法來轉換成同步List。
從它們的對象上返回的迭代器是快速失敗的,也就是說在使用迭代器進行迭代的時候,必須使用迭代器本身的remove、add、set
方法來添加或更改List元素,如果在迭代的同時,在其他線程中從結構上修改了List(結構上的修改是指任何添加或刪除一個或多個元素的操作,或者顯式調整底層數組的大小;僅僅設置元素的值不是結構上的修改),快速失敗迭代器會盡最大努力拋出ConcurrentModificationException。
討論5:使用策略
如果數據被從數據源提取,數據量不確定,該數據一經被提取後就幾乎不會再添加或刪除,那麼應該建立一個LinkedList來保存從數據源中取出的數據,然後將該LinkedList轉換成ArrayList來優化遍歷操作。反過來,數據量確定的數據從數據源取出可以先建立一個ArrayList來保存,根據需要如需頻繁增刪,就轉換為LinkedList,如頻繁遍歷就不需轉換。
轉換的方法就是使用對應的List類來封裝目標List對象。如
ArrayList al = new ArrayList();
LinkedList ll = new LinkedList(al);
同理反過來也可以
LinkedList ll = new LinkedList();
ArrayList al = new ArrayList(ll);
討論6:toArray()方法
基於數組實現的List會直接返回一個底層數組的拷貝(使用了System.arraycopy方法),基於鏈表實現的List會新生成一個數組。
討論7:不可修改
通過使用Collections.unmodifiableList(List list)來生成一個不可修改的List,試圖修改返回的列表,不管是直接修改還是通過其迭代器進行修改,都將導致拋出UnsupportedOperationException。
討論8:遍歷器
請盡量使用Iterator,Enumeration已不被鼓勵使用。
最後,請參考java.util.Collections類,該類提供了很多有用的操縱集合對象的方法。