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