關於jdk一些經常使用類的源碼特性分析

 不喜歡重複造輪子,不喜歡貼各類東西、JDK代碼什麼的,讓整篇文章很亂。。。JDK源碼誰都有,沒什麼好貼的。。。若是你沒看過JDK源碼,建議打開Eclipse邊看源碼邊看這篇文章,看過的能夠把這篇文章當成是知識點備忘錄。。。html

   JDK容器類中有大量的空指針、數組越界、狀態異常等異常處理,這些不是重點,咱們關注的應該是它的一些底層的具體實現,這篇文章就是我看完這部分源碼以後的以爲有用的知識點總結,渣渣一枚,大神勿噴。。。數組


ArrayList
一、 容器默認大小爲10,位置不夠了自動擴增,每次增長當前長度的一半;(擴增時用Arrays.copyOf進行擴增)
二、 數組容量擴增到Integer.MAX_VALUE-8的時候,就會開始限制數組擴充,超過Integer.MAX_VALUE的時候,拋內存溢出異常;
三、 clone是淺拷貝,List中的引用指向的仍是相同數據;
四、 線程不安全的;
五、 迭代器中的expectedModCount和modCount:迭代器初始化時,會用modCount去初始化expectedModCount,在迭代器的操做中都要檢查這兩個值的等值性,不想等拋出ConcurrentModificationException異常表示當前List正在被修改,爲何呢?以下:
List自己的add和remove操做時都會修改modCount的值,若是在迭代器循環迭代過程當中調用了List自己的add和remove方法就會致使兩個值不想等而拋出異常,而迭代器自己的remove則不會有這個問題,它會在remove完成後從新更新一遍expectedModCount保持兩個值的等值性。
六、 ListIterator和普通迭代器相似,只是多了雙向迭代的功能;
七、 ArrayList自己的sort實際上是調用Arrays.sort傳入比較器實現的;緩存


LinkedList
一、 沒ArrayList那麼麻煩了,不須要擴容什麼的,處理好指針引用的指向關係就行。
二、 內部維護size,first,last,支持雙向遍歷,鏈表增刪操做時,注意維護好這三個值;
三、 線程不安全;
四、 鏈表支持鏈表頭增刪,鏈表尾增刪,指定節點前或後增刪;
五、 List中的Node爲private內部類,沒法手動建立,這是爲了保證用戶拿到的全部Node都是LinkedList生成的,即其成員next和pre爲正確指定的值;
六、 LinkedList中的Element元素支持插入空值,和HashMap同樣;
七、 LinkedList的迭代器中也有expectedModCount檢測鏈表的修改狀態,迭代器循環迭代時只能用迭代器的remove方法;
八、 clone爲淺拷貝;
九、 LinkedList能夠當Deque用,由於有實現相應接口;安全


HashMap
一、 HashMap支持null的key和value;
二、 Equals會比較兩個Map地址,若地址不等,則迭代比較每一個元素,都相同才返回true;
三、 Hashcode爲每一個元素Entry的hashcode的和;
四、 Entry是一個鍵值對封裝體,都複寫了Object的不少相應方法,創建了K-V映射關係;
五、 Clone淺拷貝;
六、 HashMap默認大小16,最大大小2的30次方;
七、 結構:一開始使用數據結構書中的以鏈表爲元素的數組存儲元素,元素獲得的哈希值相同的放在數組中哈希值對應位置的鏈表的末尾,操做很簡單,可是有弊端,當同一個哈希值存在的元素過多的話,查詢速度不好,這不是是同哈希表想看到的結果,這時候採起的是轉換成紅黑樹的辦法。
八、 填充比:其中設置一個填充比,當鏈表中的元素數量超過填充比對應的值的時候,鏈表會轉換成紅黑樹,提升查詢效率,填充比在HashMap的構造函數能夠設置,默認0.75。
九、 臨界值:數組中的位置使用率達到臨界值的時候,數組會擴容;
十、 線程不安全;
十一、 Put方法:hashCode()計算Key的哈希值,從而找到數組中的元素位置,
(1)該位置中沒元素,直接放入;
(2)該位置中有元素調用equals,對比Key是否真的相等,若相等,用新的Value替代舊的Value;
(3)若equals不相等(衝突),則把這個元素放到原來的元素後面(鏈表)
注:所以做爲HashMap的Key的數據類型,有必要好好考慮Key的hashCode和equals重寫,儘可能避免衝突,提高效率;
十二、 resize():從新調整數組大小,新舊數組複製,較耗時;
1三、 get()方法:計算key的hashCode,從而找到數組位置,對比數組中元素第一個節點和key是否一致,一致返回該節點,不然判斷節點是不是紅黑樹節點來分類討論(紅黑樹按照紅黑樹的方式查找該key,鏈表則循環下去接着找),若是找到key一致的則返回,不然返回null,表示該key暫時尚未值;
1四、 put()方法步驟:
(1)檢查表是否須要擴容;
(2)檢查hashCode指定位置是否須要newNode;
(3)數組中指定位置已經有節點了,先檢查和第一個節點是否一致,一致則找到節點;
(4)不一致,檢查是否爲紅黑樹,經過紅黑樹查找節點;
(5)不是紅黑樹的,接着鏈表查找,找到元素節點或者找不到新建節點,並檢查是否須要轉換成紅黑樹;
(6)若找到的節點不爲空,賦值Value;
(7)檢查數組是否須要擴容;
(8)返回oldValue;
1五、 Remove()方法:經過hashCode找到數組位置,對比第一個節點,再對比紅黑樹或鏈表,找到節點以後刪除節點並返回;
1六、 HashMap的增刪方法也和List同樣有ConcurrentModificationException異常,使用迭代器需注意;
1七、 數據結構


