1 HashSet
1.1 底層結(jié)構(gòu)
HashSet底層是基于HashMap或者LinkedHashMap實(shí)現(xiàn)的泰涂,所以HashSet數(shù)據(jù)結(jié)構(gòu)就是HashMap或者LinkedHashMap的數(shù)據(jù)結(jié)構(gòu)。
2 四個(gè)關(guān)注點(diǎn)
關(guān)注點(diǎn) | 結(jié)論 |
---|---|
HashSet是否允許空 | 允許 |
HashSet是否允許重復(fù)數(shù)據(jù) | 不允許 |
HashSet是否有序 | 無(wú)序,特別說(shuō)明這個(gè)無(wú)序指的是遍歷HashSet的時(shí)候滔韵,得到的元素的順序和插入的順序不一致 |
HashSet是否線程安全 | 非線程安全 |
3 HashSet源碼解析
3.1 類的繼承關(guān)系
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
3.2 類的屬性
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
// 版本序列號(hào)
static final long serialVersionUID = -5024744406713321676L;
// 鍵值Map
private transient HashMap<E,Object> map;
// 用作所有鍵對(duì)應(yīng)的值,鍵所對(duì)應(yīng)的值都相等
private static final Object PRESENT = new Object();
}
說(shuō)明:HashSet中由于只包含鍵,不包含值拼卵,由于在底層具體實(shí)現(xiàn)時(shí),使用的HashMap或者是LinkedHashMap(可以指定構(gòu)造函數(shù)來(lái)確定使用哪種結(jié)構(gòu))蛮艰,我們知道HashMap是鍵值對(duì)存儲(chǔ)腋腮,所以為了適應(yīng)HashMap存儲(chǔ),HashSet增加了一個(gè)PRESENT類域(類所有)壤蚜,所有的鍵都有同一個(gè)值(PRESENT)即寡。
3.3 類的構(gòu)造函數(shù)
1. HashSet()型構(gòu)造函數(shù)
public HashSet() {
map = new HashMap<>();
}
說(shuō)明:底層維護(hù)了一個(gè)HashMap。
2. HashSet(Collection<? extends E> c)型構(gòu)造函數(shù)袜刷。
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
3. HashSet(int initialCapacity, float loadFactor)型構(gòu)造函數(shù)聪富。
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
說(shuō)明:可以指定初始化容量和負(fù)載因子。
4. HashSet(int initialCapacity)型構(gòu)造函數(shù)水泉。
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
5. HashSet(int initialCapacity, float loadFactor, boolean dummy)型構(gòu)造函數(shù)善涨。
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
說(shuō)明:底層維護(hù)了一個(gè)LinkedHashMap。
3.4 核心函數(shù)分析
add草则、contains钢拧、remove函數(shù)等都是基于HashMap或者LinkedHashMap做的操作。
1. isEmpty函數(shù)
public boolean isEmpty() {
return map.isEmpty();
}
2. contains函數(shù)
public boolean contains(Object o) {
return map.containsKey(o);
}
3. add函數(shù)
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
說(shuō)明:因?yàn)閙ap的鍵e不能重復(fù)炕横,所以使得set中不能出現(xiàn)重復(fù)的對(duì)象源内。
4. remove函數(shù)
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}