HashSet是Java中常用的一個集合類涡驮,是Set接口的一個實(shí)現(xiàn)類固耘,而Set接口繼承自Collection接口眷射,所以HashSet是Collection的一個實(shí)現(xiàn)類挖腰。
本篇主要討論一下HashSet底層代碼的實(shí)現(xiàn)雕沿。
核心成員變量
//HashSet底層是基于HashMap存儲數(shù)據(jù),該map的key就是HashSet要存放的數(shù)據(jù)
private transient HashMap<E,Object> map;
//該變量用來填充上一個map的value字段猴仑,因?yàn)镠ashSet關(guān)注的是map的Key
private static final Object PRESENT = new Object();
無參構(gòu)造函數(shù)
public HashSet() {
//實(shí)例化map成員變量
map = new HashMap<>();
}
說明:
- hashSet底層是基于hashMap實(shí)現(xiàn)的审轮,hashSet存放的數(shù)據(jù)實(shí)際就是hashMap的key,而hashMap的value存放的是一個靜態(tài)的final對象PERSENT;
- 當(dāng)調(diào)用hashSet無參構(gòu)造函數(shù)的時候辽俗,實(shí)際只是實(shí)例化了hashMap對象疾渣。
add(E e)方法實(shí)現(xiàn)
//添加一個元素,如果該元素已經(jīng)存在崖飘,則返回true榴捡,如果不存在,則返回false
public boolean add(E e) {
//往map中添加元素朱浴,返回null薄疚,說明是第一個往map中添加該key
return map.put(e, PRESENT)==null;
}
說明:
- 往hashSet中添加元素,實(shí)際是往map成員變量里面添加對應(yīng)的key和value赊琳;
- map 中的key實(shí)際就是要添加的元素,value是一個固定的對象砰碴;
- 當(dāng)?shù)谝淮瓮鵰ap中添加key時躏筏,添加成功返回null,所以當(dāng)?shù)谝淮瓮鵫ashSet中添加元素時呈枉,會返回true趁尼;
- 由于hashMap中的key不能重復(fù),所以hashSet不能存儲重復(fù)元素猖辫;
remove(Object o)方法實(shí)現(xiàn)
//刪除指定的元素酥泞,刪除成功返回true
public boolean remove(Object o) {
//實(shí)際是刪除map中的一個對象
return map.remove(o)==PRESENT;
}
說明:
- 當(dāng)hashSet刪除一個元素時,實(shí)際是操作map刪除對應(yīng)的元素啃憎;
- 當(dāng)刪除map中一個不存在的對象是芝囤,會返回null,所以這里當(dāng)返回PERSENT時,說明之前hashSet往map中添加過對應(yīng)的元素悯姊,因此羡藐,當(dāng)remove(o)返回true時,說明之前已經(jīng)存在該元素悯许,并且成功刪除仆嗦;當(dāng)返回false時,說明之前并沒有添加過該對象先壕;
iterator()方法實(shí)現(xiàn)
//獲取hashSet的迭代器
public Iterator<E> iterator() {
//調(diào)用map獲取keySet
return map.keySet().iterator();
}
說明
- hashset獲取迭代器實(shí)際是獲取map的keySet的iterator瘩扼;
size()方法實(shí)現(xiàn)
public int size() {
return map.size();
}
說明
- size方法實(shí)際是調(diào)用map.size方法;
總結(jié)
hashSet底層是基于hashMap實(shí)現(xiàn)的垃僚,hashSet存儲的元素對應(yīng)hashMap的key集绰,因?yàn)閔ashMap不能存儲重復(fù)的Key,所以hashSet不能存放重復(fù)元素冈在;由于hashMap的key是基于hashCode存儲對象的倒慧,所以hashSet中存放的對象也是無序的;hashSet也沒有提供get方法包券,可以通過Iterator迭代器獲取數(shù)據(jù)纫谅。