LinkedHashMap
一、 HashMap的子類;
二、 存儲方式和HashMap都同樣,只是在put元素的時候順帶存儲了元素的存入前後順序,在迭代器遍歷的時候,輸出的結果順序是和插入元素時的插入前後順序一致的;
三、 有ConcurrentModificationException;
四、 能夠設置插入元素時自動刪除最舊的元素;多線程


TreeMap
一、 實現了NavigableMap接口(是SortedMap的子接口);
二、 使用紅黑樹做爲底層實現,排序平衡樹,有序,提供一系列有序集合纔有的方法(獲取第一個,獲取某一範圍內的),排序按照Key爲標準進行比較;
三、 默認爲升序排序,descendingMap()返回降序排序的實例;
四、 維護了比較器comparator、樹根節點root、size屬性;
五、 putAll方法時,先判斷傳入的集合是不是SortedMap,是的話利用比較器直接經過紅黑樹批量插入再調整紅黑樹,較爲高效,若不是,則遍歷整個集合把每一個元素一一插入;
六、 元素間比較:若內部比較器不爲空,則用內部比較器進行key的比較,不然元素自己要實現Comparable接口以提供比較;
七、 不容許key爲空;
八、 Entry就是紅黑樹的節點;
九、 Put:按照排序樹查找key,找到直接修改value,沒找到就插入一個節點,並進行紅黑樹調整;
十、 Remove:按照key查找相應的Entry,再把這個節點從紅黑樹中刪除,並進行紅黑樹調整;
十一、 淺拷貝;
十二、 Replace要求提供的oldValue要和key對應的Entry的value一致才能成功替換;
1三、 非迭代器的增刪方法也有ConcurrentModificationException;函數


HashTable
一、 Dictionary的子類;
二、 淺拷貝;
三、 Keyset,ValueSet,EntrySet三種值的獲取方式使用了標記位的方式,代碼重用,不像以前的,每一個都各寫一個;
四、 Map操做是方法粒度的線程安全的;
五、 不容許key爲空或value爲空;
六、 遍歷迭代器使用Enumeration方式;
七、 HashMap的get方法返回null表示沒有該key或者該key對應的value爲空;而HashTable的get返回空則必定是沒有該key;工具


IdentityHashMap
一、 和WeakHashMap同樣,用一個特殊值表示null的key;
二、 線程不安全;
三、 淺拷貝;
四、 底層用一個數組實現存儲,下標0,2,4,6…存儲key,下標1,3,5,7…存儲value,
remove時,將相應位置的值賦空,並把後面的元素往前移;
put時一次遞增兩個位置下標來查找;
hashCode採用native底層實現,根據內存地址計算哈希值,兩個key只有==時纔算相同,在字符串常量池和堆區的兩個相同字符串不算相等;優化


HashSet
   底層由HashMap提供支持,實現容器中元素單一出現的目的。ui


TreeSet
一、 有序的Set,元素須要實現Comparable接口,要求compareTo和equals的返回結果一致;
二、 Comparator負責提供給TreeMap比較器;
三、 具備有序集合的一些性質:好比提取比某個值大的子集合,提取在某一範圍內的子集合等有序才具備的操做;
四、 實現了NavigableSet接口,NavigableSet是SortedSet的子接口;
五、 底層爲TreeMap提供支持,Set中的元素就是Map的Key;
六、 淺拷貝;
七、 PRESENT:Set提供給底層Map的Value,全部Key共用經過一個Value;


Queue
   單向隊列,隊頭取出,隊尾加入。


Deque
   雙向隊列,雙向添加刪除,分別有兩個方向的迭代器。


Vector
   和ArrayList都同樣,可是提供了方法粒度級別的同步機制。


Stack
一、 繼承於Vector,線程安全,底層數組實現,自動擴張;
二、 棧頂增刪查操做,並提供整棧元素搜索功能。


