欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

HashSet源码分析

程序员文章站 2022-07-13 16:55:08
...

HashSet源码分析

 

 

HashSet是Set的一个实现,Set定义一个集合,集合的一个特征是不能包含重复的元素(可以包含null),HashSet底层使用HashMap作为存储结构来实现。

 

        可知HashSet只用来存储对象,并不是key-value对,因为HashMap中的key必须是不同的,跟集合的定义相同,

所以HashSet只使用HashMap中的key来存储元素,而value字段使用同一个常量对象PRESENT就可以了。

 

        private static final Object PRESENT = new Object();

        private transient HashMap<E,Object> map;

 

 

       可知HashSet中判断将要被存储的元素是否已经存在集合中,被转移到HashMap中判断key值是否有重复,而key的判断逻辑如下:

 

         //x,y是两个key

       static boolean eq(Object x, Object y) {

        return x == y || x.equals(y);
       }

 

         那么到底要不要重写HashSet中对象的equals()方法呢?个人认为这个还是需要根据具体应用需求来决定,默认情况下equals()实现就是比较(x == y),重写以后就是比较两对象的属性值是否相等。

         如果应用场景认为,两个对象相同的条件是指向同一个引用,就不需要重写equals()方法了。

         如果应用场景认为,两个对象相同的条件是指内部属性值相同,就需要重写equals()方法了。


 

        构造函数

 

  //可知HashSet只用来存储对象,并不是key-value对,因为HashMap中的key必须是不同的,跟集合的定义
  //相同,所以HashSet只使用HashMap中的key来存储元素,而value字段使用一个final Object PRESENT就可以
  public HashSet() {
	map = new HashMap<E,Object>();
  }

  //构造函数中指定底层HashMap的initialCapacity和loadFactor
  public HashSet(int initialCapacity, float loadFactor) {
	map = new HashMap<E,Object>(initialCapacity, loadFactor);
  }

   public HashSet(int initialCapacity) {
        map = new HashMap<E,Object>(initialCapacity);
   }
  

    add()方法

 

     public boolean add(E o) {

               //value值为PRESENT对象,一个常量对象
		return map.put(o, PRESENT)==null;
	    }
 

    remove()方法

     public boolean remove(Object o) {

               //map.remove(o)可能返回null,那就表示不存在目标Object o
               //删除失败
		return map.remove(o)==PRESENT;
 }

 

    contains()方法

     public boolean contains(Object o) {

                //到HashMap的Key中去查找目标对象O
		return map.containsKey(o);
  }
 

 

    Iterator

 

     //HashSet自己没有实现Iterator接口,而使用HashMap的实现

    public Iterator<E> iterator() {
		return map.keySet().iterator();
    }