java容器篇

來源:互聯網
上載者:User

標籤:指標   dex   rand   基於   欄位   可重複   類型   fir   添加   

容器
     -Collection 儲存物件的集合;Map 儲存索引值對的映射表
     -Iterator(迭代器模式)
         -集合訪問器,用於逐一查看集合中的對象
         -所有實現了Collection介面的容器類都有iterator方法,用於返回一個實現了Iterator介面的對象。Iterator對象稱作迭代器,Iterator介面方法能以迭代方式逐個訪問集合中各個元素,並可以從Collection中除去適當的元素
     -Collection
         -set(特徵:無序且不可重複)
             -TreeSet:基於紅/黑樹狀結構實現,支援有序性操作,例如根據一個範圍尋找元素的操作。但是尋找效率不如 HashSet,HashSet 尋找的時間複雜度為 O(1),TreeSet 則為 O(logN)。
             -HashSet:基於雜湊表實現,支援快速尋找,但不支援有序性操作。並且失去了元素的插入順序資訊,也就是說使用 Iterator 遍曆 HashSet 得到的結果是不確定的
             -LinkedHashSet:具有 HashSet 的尋找效率,且內部使用雙向鏈表維護元素的插入順序
             -紅/黑樹狀結構:漫畫看懂紅/黑樹狀結構 連結:https://www.sohu.com/a/201923614_466939
         -list(特徵:有序且可重複)
             -ArrayList:基於動態數組實現,支援隨機訪問。
                 -概覽
                     -實現了 RandomAccess 介面,因此支援隨機訪問。這是理所當然的,因為 ArrayList 是基於數組實現的,其數組的預設大小為 10。
                 -序列化
                     -基於數組實現,並且具有動態擴容特性,因此儲存元素的數組不一定都會被使用,那麼就沒必要全部進行序列
                      transient Object[] A; //transient關鍵字聲明數組預設不會被序列化
                         -為什麼定義A數組要用transient關鍵字修飾,使其預設不被序列化?
                             假如現在實際有了5個元素,而elementData的大小可能是10,那麼在序列化時只需要儲存5個元素,數組中的最後五個元素是沒有實際意義的,不需要儲存。所以ArrayList的設計者將elementData設計為transient,然後在writeObject方法中手動將其序列化,並且只序列化了實際儲存的那些元素,而不是整個數組
                     -序列化時需要使用 ObjectOutputStream 的 writeObject() 將對象轉換為位元組流並輸出。而 writeObject() 方法在傳入的對象存在 writeObject() 的時候會去反射調用該對象的 writeObject() 來實現序列化。還原序列化使用的是 ObjectInputStream 的 readObject() 方法,原理類似。
                     -java中序列化的目的:
                         -以某種儲存形式使自訂對象持久化;
                         -將對象從一個地方傳遞到另一個地方。
                         -使程式更具維護性
                 -擴容
                     -添加元素時使用 ensureCapacityInternal() 方法來保證容量足夠,如果不夠時,需要使用 grow() 方法進行擴容,新容量的大小為 oldCapacity + (oldCapacity >> 1),也就是舊容量的 1.5 倍
                     -擴容操作需要調用 Arrays.copyOf() 把原數組整個複製到新數組中,這個操作代價很高,因此最好在建立 ArrayList 對象時就指定大概的容量大小,減少擴容操作的次數
                 -刪除元素
                     -需要調用 System.arraycopy() 將 index+1 後面的元素都複製到 index 位置上,該操作的時間複雜度為 O(N), ArrayList 刪除元素的代價是非常高的。
                 -fail-fast
                     -modCount 用來記錄 ArrayList 結構發生變化的次數。結構發生變化是指添加或者刪除至少一個元素的所有操作,或者是調整內部數組的大小,僅僅只是設定元素的值不算結構發生變化
                     -在進行序列化或者迭代等操作時,需要比較操作前後 modCount 是否改變,如果改變了需要拋出 ConcurrentModificationException。
                 -fail-fast與fail-safe
                     -fail-fast
                         -fail-fast機制在遍曆一個集合時,當集合結構被修改,會拋出ConcurrentModificationException。
                         -java.util包下的集合類都是快速失敗的,不能在多線程下發生並發修改(迭代過程中被修改)。
                     -fail-safe
                         -fail-safe任何對集合結構的修改都會在一個複製的集合上進行修改,不像fail-fast在原集合上修改,因此不會拋出ConcurrentModificationException
                         -java.util.concurrent包下的容器都是安全失敗,可以在多線程下並發使用,並發修改。
                         -優點
                             -避免了ConcurrentModificationException
                         -缺點
                             -需要複製集合,產生大量的無效對象,開銷大
                             -無法保證讀取的資料是目前未經處理資料結構中的資料。
                             -迭代器並不能訪問到修改後的內容,即:迭代器遍曆的是開始遍曆那一刻拿到的集合拷貝,在遍曆期間原集合發生的修改迭代器是不知道的。
             -Vector:和 ArrayList 類似,但它是安全執行緒的。
                 -它的實現與 ArrayList 類似,但是使用了 synchronized 進行同步。因此是安全執行緒的
                 -與ArrayList比較
                     -Vector 是同步的,因此開銷就比 ArrayList 要大,訪問速度更慢。最好使用 ArrayList 而不是 Vector,因為同步操作完全可以由程式員自己來控制;
                     -Vector 每次擴容請求其大小的 2 倍空間,而 ArrayList 是 1.5 倍。
             -LinkedList:基於雙向鏈表實現,只能順序訪問,但是可以快速地在鏈表中間插入和刪除元素。不僅如此,LinkedList 還可以用作棧、隊列和雙向隊列。
                 -概覽
                     -基於雙向鏈表實現,使用 Node 儲存鏈表節點資訊。
                       private static class Node<E> {
                             E item;
                             Node<E> next;
                             Node<E> prev;
                         }
                       每個鏈表格儲存體了 first 和 last 指標
                       transient Node<E> first;
                       transient Node<E> last;
                 -與 ArrayList 的比較
                     -ArrayList 基於動態數組實現,LinkedList 基於雙向鏈表實現;
                     -ArrayList 支援隨機訪問,LinkedList 不支援;
                     -LinkedList 在任意位置添加刪除元素更快。
     -Map
         -TreeMap:基於紅/黑樹狀結構實現
         -HashMap:基於雜湊表實現。
             -儲存結構
                 -內部包含了一個 Entry 類型的數組 table。
                     transient Entry[] table;
                     Entry 儲存著索引值對。它包含了四個欄位,從 next 欄位我們可以看出 Entry 是一個鏈表。即數組中的每個位置被當成一個桶,一個桶存放一個鏈表。HashMap 使用拉鏈法來解決衝突,同一個鏈表中存放雜湊值相同的 Entry。
                     {{{{{{{entry結構圖}}}}}}}
             - 拉鏈法的工作原理
                 HashMap<String, String> map = new HashMap<>();
                 map.put("K1", "V1");
                 map.put("K2", "V2");
                 map.put("K3", "V3");
                 建立一個 HashMap,預設大小為 16;
                 插入 <K1,V1> 索引值對,先計算 K1 的 hashCode 為 115,使用除留餘數法得到所在的桶下標 115%16=3。
                 插入 <K2,V2> 索引值對,先計算 K2 的 hashCode 為 118,使用除留餘數法得到所在的桶下標 118%16=6。
                 插入 <K3,V3> 索引值對,先計算 K3 的 hashCode 為 118,使用除留餘數法得到所在的桶下標 118%16=6,插在 <K2,V2> 前面。
                
                 -應該注意到鏈表的插入是以頭插法方式進行的,例如上面的 <K3,V3> 不是插在 <K2,V2> 後面,而是插入在鏈表頭部。
                 -尋找需要分成兩步進行:
                     -計算索引值對所在的桶;
                     -在鏈表上順序尋找,時間複雜度顯然和鏈表的長度成正比。
             -put操作
                 -HashMap 允許插入鍵為 null 的索引值對。但是因為無法調用 null 的 hashCode() 方法,也就無法確定該索引值對的桶下標,只能通過強制指定一個桶下標來存放。HashMap 使用第 0 個桶存放鍵為 null 的索引值對。
             -確定桶下標
             -擴容
                 -基本原理
                 -重新計算桶下標
                 -計算數組容量
             -鏈錶轉紅/黑樹狀結構
                 -從 JDK 1.8 開始,一個桶儲存的鏈表長度大於 8 時會將鏈錶轉換為紅/黑樹狀結構
             -與 HashTable 的比較
                 HashTable 使用 synchronized 來進行同步。
                 HashMap 可以插入鍵為 null 的 Entry。
                 HashMap 的迭代器是 fail-fast 迭代器。
                 HashMap 不能保證隨著時間的推移 Map 中的元素次序是不變的。
         -HashTable:和 HashMap 類似,但它是安全執行緒的,這意味著同一時刻多個線程可以同時寫入 HashTable 並且不會導致資料不一致。它是遺留類,不應該去使用它。現在可以使用 ConcurrentHashMap 來支援安全執行緒,並且 ConcurrentHashMap 的效率會更高,因為 ConcurrentHashMap 引入了分段鎖。
         -LinkedHashMap:使用雙向鏈表來維護元素的順序,順序為插入順序或者最近最少使用(LRU)順序。

java容器篇

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.