WeakHashMap
一、 容許Key爲空,可是在存儲底層是使用了內部一個特殊Object對象來表示Null的Key;
二、 維持了一個弱引用隊列,Map的Entry就是一個弱引用對象;
三、 底層實現和HashMap基本一致,只是tables中的引用對象都是弱引用;
四、 弱引用:不能保證引用還存在時避免引用指向的內存不被垃圾回收機制回收;
五、 Entry在new的時候建立了一個弱引用對象並加入弱引用隊列中,該弱引用指向的內存空間隨時可能被回收,被回收後再使用該弱引用返回null,而且內部的多數Map操做都附帶了弱引用回收操做,把那些已經被回收的弱引用從弱引用隊列中移除,不影響該弱引用在hashTable中鏈表指向的下一個節點。


Collections
一、 封裝了集合的不少經常使用工具靜態方法,二分查找、排序、子集合、替換、比較等;
二、 synchronizedCollection等一系列的方法提供了將普通集合轉換成代碼塊粒度的同步,使用mutex進行同步;
三、 singleton提供了集合中單元素的集合靜態方法;
四、 unmodifiableCollection提供了將所給集合變成不可寫的集合的方法;
五、 等等。。。。。


Arrays
一、 數組的經常使用工具靜態方法,排序,二分查找,數組填充,子數組提取,深equals,深hashCode,數組複製等;
二、 基本數據類型使用插入排序(長度小於7)和快速排序(長度大於7);
三、 Object的數組使用歸併排序(穩定排序);


Array
   反射包中的Array,表示全部的數組,由native本地方法實現,一個數組就至關因而一個Object。原生數組中的相關調用就至關因而調用這個類中的相關方法。


String
一、 對char數組的封裝,至關因而一個元素爲char的ArrayList,沒有長度自動伸縮功能;
二、 封裝了字符串操做的經常使用方法,底層實現都是在反覆操縱char[];
三、 Equals重寫成了char[]的各個元素;
四、 hashCode重寫成char[]計算的哈希值;
五、 split經過不斷查找切割子串的位置來substring字符串獲得字符串分割結果數組;
六、 String長度建立後不變,改變的話就是整個char[]變了,不能對char[]數組中的指定下標進行隨機修改;


StringBuilder
一、 底層char[]實現,至關於ArrayList的char元素的實現,提供元素增刪改查;
二、 線程不安全;
三、 可設定初始長度,防止擴充長度的資源消耗;
四、 可修改指定下標的char值;
五、 動態修改動態添加,長度可變;


StringBuffer
   與StringBuilder繼承相同抽象類,底層相同實現,可是StringBuffer是線程安全的。


ThreadLocal
一、 多線程同時訪問統一共享屬性的時候產生的線程安全問題的一種解決方案,適用於每一個線程對這個共享屬性的修改都不會影響到其餘線程,即不須要線程間通訊的這種狀況;這樣作是爲了不使用同步鎖致使的效率問題(每一個線程各建立一個共享數據的副本分別服務於各自的線程);
二、 每一個Thread內部有兩個相似Map的屬性ThreadLocalMap,經過Thread.currentThread();獲取當前的線程實例,再獲取本線程中的Map實例,經過對這個Map中進行數據的增刪,實現共享數據的副本和線程綁定的目的,從而在必定程度上避免線程安全問題。

 


額外收穫:
1. transient:關鍵字,修飾的變量不參與序列化操做;
2. volatile:關鍵字,修飾的變量在每次使用時都會去查詢其最新值,防止編譯器優化使用緩存錯過他的最新值;
注:這裏的每次使用指的是從堆區複製這個值的瞬間,當一個線程訪問時,會從堆區拷貝這個值一份到本身的線程棧中,以後線程就只修改線程棧中的這個值,對於堆區的值沒有修改,這是volatile的侷限性。詳細看:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 3. 集合equals判斷:先判斷地址是否相同,再判斷類型是否相同,再判斷size,以後判斷集合中每一個元素是否相同; 4. 集合hashCode:集合中每一個非空元素的hashCode之和; 5. Remove若是刪除了集合中沒有的元素,集合沒有任何改變,返回false; 6. HashMap、LinkedHashMap、TreeMap區別(迭代遍歷順序):    HashMap存儲和查詢順序根據Hash而定,順序不肯定;    LinkedHashMap:按照元素插入前後順序;    TreeMap:按照元素Key比較順序,或臨時設定的比較器決定的順序輸出; 7. Comparable和Comparator:    Comparable是Entity元素的可實現接口,實現該接口的Entity在和本類型的其餘Entity比較時就是經過該接口的compareTo方法進行比較;    Comparator:提供給集合的比較器接口,該比較器能夠經過傳入相同類型的兩個對象進行compare比較並返回相應值判斷出大小關係(一般保證比較結果要和該類型的equals返回結果相一致)。

相關文章
相關標籤/搜索