我們?cè)?a href="http://www.lxweimin.com/p/69ac46f2a7f2" target="_blank">jdk源碼分析(四)——ArrayList和jdk源碼分析(五)——HashMap中分別分析了List和Map兩種數(shù)據(jù)結(jié)構(gòu),在Java的集合框架中,還有另一類(lèi)成員,就是Set,今天我們就來(lái)看看常用的
HashSet
。
一.類(lèi)定義
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
可以看到,和HashMap
類(lèi)似,HashSet
也是繼承了一個(gè)抽象類(lèi),并實(shí)現(xiàn)了一個(gè)基礎(chǔ)的接口Set
。
Set
接口中的主要方法如下:
核心的方法都是一些對(duì)集合的操作,例如添加元素,判斷元素是否存在,遍歷,刪除等。
二.存儲(chǔ)結(jié)構(gòu)
HashSet
主要是使用HashMap
來(lái)實(shí)現(xiàn)元素的存儲(chǔ)的:
// 存儲(chǔ)集合元素
private transient HashMap<E,Object> map;
// 常量,表示某個(gè)集合元素存在,在map中作為value
private static final Object PRESENT = new Object();
因此主要操作都是圍繞著這個(gè)map
進(jìn)行的,自然不可避免的要使用到我們上一篇中講到的HashMap
了。map
的value
是Object
類(lèi)型的常量。
三.常用方法
1.構(gòu)造方法
先來(lái)看看無(wú)參構(gòu)造方法:
public HashSet() {
map = new HashMap<E,Object>();
}
代碼很簡(jiǎn)單,只有一行,完成對(duì)map
的實(shí)例化,以備使用。
除了無(wú)參構(gòu)造方法外,還可以基于已有的集合類(lèi)來(lái)初始化HashMap
:
public HashSet(Collection<? extends E> c) {
map = new HashMap<E,Object>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
首先調(diào)用了HashMap
的構(gòu)造方法,并指定map
的初始容量。初始容量的計(jì)算方法如下:
(1)將集合中的元素個(gè)數(shù)除以0.75,向上取整
(2)?。?)中結(jié)果與16中的較大者
通過(guò)HashMap
的源碼分析,我們已經(jīng)知道,HashMap
的默認(rèn)裝載因子是0.75(也就是說(shuō),默認(rèn)只裝載75%左右的位置),而HashSet
底層使用HashMap
來(lái)存儲(chǔ),因此需要根據(jù)這個(gè)裝載因子算出需要的散列表大小。而HashMap
的默認(rèn)大小是16,因此這里的初始化大小最小是16。
2.add方法
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
邏輯實(shí)現(xiàn)也很簡(jiǎn)單,就是調(diào)用HashMap
的put
方法,將需要存儲(chǔ)的集合元素作為key,將常量PRESENT
作為value。put
方法的返回值是map中與此key關(guān)聯(lián)的value值,某個(gè)元素第一次存入時(shí)返回null,如果key已經(jīng)存在,則返回此key對(duì)應(yīng)的value。
需要注意的是,HashMap
是允許key覆蓋的,而集合Set的特性決定了,Set中同一個(gè)元素只能存在一次,因此,如果集合中已經(jīng)存在該元素了,那么map的返回值為非null,從而add
方法返回false。
3.contains方法
public boolean contains(Object o) {
return map.containsKey(o);
}
該方法也比較簡(jiǎn)單,直接調(diào)用HashMap
的containsKey
方法來(lái)判斷元素是否存在。
HashSet
的實(shí)現(xiàn)比較容易理解,我們就不再啰嗦了,輕松加愉快。期待與大家一起學(xué)習(xí)后面的jdk源碼。
本文已遷移至我的博客:http://ipenge.com/54585.html