[关闭]
@kiraSally 2018-03-12T18:34:08.000000Z 字数 2552 阅读 2114

集合番@HashSet一文通(1.7版)

JAVA COLLECTIONS 源码 1.7版本


1.HashSet的定义

2.HashSet的数据结构

2.1 类定义

  1. public class HashSet<E>
  2. extends AbstractSet<E>
  3. implements Set<E>, Cloneable, java.io.Serializable

2.2 重要全局变量

  1. //维护一个HashMap作为底层数据结构
  2. private transient HashMap<E,Object> map;
  3. //Dummy value, HashSet存储时,将该值作为底层map的默认value
  4. private static final Object PRESENT = new Object();

2.3 构造器

  1. /**
  2. * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
  3. * default initial capacity (16) and load factor (0.75).
  4. */
  5. public HashSet() {
  6. map = new HashMap<>();
  7. }
  8. /**
  9. * 构造一个包含指定collection中的元素的新set。
  10. * 实际底层使用默认的加载因子0.75和足以包含指定collection中所有元素的初始容量来创建一个HashMap。
  11. * @param c 其中的元素将存放在此set中的collection。
  12. */
  13. public HashSet(Collection<? extends E> c) {
  14. map = new HashMap<E,Object>(Math.max((int) (c.size()/.75f) + 1, 16));
  15. addAll(c);
  16. }
  17. /**
  18. * 以指定的initialCapacity和loadFactor构造一个空的HashSet。
  19. * 实际底层以相应的参数构造一个空的HashMap。
  20. * @param initialCapacity 初始容量。
  21. * @param loadFactor 加载因子。
  22. */
  23. public HashSet(int initialCapacity, float loadFactor) {
  24. map = new HashMap<>(initialCapacity, loadFactor);
  25. }
  26. /**
  27. * 以指定的initialCapacity构造一个空的HashSet。
  28. * 实际底层以相应的参数及加载因子loadFactor为0.75构造一个空的HashMap。
  29. * @param initialCapacity 初始容量。
  30. */
  31. public HashSet(int initialCapacity) {
  32. map = new HashMap<>(initialCapacity);
  33. }
  34. /**
  35. * 以指定的initialCapacity和loadFactor构造一个新的空链接哈希集合。此构造函数为包访问权限,不对外公开,实际只是是对LinkedHashSet的支持。实际底层会以指定的参数构造一个空LinkedHashMap实例来实现。
  36. * @param initialCapacity 初始容量。
  37. * @param loadFactor 加载因子。
  38. * @param dummy 标记。
  39. */
  40. HashSet(int initialCapacity, float loadFactor, boolean dummy) {
  41. map = new LinkedHashMap<>(initialCapacity, loadFactor);
  42. }

3.HashSet的重要方法

3.1 add方法

  1. /**
  2. * 使用HashMap作为底层数据结构
  3. * 1.利用HashMap的key不重复原则实现非重
  4. * 2.由于HashMap的非有序导致HashSet的非有序
  5. * 3.HashMap的value使用一个final的static变量作为默认值
  6. * @Return 若put成功,返回true否则false (该方法在添加 key 不重复的键值对的时候,会返回 null)
  7. */
  8. public boolean add(E e) {
  9. return map.put(e, PRESENT)==null;
  10. }

3.2 clone方法

  1. /**
  2. * 返回此HashSet实例的浅表副本:并没有复制这些元素本身
  3. * @Return 底层实际调用HashMap的clone()方法,获取HashMap的浅表副本
  4. * 拓展:
  5. * 1.浅复制就是仅复制类中的值类型成员
  6. * 2.深复制就是复制类中的值类型成员和引用类型的成员
  7. */
  8. public Object clone() {
  9. try {
  10. HashSet<E> newSet = (HashSet<E>) super.clone();
  11. newSet.map = (HashMap<E, Object>) map.clone();
  12. return newSet;
  13. } catch (CloneNotSupportedException e) {
  14. throw new InternalError();
  15. }
  16. }

3.3 iterator方法

  1. /**
  2. * 1.基于迭代器模式(Set接口定义Iterator<E> iterator()方法)
  3. * 2.迭代map的keySet集合
  4. */
  5. public Iterator<E> iterator() {
  6. return map.keySet().iterator();
  7. }

4.HashSet的总结

  • 对于 HashSet 中保存的对象,请注意正确重写其 equalshashCode 方法,以保证放入的对象的唯一性
  • 有序可选用LinkedHashSetTreeSet
  • 线程安全可选用CopyOnWriteArraySetConcurrentSkipListSet

集合番@HashSet一文通(1.7版)黄志鹏kira 创作,采用 知识共享 署名-非商业性使用 4.0 国际 许可协议 进行许可。

本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注