collection介面:單列集合,用來儲存乙個乙個的物件
1,list介面:儲存有序的,可重複的資料。 -->「動態」陣列,替換原有的陣列
2,arraylist:作為list介面的主要實現類,執行緒不安全,效率高,底層使用object elementdata儲存
2.1,arraylist的原始碼分析:jdk7
arraylist list =
newarraylist()
;//底層建立了長度是10的object陣列elementdata
list.
add(
123)
;//elementdata[0] = new integer(123);..
.list.
add(11)
;//如果此次的新增導致底層elementdata陣列陣列容量不夠,則擴容。預設情況下,擴容為原來的容量的1.5倍,同時需要將原有的資料複製到新的陣列中。
結論:建議開發中使用帶參的構造器:arraylist list = new arraylist(int capacity)
2.2,jdk8 中arraylist的變化:
arraylist list =
newarraylist()
;//底層object elementdata初始化為{},並沒有建立長度為10的陣列
list.
add(
123)
;//第一次呼叫add()時,底層才建立了長度10的陣列,並將123新增到elementdata中去
//後續的新增和擴容操作與jdk 7無異
結論:jdk7中的arraylist的物件的建立類似於單例的餓漢式,而jdk8中的arraylist的物件的建立類似於單例的懶漢式,延遲了陣列的建立,節省記憶體。
3,linkedlist:對於頻繁的插入,刪除操作,使用此類效率比arraylist高;底層使用雙向鍊錶儲存
3.1,linkedlist的原始碼分析:
linkedlist list =
newlinkedlist()
;內部宣告了node型別的first和last屬性,預設值為null
list.
add(
123)
;//將123封裝到node中,建立了node物件。
其中,node定義為:體現了linkedlist的雙向鍊錶的說法
e item;
node
next;
node
prev;
node
(node
prev, e element, node
next)
4,vector:作為list介面的古老實現類,執行緒安全的,效率低,底層使用object elementdata儲存
4.1,vector的原始碼分析:
jdk7和jdk8中通過vector()構造器建立物件時,底層都建立了長度為10的陣列,在擴容方面,預設擴容為原來的陣列長度的2倍
set介面:儲存無序的,不可重複的資料
1,hashset: 作為set介面的主要實現類,執行緒不安全的,可以儲存null值
2,linkedhashset:作為hashset的子類:遍歷其內部資料時,可以按照新增的順序遍歷。對於頻繁的遍歷操作,linkedhashset效率高於hashset.
3,treeset: 可以按照新增物件的指定屬性
3.1treeset:
1,向treeset中新增的資料,要求是相同類的物件
2,兩種排序方式:自然排序(實現comparable介面)和定製排序(comparator)
3,自然排序中,比較兩個物件是否相同的標準為:compareto()返回0,不再是equals()。
4,定製排序中,比較兩個物件是否相同的標準為:compare()返回0,不再是equals()。
set原始碼分析
set中無序性: 不等於隨機性。儲存的資料在底層資料中並非按照陣列所以的順序新增,而是根據資料的雜湊值決定的
不可重複性: 保證新增元素按照equals()判斷時,不能返回true。即:相同的元素只能新增乙個
新增元素的過程: 以hashset(陣列+鍊錶)為例:
我們向hashset中新增元素a,首先呼叫元素a所在的hashcode()方法,計算元素a的雜湊值,此雜湊值接著通過某種演算法計算出在hashset底層陣列中的存放位置(即為索引位置),判斷陣列此位置上是否已經有元素:
情況1 --> 如果此位置上沒有其他元素,則元素a新增成功。
如果此位置上有其他元素b(或以鍊錶形式存在的多個元素),則比較元素a與元素b的hash值:
情況2 --> 如果hash值不相同,則元素a新增成功。
如果hash值相同,進而需要呼叫元素a所在類的equals()方法:
equals()方法返回true,元素a新增失敗。
情況3 --> equals()方法返回false,則元素a新增成功。
對於新增成功的情況2和情況3而言:元素a與已經存在指定索引位置上資料以鍊錶的方式儲存。
jdk7:元素a放到陣列中,指向原來的元素。
jdk8:原來的元素在陣列中,指向元素a
總結:七上八下
4.1 set介面中沒有額外定義新的方法,使用的都是collection中宣告過的方法。
4.2 要求:
重寫的hashcode()和equals()盡可能保持一致性:相等的物件必須具有相等的雜湊碼
重寫兩個方法的小技巧:物件中用作equals()方法比較的field,都應該用來計算hashcode值
為什麼重寫hashcode方法,有31這個數字?
1,選擇係數的時候要選擇盡量大的係數,因為如果計算出來的hash位址越大,所謂的"衝突"就越少,查詢起來效率也會提高。(減少衝突)
2,並且31只占用5bits,相乘造成資料溢位的概率較小。
3,31可以由i*31 == (i << 5)-1來表示,現在很多虛擬機器裡面都有做相關優化。(提高演算法效率)
4,31是乙個素數,素數作用就是如果我用乙個數字來乘以這個素數,那麼最終出來的結果只能被素數本身和被乘數還有1來整除!(減少衝突)
Collection集合的子類List集合
1.因為list集合是collection的子類,所以他可以呼叫collection集合中的所有方法。2.list集合特有方法的概述 void add int index,e element 在指定索引處新增元素 e remove int index 移除指定索引處的元素,返回的是移除的元素 e g...
Collection中的排序
我們來了解一下collection的框架與介面 set介面下面已經有sortedset介面,其中提供了很多自帶排序的實現類,例如threeset,使用者還能夠自定義比較器來規定自己的排序規則。本篇著重說list介面下的排序,list的排序主要通過服務於collection框架的工具類collecti...
Collection集合框架和List集合筆記
1.什麼是集合?能夠儲存多個同型別的基本資料型別的容器我們叫陣列,那麼可以儲存多個同型別物件的容器我們就稱之為集合!什麼是collection集合框架,通過下面這個圖來說明!collection是乙個根介面,而它旗下又很多個子介面繼承了它,其中兩個最重要的子介面分別的是list和set,它們繼承了c...