java容器类:HashSet

HashSet是基于HashMap实现的,之前有被问到HashSet和HashMap的区别,我只死记了一条:HashSet的存储的内容不可重复,HashMap可以重复.那么HashSet基于HashMap实现,怎么做可以让HashSet中的对象不重复呢?

HashSet源码##

//Hashset类内部维护了一个HashMap类,提供5种构造方法用于实例化map类.
private transient HashMap<E,Object> map;
public HashSet() {
    map = new HashMap<>();
}
public HashSet(Collection<? extends E> c) {
    map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
    addAll(c);
}
public HashSet(int initialCapacity, float loadFactor) {
    map = new HashMap<>(initialCapacity, loadFactor);
}
public HashSet(int initialCapacity) {
    map = new HashMap<>(initialCapacity);
}
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

HashSet的size,isEmpty,contains,clear,add,remove等方法都是基于HashMap的对应方法实现的,而HashSet的不重复特性依靠add方法

//HashSet被调用的时候生成的一个简单对象    
private static final Object PRESENT = new Object();

//调用HashMap的put方法,将要插入的对象作为key,PRESENT作为值,两者联合为键值对存入map中
public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

public V put(K key, V value) {
    if (table == EMPTY_TABLE) {
        inflateTable(threshold);
    }
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key);
    int i = indexFor(hash, table.length);
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        Object k;
         //第一步首先判断key的哈希码是否一致,第二步判断代表key的对象是否一致,如果判断都通过的话新的值替换旧的值.
         //因此反复地传入相同对象,只会在一个位置重复替换没有实际意义的PRESENT对象(或者说根本没换过),达到了防重复的目的.
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {   
            V oldValue = e.value;
            e.value = value;
        //该方法在LinkedList有实现.
            e.recordAccess(this);
            return oldValue;
        }
    }

    modCount++;
        //如果无法匹配已经存在的键,则插入一个新的键值对.
    addEntry(hash, key, value, i);
    return null;
}
  • 判断是否重复的一个重要依据是对象的hashCode方法和euqal方法,我们可以通过重写这两个方法来自由制定我们的防重复的规则.
  • 例如我们判断对象是否重复基于其中的一个属性
public class Person {

public Integer age = 14;

@Override
public int hashCode() {
	return age.hashCode();
}

@Override
public boolean equals(Object obj) {
	Person person = (Person) obj;
	if(person.age == this.age) {
		return true;
	}
	return false;
}
}

这样两个age相同的Person类就只能有一个被纳入HashSet中

原文地址:https://www.cnblogs.com/itsrobin/p/5134560.html