HashSet源码分析

一、HashSet简介

HashSet存储的是无序、不重复的对象。每组数据都没有索引,需要通过索引来进行操作的方法都没有,所以也不能使用普通for循环来进行遍历。存储元素的顺序并不是按照存入时的顺序(和List显然不同) 是按照哈希值来存的所以取数据也是按照哈希值取的。
public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable

 HashSet继承AbstractSet类,实现Set、Cloneable、Serializable接口。

有四种构造函数

   //默认构造函数,创建一个大小为16的容器,加载因子为0.75
    public HashSet() {
        map = new HashMap<>();
    }
// 带集合的构造函数
 public HashSet(Collection<? extends E> c) {
  // 因为从HashMap的效率(时间成本和空间成本)考虑,HashMap的加载因子是0.75。
  // 当HashMap的“阈值”(阈值=HashMap总的大小*加载因子) < “HashMap实际大小”时,就要将HashMap的容量翻倍。
  // 所以,(c.size()/.75f) + 1 计算出来的正好是总的空间大小。
  map = new HashMap<E,Object>(Math.max((int) (c.size()/.75f) + 1, 16));
  // 将集合(c)中的元素都添加到HashSet中
  addAll(c);
 }

// 指定HashSet初始容量和加载因子的构造函数
 public HashSet(int initialCapacity, float loadFactor) {
  map = new HashMap<E,Object>(initialCapacity, loadFactor);
 }

 // 指定HashSet初始容量的构造函数
 public HashSet(int initialCapacity) {
  map = new HashMap<E,Object>(initialCapacity);
 }
 

  

二、主要方法

2.1 add()方法

底层利用了HashMap键进行了元素的添加。

HashMap的put()方法中,该方法的返回值是对应HashMap中键值对中的值,

//如果当前列表中没有e则将e加进去
 public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

2.2 clear()方法

 

从set中移除所有元素。调用HashMap的clear方法清空所有元素。

 

    public void clear() {
        map.clear();
    }

2.3 remove()方法

 

如果指定元素存在于此set中,则将其移除。如果此set已包含该元素,则返回true。调用HashMap的remove方法删除指定Entry。
    public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }

    public V remove(Object key) {
        Node<K,V> e;
        return (e = removeNode(hash(key), key, null, false, true)) == null ?
            null : e.value;
    }

  

 

2.4 contains()方法

底层实际调用HashMap的contains Key,判断是否包含指定key

   public boolean contains(Object o) {
        return map.containsKey(o);
    }

2.5  iterator()方法

返回对此set中元素进行迭代的迭代器。返回元素的顺序并不是特定的。调用底层HashMap的keySet来返回所有的key。
    public Iterator<E> iterator() {
        return map.keySet().iterator();
    }

  

上一篇:HashSet的扩容过程


下一篇:HashSet集合介绍