JavaSE_坚持读源码_HashSet对象_Java1.7
Posted rocker-pg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaSE_坚持读源码_HashSet对象_Java1.7相关的知识,希望对你有一定的参考价值。
对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSet 的源代码,可以看到如下代码:
1 package java.util; 2 3 public class HashSet<E> 4 extends AbstractSet<E> 5 implements Set<E>, Cloneable, java.io.Serializable 6 { 7 static final long serialVersionUID = -5024744406713321676L; 8 9 // 使用 HashMap 的 key 保存 HashSet 中的所有元素 10 private transient HashMap<E,Object> map; 11 12 // 定义一个虚拟的 Object 对象作为 HashMap 的 value 13 private static final Object PRESENT = new Object(); 14 15 // 初始化一个 HashSet ,底层会初始化一个 HashMap 16 public HashSet() { 17 map = new HashMap<>(); 18 } 19 20 public HashSet(Collection<? extends E> c) { 21 map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); 22 addAll(c); 23 } 24 25 // 以指定的 initialCapacity 和 loadFactor 创建一个 HashSet 26 // 其实就是以相应的参数创建 HashMap 27 public HashSet(int initialCapacity, float loadFactor) { 28 map = new HashMap<>(initialCapacity, loadFactor); 29 } 30 31 public HashSet(int initialCapacity) { 32 map = new HashMap<>(initialCapacity); 33 } 34 35 HashSet(int initialCapacity, float loadFactor, boolean dummy) { 36 map = new LinkedHashMap<>(initialCapacity, loadFactor); 37 } 38 39 // 调用 map 的 keySet 来返回所有的 key 40 public Iterator<E> iterator() { 41 return map.keySet().iterator(); 42 } 43 44 // 调用 HashMap 的 size() 方法返回 Entry 的数量,就得到该 HashSet 里的元素的个数 45 public int size() { 46 return map.size(); 47 } 48 49 // 调用 HashMap 的 isEmpty() 方法判断该 map 是否为空 50 // 当 map 为空时,对应的 HashSet 也为空 51 public boolean isEmpty() { 52 return map.isEmpty(); 53 } 54 55 // 调用 HashMap 的 containsKey() 判断是否包含指定的 key 56 // HashSet 的所有元素就是通过 HaseMap 的 key 保存的 57 public boolean contains(Object o) { 58 return map.containsKey(o); 59 } 60 61 // 将指定元素放入 HashSet 中,也是将该元素作为 key 存入到 HashMap 中 62 public boolean add(E e) { 63 return map.put(e, PRESENT)==null; 64 } 65 66 // 调用 HashMap 的 remove(o) 删除指定的 Entry ,也就是删除了 HashSet 对应的元素 67 public boolean remove(Object o) { 68 return map.remove(o)==PRESENT; 69 } 70 71 // 调用 HashMap 的 clear() 清空所有的 Entry ,也就清空 HashSet 中的所有元素 72 public void clear() { 73 map.clear(); 74 } 75 76 ... 77 78 }
由上面源程序可以看出,HashSet 的实现其实非常简单,它只是封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。
HashSet 的绝大部分方法都是通过调用 HashMap 的方法来实现的,因此 HashSet 和 HashMap 两个集合在实现本质上是相同的。
HashMap 的 put 与 HashSet 的 add
由于 HashSet 的 add() 方法添加集合元素时实际上转变为调用 HashMap 的 put() 方法来添加 key-value 对,当新放入 HashMap 的 Entry 中 key 与集合中原有 Entry 的 key 相同(hashCode() 返回值相等,通过 equals 比较也返回 true),新添加的 Entry 的 value 将覆盖原来 Entry 的 value,但 key 不会有任何改变,因此如果向 HashSet 中添加一个已经存在的元素,新添加的集合元素(底层由 HashMap 的 key 保存)不会覆盖已有的集合元素。
以上是关于JavaSE_坚持读源码_HashSet对象_Java1.7的主要内容,如果未能解决你的问题,请参考以下文章
Java源码初学_HashSet&LinkedHashSet