談談ArrayList、Vector和LinkedList 的存儲性能及特性
? 又有一位工作2年的小伙伴面試的時候,被問到一個集合相關的問題。說請你談談ArrayList、Vector和LinkedList 的存儲性能及特性。
今天呢,我給大家分享一下我對這個問題的理解。
?1、存儲性能及特性
關于ArrayList、Vector和LinkedList 的存性能理及特性,我從以下3個方面來分析:
(1)首先,ArrayList 和 Vector 的底層都是采用數組的來存儲數據,而且都是根據索引來取數據,這樣設計使得獲取數據快而插入數據慢。另外,每次擴容都要移動數組中的元素,存儲數據量較大的時候會影響讀寫性能。
(2)其次,由于Vector 中的方法都使用了 synchronized 修飾,因此 ,Vector 中對數據操作都是線程安全的,但性能上比ArrayList 差。
(3)然后,LinkedList 的底層是采用雙向鏈表來存儲數據的,也就是說將內存中零散的內存單元通過附加的引用關聯起來,形成一個可以按序號索引的線性結構,這種鏈式存儲方式與數組的連續存儲方式相比,內存的利用率更高。LinkedList獲取數據需要根據索引序號,向前或者向后遍歷,但是插入數據時只需要記錄本項的前后項即可,所以,LinkedList插入數據的速度更快。
(4)最后,再補充一點,Vector是Java 早期的版本中提供的容器, 屬于遺留容器,官方已經不再推薦使用。但是由于 ArrayList 和 LinkedListed 都是非線程安全的,在多線程環境下,可以使用工具類Collections 的 synchronizedList() 方法,將容器轉換成線程安全的容器再使用。這其實也是裝飾器模式的一種應用。
2、關于遺留容器
關于Java中的遺留容器,我最后再補充一下。除Vector之外,還有Hashtable、Dictionary、BitSet、Stack、Properties都是遺留容器,這些容器中,Properties 類存在比較嚴重的設計缺陷。來看這段源碼:
/* Since : JDK1.0 See Also : native2ascii tool for Solaris, native2ascii tool for Windows Author : Arthur van Hoff, Michael McCloskey, Xueming Shen */ public class Properties extends Hashtable<Object,Object> { }
Properties是一個鍵和值都是字符串的特殊的鍵值對映射,在設計上應該是關聯一個Hashtable,并將它的兩個泛型參數設置為 String 類型,但是 Java API 中的Properties是直接繼承了 Hashtable,這很明顯是對繼承的濫用。主要體現在以下兩個方面:
(1)首先,根據合成復用原則,這里Properties 和Hashtable的代碼復用關系應該是 Has-A 關系,而不是 Is-A 關系。
(2)另一方面,這兩個容器都屬于工具類,繼承工具類本身就是一個錯誤的做法,使用工具類最好的方式是 Has-A 關系(關聯)或Use-A 關系(依賴)。
既然都講到這里了,最后再擴展一下Stack 類在設計上也存在Properties同樣的缺陷。來看這樣一段源碼:
/* Since : JDK1.0 Author : Jonathan Payne */ public class Stack<E> extends Vector<E> { }
在JDK的util包中,我們發現Stack類也是繼承了 Vector,這個設計也是不太合理的。
好了,以上就是我對ArrayList、Vector和LinkedList的理解。