浅析JDK1.8 HashSet源码。
写在开篇
HashSet源码比较简单,所以文章就会比较过水。
先简单介绍一下HashSet:
- 实现了Set接口,不允许元素重复
- 底层实现是基于HashMap的,它利用HashMap中的key存储数据,使用成员变量PRESENT来填充value
- 是线程不安全的
类的继承关系
HashSet继承AbstractSet抽象类,实现了Set(规定了Set的操作规范)、Cloneable(可拷贝)、Serializable(可序列化)这几个接口。
| 12
 3
 
 | public class HashSet<E>extends AbstractSet<E>
 implements Set<E>, Cloneable, java.io.Serializable {
 
 | 
成员变量
| 12
 3
 4
 5
 
 | private transient HashMap<E,Object> map;
 
 
 private static final Object PRESENT = new Object();
 
 | 
构造方法
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 
 | 
 
 public HashSet() {
 map = new HashMap<>();
 }
 
 
 
 
 public HashSet(Collection<? extends E> c) {
 map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
 addAll(c);
 }
 
 
 
 
 public HashSet(int initialCapacity, float loadFactor) {
 map = new HashMap<>(initialCapacity, loadFactor);
 }
 
 
 
 
 public HashSet(int initialCapacity) {
 map = new HashMap<>(initialCapacity);
 }
 
 
 
 
 
 
 HashSet(int initialCapacity, float loadFactor, boolean dummy) {
 map = new LinkedHashMap<>(initialCapacity, loadFactor);
 }
 
 | 
Set接口的实现
add()
HashSet将添加的元素通过map中的key来保存,当有相同的key时,也就是添加了相同的元素,那么map会讲value给覆盖掉,而key还是原来的key。
| 12
 3
 
 | public boolean add(E e) {return map.put(e, PRESENT)==null;
 }
 
 | 
remove()
HashSet通过删除map中key的返回值是否为PRESENT判断set中是否有该值。
| 12
 3
 
 | public boolean remove(Object o) {return map.remove(o)==PRESENT;
 }
 
 | 
contains()
直接调用map中containsKey()。
| 12
 3
 
 | public boolean contains(Object o) {return map.containsKey(o);
 }
 
 | 
isEmpty()
| 12
 3
 
 | public boolean isEmpty() {return map.isEmpty();
 }
 
 | 
size()
| 12
 3
 
 | public int size() {return map.size();
 }
 
 | 
iterator()
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 
 | public Iterator<E> iterator() {
 return map.keySet().iterator();
 }
 
 
 public Set<K> keySet() {
 Set<K> ks = keySet;
 if (ks == null) {
 ks = new KeySet();
 keySet = ks;
 }
 return ks;
 }
 
 
 private final class KeySet extends AbstractSet<K> {
 public Iterator<K> iterator() {
 return newKeyIterator();
 }
 public int size() {
 return size;
 }
 public boolean contains(Object o) {
 return containsKey(o);
 }
 public boolean remove(Object o) {
 return HashMap.this.removeEntryForKey(o) != null;
 }
 public void clear() {
 HashMap.this.clear();
 }
 }
 
 
 Iterator<K> newKeyIterator()   {
 return new KeyIterator();
 }
 
 
 
 private final class KeyIterator extends HashIterator<K> {
 public K next() {
 return nextEntry().getKey();
 }
 }
 
 | 
 
        
    
    
        
    Last updated: