ArrayList 內部是由一個array 實現的。
如果你知道array 和 ArrayList 的相似點和不同點,就可以選擇什么時候用array 或者使用ArrayList , array 提供 O(1)的查找性能和很基本的方式去存儲數據。
ArrayList 是Java集合框架類的一員,可以稱它為一個動態數組。array 是靜態的,所以一個數據一旦創建就無法更改他的大小。
所以, 如果需要一個數組可以重新定義他的大小,你應該使用 ArrayList, 這是array 和ArrayList的基本的不同。
不同點:
通過一些點來比較兩個不同的事情是最好的方式,這樣會使大家容易理解他們的不同點。所以讓我們來看看有哪些點能夠讓我們比較array 和ArrayList。
1) Implementation(實現)
array 是本地的程序設計組件或者數據結構,但是ArrayList是一個來自Java集合類的類,一個接口 (Application programming interface)。
實際上,ArrayList 在Java上,它的內部是由一個array實現的。既然ArrayList是一個類,所以它持有了所有類的屬性。
例如:你可以創建對象,可以調用方法,但array並不提供任何方法,它僅僅暴露了一個常量的長度來表示當前數組的長度。
2) Performance(性能)
ArrayList是基於array,它提供和array一定程度上一樣的性能。但是在一些額外功能性的ArrayList上性能還是和array 存在一定差別,主要是內存的使用和CPU 耗時。
在索引上,ArrayList和array都能提供O(1)的時間復雜度,但是在添加item的時候如果出發resize,ArrayList可能會是O(logN)的時間復雜度,因為它包含了創建一個新的array 和將老的array的數據拷貝到新的array里。
在存儲相同數量的對象時,ArrayList所需要的內存也是比array大的。例如:一個int[] 的數組會比ArrayList節省20個int 變量的大小,因為對象的基本數據會在ArrayList和包裝類上進行開銷。
3) Type Safety(類型安全)
ArrayList 是類型安全的,因為它支持泛型(Generics) 允許編譯器檢查 ArrayList 里所包含的對象是否是正確的類型。
然而,array 並不支持泛型。這代表在編譯時期檢查array 所保存對象的類型是不可能的,但是array 通過拋出 ArrayStoreException 異常的方式來進行運行時的類型檢查如果你存儲了一個錯誤類型的對象。
例如:存儲一個String 到 int array 里。
4) Flexibility(靈活性)
靈活性是區分array 和 ArrayList最重要的一個東西,ArrayList比簡單的array要靈活的多,因為ArrayList 是動態的,可以在需要的時候擴大自己的內存, array 不可能做的到。
ArrayList 也允許你刪除元素,這在array上也是不可能的。通過刪除,我的意思並不是將null置於對應的index里,而是將所刪除元素的后面所有元素的index都往前移動一位,這些都是ArrayList自動為我們做的。
5) Primitives(基本類型)
如果你第一次開始使用Arraylis,你會發現,你不能保存基本類型到ArrayList里。這是array和ArrayList一個關鍵的不同,因為array既可以保存對象也可以保存基本類型。
例如:int[]數組是合法的,但是一個int型的ArrayList是不合法的。
如何解決這個問題呢? 假設你想存儲int類型到ArrayList里,你會怎么做呢? 是的,你可以用封裝類,這就是封裝類被引進java的原因之一。
所以,從java5開始,這個區別越來越不明顯了,因為通過自動封裝你會發現“ArrayList.add(21)”是非常合法並且運行正常。
6) Generics(泛型)
ArrayList和array之間的另外一個重要的區別就是前者能夠顯示的支持泛型,后者不行。
由於數組是協變性的,所以你可以在array上使用泛型(Since an array is of covariant type, you can use Generics with them)。這個表示編譯器不可能檢查array的類型安全,但是可以校驗類型安全。
當你要寫一個類型安全的類的時候如何解決這個問題呢?好吧,你可以用《Effective Java》里展示的技術,通過申明一個類似於E[]的數組,然后后期進行類型轉換。
7) Iteration(迭代)
ArrayList 提供比array更多的方式來迭代,即可以允許一個接一個的訪問所有的元素。
可以通過for、while等循環來遍歷array,但是你可以通過Iterator 和ListIterator類來遍歷ArrayList。
8) Supported Operations(支持的操作)
由於ArrayList的內部是由一個array支撐着,所以它暴露了能夠在array可能支持的操作,並且還提供了它動態的屬性。
它也支持添加操作,這是在array上不可能的。你可以同時在array和ArrayList上存儲元素,但是僅ArrayList允許你刪除元素。
然而你可以通過模擬將null賦值到對應的index里來模擬刪除,這個模擬不會像是刪除,除非你同時將所刪除元素對應的索引(index)移動到下一級。
ArrayList和array都提供獲取元素的方法。例如:ArrayList用索引通過get()方法來獲取一個元素,version[0]將會返回array的第一個元素。
ArrayList也提供一個方法來清空和重用,例如:clear() 和 removeAll()。array並不提供這個方法,但是你可以通過循環這個數組來將null賦值到所有的元素里來模擬ArrayList的removeAll()。
9) Size() vs length(大小 vs 長度)
array 僅僅提供一個length 屬性來告訴你array里有多少個插槽,即可以存儲多少個元素,但它沒有提供任何方法來告訴你哪些插槽是滿的,哪些是空的,即當前元素的個數。
但是ArrayList提供一個size()方法來告訴你當前時間點ArrayList存儲了多少個元素。size() 總是和length不同的,它也是ArrayList的容量。
10) Dimension(維度)
ArrayList和array的另外一個重要的區別就是array可以使多維度的。如你可以設置一個二維數組或者三維數組,可以使你創在一個特殊的數據結構來代表矩陣或者2D形式(terrains)。
另一方面,ArrayList並不支持允許你指定維度。
相似點:
1) Data Structure(數據結構 )
兩者都允許存數對象,並且所有的都是基於index的數據結構,提供O(1)的復雜度來獲取一個元素,但是如果通過二分查找來查詢某個元素依舊需要log(N)的復雜度。
2) Order(順序)
array 和ArrayList在添加元素時都維持着元素的順序。(Both array and ArrayList maintains order on which elements are added into them. )
3) Search(查找 )
可以通過index來查找一個元素,這個是O(1)的時間復雜度;
除此之外如果你的array不是排好序的數組你可以用線性的查找,這個將消耗大約O(n)的時間復雜度
或者你可以將數組排序后使用二分查找,這個將消耗排序的時間復雜度加上O(logN) 。
4) Null values(空值 )
array 和 ArrayList都允許存儲null值,只有object的array可以這樣,基本類型的數組會存儲他們的默認值,例如int型的數組默認存儲0,boolean的數組默認存儲false。
5) Duplicates(重復 )
array和Arraylis都允許存儲重復的值。
6) Performance(性能 )
ArrayList模仿(模擬)array的性能,例如:O(1)復雜度的訪問元素,如果你知道這個元素的index,但是ArrayList會消耗更多的內存,因為它是存儲的對象,並且持有了額外的數據來自動更改ArrayList的長度。
7) Zero-based Index(從零開始索引)
array和ArrayList都從零開始的索引,即第一個元素從零的開始索引。
這些就是關於array和ArrayList的所有不同點啦。
其中你需要記住的最重要的不同點就是array是靜態的,你無法一旦創建了一個數組就無法更改它的大小;但是ArrayList因為是動態的,所以它可以做到。
根據這個不同點,如果你事先知道數組的長度,並且確定它的大小不會改變,你應該使用array,否則請使用ArrayList吧。