java容器篇

來源:互聯網
上載者:User

標籤:ast   技術分享   first   img   持久化   還原序列化   安全執行緒   圖片   資訊   

引言

   第三天卡。。。

  今天主要看了下java容器方面的知識,很累但是很充實。吃兩把雞去了,休息一下,再戰。

開始

    -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。
                   

            - 拉鏈法的工作原理
                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.