集合详解之Set
一:先看看集合框架接口圖
可以看到Set接口實現(xiàn)了Collection,那么什么是Collection接口,以及Collection詳解請移步:集合詳解之List
二:散列集
談Set前先說說散列集,有一種總所周知的數(shù)據(jù)結(jié)構(gòu),可以快速的查找所需要的對象,它就是散列表(hash table)。散列表為每一個對象計算一個整數(shù),稱為散列碼,也叫哈希碼。散列碼是有對象的實例域產(chǎn)生的一個整數(shù)。更確切的說,具有不同數(shù)據(jù)域的對象將產(chǎn)生不同的散列碼,當(dāng)然這是理想的情況下。自定義的類,就要負(fù)責(zé)實現(xiàn)這個類的hashCode方法,然而有些程序設(shè)計者重寫hashCode()所使用的雜湊算法也許剛好會讓多個對象傳回相同的值,越是糟糕的雜湊算法越容易碰撞,這也與數(shù)據(jù)值域分布的特性有關(guān)。
在java中,散列表用鏈表數(shù)組實現(xiàn)。每個列表被稱作為桶。想要查找表中對象的位置,就要計算它的散列碼,然后與桶的總數(shù)取余,所得到的結(jié)果就是保存這個元素的桶的索引。列如,如果某個對象的散列碼為76268,并且有128個桶,對象就應(yīng)該保存在108號桶中(76268%128=108)。若桶中沒有其它元素就可以直接將元素插入桶中,若桶中有其它元素就需要用新對象與桶中的所有對象進(jìn)行比較,查看這個對象是否已經(jīng)存在,這種現(xiàn)象被稱為散列沖突。這種方法也是Set找重時所用到的方法,稍后會再次講到
? 散列表可以用于實現(xiàn)幾個重要的數(shù)據(jù)結(jié)構(gòu)。其中最簡單的就是set類型,set是沒有重復(fù)元素的元素集合,set的add方法首先會在集中查找要添加的對象,如果不存在,就將這個對象添加進(jìn)去。
?
?
二:Set是什么?
Set集合擴(kuò)展了Collection接口,它是一個不允許重復(fù)的集合,不會有多個元素引用相同的對象。
更正式地,集合不包含一對元素e1和e2 ,使得e1.equals(e2) ,并且最多一個空元素。 正如其名稱所暗示的那樣,這個接口模擬了數(shù)學(xué)集抽象。
Set接口中的方法:
boolean add(E e)
//添加指定的元素
boolean addAll(Collection<? extends E> c)
//將指定集合中的所有元素添加到此集合
void clear()
//從此集合中刪除所有元素
boolean contains(Object o)
//如果此集合包含指定的元素,則返回 true
boolean containsAll(Collection<?> c)
//如果此集合包含所有指定集合的元素返回 true
boolean equals(Object o)
//將指定的對象與此集合進(jìn)行比較以實現(xiàn)相等
int hashCode()
//返回此集合的哈希碼值。
boolean isEmpty()
//如果此集合不包含元素,則返回 true
Iterator<E> iterator()
//返回此集合中元素的迭代器。
boolean remove(Object o)
//如果存在,則從該集合中刪除指定的元素
boolean removeAll(Collection<?> c)
//從此集合中刪除指定集合中包含的所有元素
boolean retainAll(Collection<?> c)
//僅保留該集合中包含在指定集合中的元素
int size()
//返回此集合中的元素數(shù)
default Spliterator<E> spliterator()
//在此集合中的元素上創(chuàng)建一個 Spliterator 。
Object[] toArray()
//返回一個包含此集合中所有元素的數(shù)組。
<T> T[] toArray(T[] a)
//返回一個包含此集合中所有元素的數(shù)組; 返回的數(shù)組的運(yùn)行時類型是指定數(shù)組的運(yùn)行時類型
三:Set接口的具體實現(xiàn)類
1.HashSet
?查看HashSet的源碼可發(fā)現(xiàn),HashSet的底層是通過HashMap實現(xiàn)的
public HashSet(){map = new HashMap<>();}
HashSet類它實現(xiàn)了基于散列表的集。可以用add添加元素。contains方法已經(jīng)被重新定義,用來快速的查找是否某個元素已經(jīng)存在于集中,它只在某個桶中查找元素,而不需要查看集合中的所有元素。由于散列表將元素分散在表的各個位置上,所以訪問他們的順序幾乎是隨機(jī)的。所以只有不關(guān)心集合中元素的順序時才應(yīng)該使用HashSet。
HashSet中的方法:
boolean add(E e)
//將指定的元素添加到此集合
void clear()
//從此集合中刪除所有元素
Object clone()
//返回此 HashSet實例的淺層副本:元素本身不被克隆。
boolean contains(Object o)
//如果此集合包含指定的元素,則返回 true 。
boolean isEmpty()
//如果此集合不包含元素,則返回 true 。
Iterator<E> iterator()
//返回此集合中元素的迭代器。
boolean remove(Object o)
//如果存在,則從該集合中刪除指定的元素。
int size()
//返回此集合中的元素數(shù)(其基數(shù))。
Spliterator<E> spliterator()
//在此集合中的元素上創(chuàng)建late-binding和故障快速 Spliterator
HashSet檢查重復(fù)
當(dāng)你把對象加入HashSet時,HashSet會先計算對象的hashcode值來判斷對象加入的位置,同時也會與其他加入的對象的hashcode值作比較,如果沒有相符的hashcode,HashSet會假設(shè)對象沒有重復(fù)出現(xiàn)。但是如果發(fā)現(xiàn)有相同hashcode值的對象,這時會調(diào)用equals()方法來檢查hashcode相等的對象是否真的相同。如果兩者相同,HashSet就不會讓加入操作成功。
2.TreeSet
TreeSet類與散列集十分類似,不過它比散列集有所改進(jìn)。TreeSet是一個有序集合。可以以任意順序?qū)⒃夭迦爰现小T趯线M(jìn)行遍歷時,每個值將自動地按照排序后的順序呈現(xiàn)。排序使用樹結(jié)構(gòu)完成的(當(dāng)前使用的是紅黑樹,這里不做介紹,詳情請移步:五分鐘搞懂什么是紅黑樹)。如果要使用TreeSet方法就需要提供排序方法,否則就會報錯。詳情可閱讀:TreeSet的兩種排序方式
?
總結(jié)
- 上一篇: 集合详解之List
- 下一篇: Java集合详解之Map