1. 程式人生 > 實用技巧 >Collection介面及其常用子類(java.util包)

Collection介面及其常用子類(java.util包)

1. Collection介面

  • List關注事物的索引列表

    • ArrayList:可以理解為一個可增長的陣列,提供快速迭代和隨機訪問的能力。
    • LinkedList:可以理解為一個雙鏈表,提供快速插入刪除的能力。
    • Vector:是執行緒安全版本的ArrayList,但是效能低。

Collection結構圖及總結

Collection是單個集合儲存的最大父介面。
每一次進行資料操作的時候只能夠對單個物件進行處理。

public interface Collection<E> extends Iterable<E>
  • 1
    • Iterable是一個迭代器介面。
      介面Iterable,該介面包含一個能夠產生Iterator介面的iterator()方法,並且Iterable物件被foreach用來在序列中移動,因此建立的任何實現了Iterable介面的類都可以將它用於foreach。
    • 1.1Collection介面中的核心方法

      ****add(T t) //向類集中新增元素
      ****iterator() //取得類集迭代器
      addAll()
      clear()
      contains()
      remove()
      size()
      toArray()
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      ---------簡寫,並不全是無參。加星號的表示比較重要。

      collection只定義了儲存資料的標準,但是無法區分儲存型別。
      實際中更多的是使用兩個子介面:1. List(允許重複) 2. Set(不允許重複)

      1.2List介面

      在進行單個集合處理時,優先考慮List介面,是允許資料重複的。

      List介面若想儲存自定義類的物件,該類必須覆寫equals()才能使用contains()、remove()。
      所以使用List介面一定得覆寫equals()方法。

      List介面除了實現Collection介面的方法,還有自己獨有的方法。

      public E get(int index) //根據索引獲取資料
      public E set(int index,E element) //根據索引更新資料,返回原來資料
      
      • 1
      • 2

      List中有三個常用的子類,值得去深究它們之間的區別和底層實現。
      1.ArrayList 2.Vector 3.LinkedList 都繼承抽象類 AbstractList< E>抽象類

      重點重點重點重點

      • 問題1:ArrayList和Vector區別

      共同點:底層都是用陣列實現儲存物件
      區別:

      1. 版本
        ArrayList JDK1.2。Vector JDK1.0:在類集出現之前,都是直接繼承這個類。
      2. 初始化策略
        Vector在無參構造執行後將物件陣列大小初始化為10.
        ArrayList在構造階段並不初始化物件陣列,在第一次新增元素時才初始化陣列。-懶載入策略
        建立大小minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        DEFAULT_CAPACITY大小為10
      3. 擴容策略:
        Vector:2倍(根據作業系統不同而不同)
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
        ArrayList:1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
      4. 執行緒處理:
        Vector: 方法上加鎖,執行緒安全,效率較低。 synchronized
        ArrayList: 非同步處理,執行緒不安全,效率較高。
        (即便要用執行緒安全的List,也不用Vector)
      5. 遍歷:
        Vector: 支援較老的迭代器Enumeration
        ArrayList:不支援
      • 問題2:ArrayList和LinkedList區別

      共同點:都沒有加鎖操作,非同步處理。
      區別:

      1. 底層實現:
        ArrayList:使用陣列
        LinkedList:使用連結串列

      1.3 Set介面

      不允許資料重複!!

      沒有擴充方法,直接覆寫collection的抽象方法。

      • 有兩個很重要的子類:
      1. HashSet||無序儲存
        實際上就是HashMap 的Key值+一個靜態的null物件
        底層使用雜湊表+紅黑樹
        允許存放null
      2. TreeSet||有序儲存
        底層使用紅黑樹
        不允許存放null
        :因為是有序儲存,所以自定義類要想儲存到TreeSet中
        必須①實現Comparable介面
        或者②向TreeSet中傳入比較器(Compartor介面)
        實現比較標準,才能實現TreeSet中部分方法。
      • 問題1:說到了Comparable和Compartor介面,那就簡單比較區分一下:

      它們的目的和作用都是一樣的,在Java中實現自定義類的比較。
      多用於TreeSet和TreeMap。

      但是使用方法上和功能實現上都是完全不一樣的。

      實現java.lang.Comparable(1.2)介面,就說明該類支援排序。
      存放該類的collection或者陣列可以通過collections.sort()進行排序。可以直接存放在TreeSet中。
      介面內就一個int ComparTo(T o)方法,覆寫這個方法,就是告訴怎麼去比較。在類內實現排序。
      稱之為 類內比較器。

      第三方實現java.util.Comparator(1.5)介面,是需要比較的類本身不支援排序,就可以外部建立一個該類的"比較器"來進行排序。這個外部比較器實現Compartor介面即可。
      介面中有個compare(T t,E e)方法。建立一個類在類外實現排序。必須實現equals
      稱之為 外部比較器。
      -策略模式,更加靈活,可以輕鬆改變策略進行第三方排序。

      • 問題2:既然知道了TreeXXX自定義類的比較方法,那麼同樣在意順序的HashXXX怎麼比較物件順序呢?

      這就得引出一個HashCode概念,這是通過雜湊演算法雜湊得來的。雜湊表中的概念。
      要判斷大小就得同時覆寫HashCode()和equals()兩個方法。
      必須hashCode和equals都返回ture才是相等。
      equals比較的是元素的內容,HashCode比較的是元素儲存的經過hash轉化的地址。

      equals相同,hashcode一定保證相同
      hashcode相同,equals不一定相同

      這裡又引入了一個問題,問題3:雜湊碰撞,~~~
      把任意長度的字串變成固定長度的字串,所以必有一個輸出串對應無窮多個輸入串,碰撞是必然存在的。
      解決方法在這裡就簡單一提,
      1.開放定址法,也就是一直為衝突的元素找新地址
      2.再雜湊法,就是同時構造多個hash函式,衝突就換函式
      3.鏈地址法,把衝突的元素放進一個連結串列中
      4.建立公共溢位區,將衝突的元素統一放入另一個區域

      • 問題4:那為什麼非要在乎比較物件大小這個概念?

      因為Set是不可重複的,那既然不可重複就得規定一個標準,讓計算機知道怎麼樣才能算相等,就像定義了一個學生資訊表,你就得規定姓名和學號完全一樣才算相等。
      還有就是TreeXXX在意的是物件的自然排序,所以必須要定義這個比較"準則"。

      2. Collections工具類


      • 常用子類
      1. 將執行緒不安全集合包裝成執行緒安全集合(不推薦)
        推薦使用juc包下的併發集合類(ConcurrentHashMap、CopyOnWriteArrayList)
        eg:把ArrayList變的安全
        內部實現就是在方法內部使用 執行緒安全同步程式碼塊,效率較低
        synchronizedList(list)
      2. 向集合中一次加入多個元素
        addAll()
      3. 集合反轉
        reverse()
      4. 集合排序
        sort()

      寫到這裡,Collection介面和Map介面的特點、實現以及它們的常用子類的特點、區別、適用都已經有個大概瞭解和區分了。