HashSet源码分析2

package com.test1;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class SetTest {
    public static void main(String[] args) {
        /*
         * Set<String> set = new HashSet<>();
         * System.out.println(set.add("abc"));
         * System.out.println(set.add("xyz"));
         * System.out.println(set.add("abc"));
         * 
         * for (Iterator<String> it = set.iterator(); it.hasNext();) {
         * System.out.println(it.next()); }
         */
        /*
         * String a = "abc"; String b = "abc"; System.out.println(a.hashCode());
         * System.out.println(b.hashCode());
         */
        Set<People> set2 = new HashSet<>();
        set2.add(new People("zhangsan"));
        set2.add(new People("lisi"));
        set2.add(new People("zhangsan"));
        for (Iterator<People> it = set2.iterator(); it.hasNext();) {
            System.out.println(it.next().getName());
        }
    }
}

class People {
    String name;

    public People(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof People) {
            People people = (People) obj;
            if(this.name.equals(people.getName()));
                return true;
        }
        return false;
    }
    @Override
    public int hashCode() {
        return this.name.hashCode();
    }
}

我们来看HashSet的构造方法:

  /**
     * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
     * default initial capacity (16) and load factor (0.75).
     */
    public HashSet() {
        map = new HashMap<>();
    }

竟然是new HashMap<>();

关于HashSet与HashMap之间的关系:

HashSet是由HashMap来实现的。HashSet里面的几乎所有的方法都是由HashMap实现的

这个HashMap的key就是放进HashSet中的对象,value就是一个Object类型的对象,当调用HashSet的add方法时,实际上是向HashMap中增加了一行(key-value对),该key就是向HashSet中增加的那个对象,该行的value就是一个Object类型的对象。HashMap底层采用数组维护(数组中每个元素都是一个Map.Entry对象),调用增加的那个对象的hashCode方法,得到一个hashCode值,然后根据该值计算出一个数组的下标索引(计算出数组中的一个位置),将准备添加到Map中的对象与该位置处的对象进行比较(equals方法),如果相同,那么就向该位置处的那个对象(Map.Entry类型)的value值替换掉,否则沿着该Entry链继续重复上述过程,如果链的最后依然没有找到相同的对象,那么这个时候就将该对象添加到数组中,将数组中该位置处的Entry对象链接到这个对象后面:对于HashSet与HashMap来说,这样做是为了提高查找的效率,使得查找时间不随着Set或Map的大小而改变。

查看add方法

    /**
     * Adds the specified element to this set if it is not already present.
     * More formally, adds the specified element <tt>e</tt> to this set if
     * this set contains no element <tt>e2</tt> such that
     * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
     * If this set already contains the element, the call leaves the set
     * unchanged and returns <tt>false</tt>.
     *
     * @param e element to be added to this set
     * @return <tt>true</tt> if this set did not already contain the specified
     * element
     */
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

 

posted @ 2015-09-10 16:03  vincent_duan  阅读(121)  评论(0编辑  收藏  举报