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區別
共同點:底層都是用陣列實現儲存物件
區別:- 版本
ArrayList JDK1.2。Vector JDK1.0:在類集出現之前,都是直接繼承這個類。 - 初始化策略
Vector在無參構造執行後將物件陣列大小初始化為10.
ArrayList在構造階段並不初始化物件陣列,在第一次新增元素時才初始化陣列。-懶載入策略
建立大小minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
DEFAULT_CAPACITY大小為10 - 擴容策略:
Vector:2倍(根據作業系統不同而不同)
int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);
ArrayList:1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1); - 執行緒處理:
Vector: 方法上加鎖,執行緒安全,效率較低。 synchronized
ArrayList: 非同步處理,執行緒不安全,效率較高。
(即便要用執行緒安全的List,也不用Vector) - 遍歷:
Vector: 支援較老的迭代器Enumeration
ArrayList:不支援
- 問題2:ArrayList和LinkedList區別
共同點:都沒有加鎖操作,非同步處理。
區別:- 底層實現:
ArrayList:使用陣列
LinkedList:使用連結串列
1.3 Set介面
不允許資料重複!!
沒有擴充方法,直接覆寫collection的抽象方法。
- 有兩個很重要的子類:
- HashSet||無序儲存
實際上就是HashMap 的Key值+一個靜態的null物件
底層使用雜湊表+紅黑樹
允許存放null - 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工具類
- 常用子類
- 將執行緒不安全集合包裝成執行緒安全集合(不推薦)
推薦使用juc包下的併發集合類(ConcurrentHashMap、CopyOnWriteArrayList)
eg:把ArrayList變的安全
內部實現就是在方法內部使用 執行緒安全同步程式碼塊,效率較低
synchronizedList(list) - 向集合中一次加入多個元素
addAll() - 集合反轉
reverse() - 集合排序
sort()
寫到這裡,Collection介面和Map介面的特點、實現以及它們的常用子類的特點、區別、適用都已經有個大概瞭解和區分了。