Java集合源碼分析之基礎(一):數組與鏈表

數組鏈表是數據結構中最基本的部分,也是其余眾多數據結構的基礎。即使在Java中,這兩種結構使用的也很普遍。這里我們會先對它們進行簡要分析。

數組

在java中,數組定義為一種基本類型,其可以通過下標獲取到對應位置的數據。那么這種結構的數據,在內存中是怎么存放的呢?

數組的結構示意圖

正如上圖所示,數組在內存中是一段連續的存儲單元,每個數據依次放在每個單元中。分析這種結構,我們可以得出以下幾個結論:

  • 創建一個數組,必須聲明其長度,以在內存中尋找合適的一段連續存儲單元。這也意味著數組的大小是固定的,我們無法動態調整其大小。

  • 想要獲取數組中第i個元素,其時間復雜度是 O(1),因為可以根據其地址直接找到它。同理修改也是。

  • 數組對查詢表現一般,要想查找一個元素,需要遍歷,時間復雜度為O(n)

  • 因為地址連續,想要在數組中插入一個元素是復雜的,因為從插入位置起,后邊的所有元素都需要向后移動一位。同理刪除也是,只是移動方向為向前。并且,當數組存滿時,就無法繼續插入了。

  • 因為數組要占據一整塊內存,有可能產生許多的碎片,也可能因為找不到合適的內存塊,而導致存儲失敗。

總結起來就是:數組大小固定,查找迅速,增刪復雜,需要完整的內存塊,容易產生碎片。

鏈表

鏈表是一種離散存儲結構,其在內存中存儲不是連續的,每個數據元素都通過一個指針指向其下一個元素的地址。根據指針域的不同,鏈表又分為單鏈表、雙向鏈表、循環鏈表等,這里我們只分析單鏈表。示意圖如下所示:


鏈表的結構示意圖

分析這種結構,我們可以得出以下幾個結論:

  • 聲明一個鏈表時,不需要知道其長度,也不需要連續的內存塊,所以其大小可以動態調整。

  • 鏈表的每個元素都分為數據域和指針域,前者是實際存儲的數據,后者則指向下一個元素的地址。和數組相比,每個元素需要占用的內存更大了。

  • 要獲取鏈表的第 i 個元素變得復雜,因為其地址存放在它上一個元素的指針域里,所以只能從第一個元素起,進行 i 次操作。同理修改也是。

  • 鏈表對查詢表現也一般,需要遍歷,時間復雜度為O(n)

  • 增加與刪除一個元素更方便了,因為沒有對內存地址的限制,我們只需要在對應節點合理處理下指針域的值,就可以把一個元素插入鏈表或者從鏈表刪除。

  • 鏈表對內存的要求很小,只要能夠存儲下一個數據元素的內存塊都可以使用,因此不會造成碎片化。

總結起來就是:大小可以動態調整,增刪迅速,查找較慢,數據元素所占內存略多,不需要整塊內存塊,不會造成碎片化。

數組與鏈表的選擇

通過以上分析,數組鏈表對我們影響最大的幾點區別在于:

  • 數組按位置查找迅速,鏈表增刪方便
  • 數組是固定大小,鏈表可以隨時擴充與縮減
  • 鏈表每個元素占據內存略多于數組
  • 數組和鏈表在查詢方面表現都比較一般,耗時較長

在數據量很小,內容基本固定時,我們選擇何種數據結構的影響并不大。但當數據量較大時,如果我們需要對數據進行頻繁的插入刪除,我們應該選擇鏈表,如果我們需要頻繁的獲取某個位置的元素,我們應該選擇數組。數組與鏈表并沒有明確的優劣之分,根據不同的使用場景進行不同的選擇,才是這兩種結構使用的最佳方式。

上一篇:Java集合源碼分析之開篇

下一篇:Java集合源碼分析之基礎(二):哈希表


我是飛機醬,如果您喜歡我的文章,可以關注我~

編程之路,道阻且長。唯,路漫漫其修遠兮,吾將上下而求索。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容