1. 程式人生 > >Java中陣列和集合容器的剖析

Java中陣列和集合容器的剖析

java中常用的儲存容器就是陣列的集合,每種容器儲存的形式和結構又有所不同。

陣列,是最基礎的容器,在建立陣列的時候有三種方式分別如下:

int[] arr = new int[5];

int[] arr = new String[]{1,2,3,4,5};

int[] arr = {1,2,3,4,5};

從上面的三種方式可以看出,在定義陣列的時候有個共同的特點就是能夠直接看出陣列的長度,這也是陣列的一大特點,就是定義的時候指定長度,同時陣列一旦定義完成後長度就不可以變化,這也是陣列在後期開發中較集合使用較少的原因,因為在實際開發中容器儲存資料的長度存在較大的不確定性。在定義陣列的方式中還可以看出定義陣列的時候需要指定陣列的型別,也就是陣列內能夠儲存的資料型別,這樣陣列定義後,能夠儲存的資料型別就不能再變化,存在一定的侷限性。

陣列的記憶體儲存:

 

接下來看看集合,集合是在開發較為常用的容器,先來看看集合的分類。

 

集合分類兩個大類,分別是Collection集合和Map集合,Collection是使用單值的儲存,而Map集合是使用鍵值對的形式儲存,下面看看集合具體實現類的儲存結構和特點。

Collection集合的共同特點:

         1、儲存的元素可以是不同的型別

         2、集合的長度是變化的,不固定

         3、都可以使用迭代器Iterator對集合中的元素進行遍歷

ArrayList集合:在底層使用的陣列結構進行儲存,陣列中儲存的元素可以為null,且可以存多個重複的元素,儲存的時候是按儲存的先後順序進行排序,每一元素都對應一個腳標值,在操作其中元素的時候可以通過腳標完成,在查詢的時候,指定腳標,直接拿到指定的元素,無需遍歷集合,因此在查詢的時候效率高,增刪效率低,因為在增刪的過程中涉及集合元素的遍歷。

LinkedList集合:在底層使用的是連結串列結構,有頭有尾,也存在腳標,可以通過腳標操作,查詢的效率較低,從原始碼分析上可知,首先判斷腳標在中間位置的左側還是右側,然後對集合的一側進行遍歷,查詢元素,在增刪時直接操作指定的節點,無需遍歷,效率提高。

ArrayList和LinkedList的比較示圖:

ArrayList增加元素:

 

LinkedList新增元素:

 

Set集合:儲存資料和List集合存在差距,List集合中可以儲存重複的元素,而Set集合中不能儲存重複的資料,List集合中儲存的資料是有序的有腳標的,而Set集合中是無序的沒有腳標的,不能通過腳標來操作集合中的元素

HashSet集合:在底層儲存是使用的雜湊表結構,儲存的資料可以是null,由於唯一,因此只能儲存一個,HashSet集合是如何保證元素唯一的呢?

HashSet底層使用了陣列和雜湊演算法,在儲存資料的時候會經過多次比較才能實現

具體實現:

         1、先對儲存的元素進行雜湊演算法得到一個雜湊值

         2、會使用這個計算得到的雜湊值到儲存資料的結構中找對應的位置,當該位置沒有元素就直接新增進去

         3、如果該位置已存在元素,會使用equals方法進行比較兩個元素

         4、如果再相等新新增的元素就不會被新增到集合,如果不相等就會重新計算新增元素的雜湊值,然後進行新增

TreeSet集合:在底層使用了二叉樹的儲存結構,在保證儲存資料不重複的機制上和HashSet是完全不同的

具體實現:

方式一:採用預設的比較器Comparable,這個時候需要儲存的物件對應的類實現Comparable介面,並重新compareTo方法,在該方法中書寫具體保證元素唯一的實現程式碼,若不實現和重寫在儲存元素的時候會出現異常

方式二:採用自定的比較器Comparator,此時具體的儲存物件無需實現Comparator介面,可以另外自定義一個類,該類實現Comparator介面,並重寫compare方法,在建立TreeSet集合的時候,將自定義類的物件作為引數傳遞給TreeSet集合的構造方法。但是該方式會多需要寫一個類,較為麻煩,實現方式不友好,這個時候就可以考慮使用匿名內部類了。

兩種實現方式會不會衝突呢,這個可能對初學者存在疑問,java既然這樣設計,當然不會存在衝突的,看過原始碼的都會對這個比較機制的設計巧妙讚不絕口。

在建立TreeSet集合的時候,可以使用無參的構造方法也可以使用有參的構造方法(引數是比較器),在TreeSet中設定了一個用於儲存比較器的變數(comparator),在儲存元素的時候會呼叫一個比較的方法,該方法中對comparator進行判斷,若comparator不為空,表示使用構造方法傳入了比較器,就使用傳入的比較器進行元素的唯一性比較,反之,就使用預設的比較器進行元素的唯一性比較。

Map集合:Map集合儲存元素使用鍵值對的形式,鍵是唯一的,而值可以不唯一,鍵和值都可以為null,一個鍵只能對應一個值,但是一個值可以對應多個鍵,鍵值對在Map集合中是作為物件處理的,將一個鍵值對看做一個物件,Map集合中儲存的是多個鍵值對物件。Map集合在遍歷元素的時候沒有類似於Collection集合的迭代器,而是使用keySet方法或者entrySet方法先轉為Set集合,然後使用迭代器進行遍歷。

HashMap集合:HashMap採用的也是雜湊表機構,在保證鍵唯一性的操作上和HashSet相同。

TreeMap集合:TreeMap採用的是二叉樹結構,在保證鍵的唯一性的操作上和TreeSet相同。

補充:

         1、陣列儲存的元素可以是物件,也可以是基本資料型別,而集合只能儲存物件

         2、Collection集合都可以使用Iterator迭代器進行迭代,List集合也有它特有的迭代器ListIterator,該迭代器值適用於List集合,Collection下的其他集合不能使用

         3、在開發的過程中使用ArrayList、HashSet、HashMap集合的較為普遍,其他的集合使用較少

         4、LinkedList的API中有addFirst、removeFirst、addLast、removeLast四個特有的方法,因此可以使用該集合模擬棧和佇列結構