|
1 | | -努力编写中... |
| 1 | +HashSet 本身并没有什么特别的东西,它提供的所有集合核心功能,都是基于HashMap来实现的。如果了解HashMap源码的实现,HashSet 源码看起来跟玩一样。我的博客中有专门分析HashMap源码的文章,不熟悉的请自行翻阅。 |
| 2 | + |
| 3 | +HashSet 的特点如下: |
| 4 | +- 内部使用HashMap的key存储元素,以此来保证**元素不重复**; |
| 5 | +- HashSet是无序的,因为HashMap的key是**无序**的; |
| 6 | +- HashSet中允许有一个null元素,因为HashMap允许key为null; |
| 7 | +- HashSet是**非线程安全**的。 |
| 8 | + |
| 9 | +```java |
| 10 | +public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable { |
| 11 | + static final long serialVersionUID = -5024744406713321676L; |
| 12 | + |
| 13 | + // 基于HashMap实现 |
| 14 | + private transient HashMap<E,Object> map; |
| 15 | + |
| 16 | + // 只需要用到HashMap中key唯一的特性,所以value全部使用同一个 Object实例填充,节省内存空间 |
| 17 | + private static final Object PRESENT = new Object(); |
| 18 | + |
| 19 | + /** |
| 20 | + * 实例化 HashSet 的时候,初始化内部的 HashMap |
| 21 | + */ |
| 22 | + public HashSet() { |
| 23 | + map = new HashMap<>(); |
| 24 | + } |
| 25 | + |
| 26 | + /** |
| 27 | + * 根据一个集合实例,实例化 HashSet |
| 28 | + */ |
| 29 | + public HashSet(Collection<? extends E> c) { |
| 30 | + map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); |
| 31 | + addAll(c); |
| 32 | + } |
| 33 | + |
| 34 | + /** |
| 35 | + * 根据初始容量和扩容因子实例化 HashSet,减少rehash频率,提升性能,原理与HashMap相同 |
| 36 | + */ |
| 37 | + public HashSet(int initialCapacity, float loadFactor) { |
| 38 | + map = new HashMap<>(initialCapacity, loadFactor); |
| 39 | + } |
| 40 | + |
| 41 | + /** |
| 42 | + * 同上 |
| 43 | + */ |
| 44 | + public HashSet(int initialCapacity) { |
| 45 | + map = new HashMap<>(initialCapacity); |
| 46 | + } |
| 47 | + |
| 48 | + HashSet(int initialCapacity, float loadFactor, boolean dummy) { |
| 49 | + map = new LinkedHashMap<>(initialCapacity, loadFactor); |
| 50 | + } |
| 51 | + |
| 52 | + /** |
| 53 | + * 返回迭代器,用于迭代 |
| 54 | + * 下面所有的功能都是基于 HashMap 来实现的 |
| 55 | + */ |
| 56 | + public Iterator<E> iterator() { |
| 57 | + return map.keySet().iterator(); |
| 58 | + } |
| 59 | + |
| 60 | + /** |
| 61 | + * 元素个数 |
| 62 | + */ |
| 63 | + public int size() { |
| 64 | + return map.size(); |
| 65 | + } |
| 66 | + |
| 67 | + /** |
| 68 | + * 是否为空 |
| 69 | + */ |
| 70 | + public boolean isEmpty() { |
| 71 | + return map.isEmpty(); |
| 72 | + } |
| 73 | + |
| 74 | + /** |
| 75 | + * 是否包含给定元素 |
| 76 | + */ |
| 77 | + public boolean contains(Object o) { |
| 78 | + return map.containsKey(o); |
| 79 | + } |
| 80 | + |
| 81 | + /** |
| 82 | + * 添加元素,如果 Set集合中未包含该元素,返回true |
| 83 | + */ |
| 84 | + public boolean add(E e) { |
| 85 | + return map.put(e, PRESENT)==null; |
| 86 | + } |
| 87 | + |
| 88 | + /** |
| 89 | + * 删除元素,如果Set集合包含该元素,返回true |
| 90 | + */ |
| 91 | + public boolean remove(Object o) { |
| 92 | + return map.remove(o)==PRESENT; |
| 93 | + } |
| 94 | + |
| 95 | + /** |
| 96 | + * 清除元素 |
| 97 | + */ |
| 98 | + public void clear() { |
| 99 | + map.clear(); |
| 100 | + } |
| 101 | + |
| 102 | + /** |
| 103 | + * 浅克隆 |
| 104 | + */ |
| 105 | + @SuppressWarnings("unchecked") |
| 106 | + public Object clone() { |
| 107 | + try { |
| 108 | + HashSet<E> newSet = (HashSet<E>) super.clone(); |
| 109 | + newSet.map = (HashMap<E, Object>) map.clone(); |
| 110 | + return newSet; |
| 111 | + } catch (CloneNotSupportedException e) { |
| 112 | + throw new InternalError(e); |
| 113 | + } |
| 114 | + } |
| 115 | +} |
| 116 | +``` |
0 commit comments