《ThinkinginJava之Set接口、HashSet源碼學(xué)習(xí)》由會員分享,可在線閱讀,更多相關(guān)《ThinkinginJava之Set接口、HashSet源碼學(xué)習(xí)(5頁珍藏版)》請?jiān)谘b配圖網(wǎng)上搜索。
1、文檔供參考,可復(fù)制、編制,期待您的好評與關(guān)注!
Thinking in Java之Set接口、HashSet源碼學(xué)習(xí)
文章主要討論Set接口的設(shè)計(jì)、以及Set接口的一個(gè)實(shí)現(xiàn)類HashSet的設(shè)計(jì)細(xì)節(jié)。對于他們的思考,同樣是基于源碼學(xué)習(xí)的。
Set接口設(shè)計(jì)
通過閱讀API和源碼我們可以知道Java中的Set和數(shù)學(xué)行直觀的“集”的概念是相同的。Set的最大特點(diǎn)也就是不允許在其中放入重復(fù)的元素。Set集合最多只能包含一個(gè)null元素。至于這種特點(diǎn)是如何實(shí)現(xiàn)的,我們先不考究。在其具體子類HashSet里我們在討論之。廣州java培訓(xùn)咨詢QQ:707552864,544627
2、560
Set接口源碼解析
首先看看Set的源碼吧。
[java] view plaincopy
package com.kiritor;
/**
Set源碼研究*/
import java.util.Iterator;
public interface Set extends Collection {
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator iterator();
Object[] toArray();
T[]
3、toArray(T[] a);
boolean add(E e);
boolean remove(Object o);
boolean containsAll(Collection c);
boolean addAll(Collection c);
boolean retainAll(Collection c);
boolean removeAll(Collection c);
void clear();
boolean equals(Object o);
int hashCode();
}
可以看出的是Set繼承至Collec
4、tion,而且通過對比還可以知道的是,Set提供的方法和Colllection指定的方法是完全一樣的。那么它的不重復(fù)是如何體現(xiàn)的呢?這里我們通過研究其具體實(shí)現(xiàn)類HashSet來說明。
HashSet類實(shí)現(xiàn)
同樣的對于HashSet類的具體源碼筆者就不貼出來了。這里我們只是簡要的對其的方法做一些分析。首先看看HashSet類的頭部吧。
對于序列化、Cloneable接口筆者就不細(xì)說了。這里HashSet繼承AbstactSet這個(gè)中間抽象類,并且這個(gè)抽象類又繼承至AbstractCollection。這里簡要的說說自己的理解。在前一章對ArrayList的學(xué)習(xí)中,筆者并未就這方
5、面給予解釋。AbstractCollection其實(shí)更像是實(shí)現(xiàn)List,Set的共同的方法,而AbstactSet AbstactList更像是提供給Set、List各自特有方法的實(shí)現(xiàn)。
1、底層實(shí)現(xiàn)
通過其源碼的觀察可以知道的是HashSet的底層實(shí)現(xiàn)是基于HashMap的。它不保證Set的迭代順序而且不保證該順序永久不變。HashSet的實(shí)現(xiàn)較為的簡單,其相關(guān)的操作都是通過直接調(diào)用底層HashMap的相關(guān)方法來完成。
[java] view plaincopy
// 底層使用HashMap來保存HashSet中所有元素。
private transient
6、 HashMap map;
// 定義一個(gè)虛擬的Object對象作為HashMap的value,將此對象定義為static final。
private static final Object PRESENT = new Object();
2、構(gòu)造方法
[java] view plaincopy
* 默認(rèn)的無參構(gòu)造器,構(gòu)造一個(gè)空的HashSet。
* 實(shí)際底層會初始化一個(gè)空的HashMap,并使用默認(rèn)初始容量為16和加載因子0.75。
*/
public HashSet() {
map = new HashMap();
}
/
7、**
* 構(gòu)造一個(gè)包含指定collection中的元素的新set。
*
* 實(shí)際底層使用默認(rèn)的加載因子0.75和足以包含指定
* collection中所有元素的初始容量來創(chuàng)建一個(gè)HashMap。
* @param c 其中的元素將存放在此set中的collection。
*/
public HashSet(Collection c) {
map = new HashMap(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
/**
* 以指定的initialCap
8、acity和loadFactor構(gòu)造一個(gè)空的HashSet。
*
* 實(shí)際底層以相應(yīng)的參數(shù)構(gòu)造一個(gè)空的HashMap。
* @param initialCapacity 初始容量。
* @param loadFactor 加載因子。
*/
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap(initialCapacity, loadFactor);
}
/**
* 以指定的initialCapacity構(gòu)造一個(gè)空的HashSet。
*
9、
* 實(shí)際底層以相應(yīng)的參數(shù)及加載因子loadFactor為0.75構(gòu)造一個(gè)空的HashMap。
* @param initialCapacity 初始容量。
*/
public HashSet(int initialCapacity) {
map = new HashMap(initialCapacity);
}
/**
* 以指定的initialCapacity和loadFactor構(gòu)造一個(gè)新的空鏈接哈希集合。
* 此構(gòu)造函數(shù)為包訪問權(quán)限,不對外公開,實(shí)際只是是對LinkedHashSet的支持。
*
* 實(shí)際底層會以指定的參
10、數(shù)構(gòu)造一個(gè)空LinkedHashMap實(shí)例來實(shí)現(xiàn)。
* @param initialCapacity 初始容量。
* @param loadFactor 加載因子。
* @param dummy 標(biāo)記。
*/
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap(initialCapacity, loadFactor);
}
3、存儲元素
[java] view plaincopy
/**
* 如果此set中
11、尚未包含指定元素,則添加指定元素。
* 更確切地講,如果此 set 沒有包含滿足(e==null ? e2==null : e.equals(e2))
* 的元素e2,則向此set 添加指定的元素e。
* 如果此set已包含該元素,則該調(diào)用不更改set并返回false。
*
* 底層實(shí)際將將該元素作為key放入HashMap。
* 由于HashMap的put()方法添加key-value對時(shí),當(dāng)新放入HashMap的Entry中key
* 與集合中原有Entry的key相同(hashCode()返回值相等,通過equals比較也返回true),
12、* 新添加的Entry的value會將覆蓋原來Entry的value,但key不會有任何改變,
* 因此如果向HashSet中添加一個(gè)已經(jīng)存在的元素時(shí),新添加的集合元素將不會被放入HashMap中,
* 原來的元素也不會有任何改變,這也就滿足了Set中元素不重復(fù)的特性。
* @param e 將添加到此set中的元素。
* @return 如果此set尚未包含指定元素,則返回true。
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
4、讀取、遍歷元素
[
13、java] view plaincopy
/**
* 返回對此set中元素進(jìn)行迭代的迭代器。返回元素的順序并不是特定的。
*
* 底層實(shí)際調(diào)用底層HashMap的keySet來返回所有的key。
* 可見HashSet中的元素,只是存放在了底層HashMap的key上,
* value使用一個(gè)static final的Object對象標(biāo)識。
* @return 對此set中元素進(jìn)行迭代的Iterator。
*/
public Iterator iterator() {
urn map.keySet().iterator();
}
14、
5、刪除元素
[java] view plaincopy
/**
* 如果指定元素存在于此set中,則將其移除。
* 更確切地講,如果此set包含一個(gè)滿足(o==null ? e==null : o.equals(e))的元素e,
* 則將其移除。如果此set已包含該元素,則返回true
* (或者:如果此set因調(diào)用而發(fā)生更改,則返回true)。(一旦調(diào)用返回,則此set不再包含該元素)。
*
* 底層實(shí)際調(diào)用HashMap的remove方法刪除指定Entry。
* @param o 如果存在于此set中則需要將其移除的對象。
15、 * @return 如果set包含指定元素,則返回true。
*/
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
瘋狂Java培訓(xùn)的課程采用針對性培養(yǎng),全面提升學(xué)員就業(yè)能力,重點(diǎn)加強(qiáng)訓(xùn)練職業(yè)素質(zhì)。老師辛勤的講解,讓學(xué)員充分感受Java的魅力,充分激發(fā)每個(gè)學(xué)員對于編程的熱愛,讓學(xué)員在半年的時(shí)間內(nèi)掌握8-10萬的代碼量,成為真正的技術(shù)高手,瘋狂Java采用企業(yè)全真模擬開發(fā)訓(xùn)練,迅速積累項(xiàng)目經(jīng)驗(yàn)。讓學(xué)員迅速獲得其他人需要花費(fèi)兩年才能獲得的工作技能,迅速獲得高薪就業(yè)。如需了解更多,請登陸瘋狂軟件學(xué)院官網(wǎng)fkjava
瘋狂軟件學(xué)院地址:廣州市天河區(qū)車陂大崗路4號灃宏大廈3樓
5 / 5