HashSet集合保证元素唯一性的原理 底层代码 ---有用

分析com.itheima.demo01_set.Demo03类中的代码, 我们发现, HashSet集合保证元素唯一性的原理可能和 HashSet#add()方法相关, 于是源代码分析如下:

//HashSet集合类中的代码.
public class HashSet {

//创建一个HashMap集合类对象.
private transient HashMap<E,Object> map;
//普通的Object类对象.
private static final Object PRESENT = new Object();

public HashSet() {
map = new HashMap<>(); //结论1: HashSet集合底层依赖的是HashMap集合.
}

//HashSet集合添加元素的方法.
public boolean add(E e) { //e: 表示要往集合中添加的元素.
return map.put(e, PRESENT)==null;
}
}


HashMap集合类中的源代码:
public class HashMap {

//key: 表示要往集合中添加的元素
//value: new Object()
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}

/*
hash: 表示 要往集合中添加的元素的 哈希值.
key: 表示 要往集合中添加的元素
value: new Object()
onlyIfAbsent: false
evict: true
*/
final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) {
//初始化哈希表引用.
Node<K,V>[] tab; Node<K,V> p; int n, i;
//对哈希表做非空校验, 即记录哈希表的长度
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
//如果元素在哈希表中不存在, 就创建一个 节点记录该元素.
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
//走这里, 说明哈希表不为空, 即: 集合中已经有元素存在了.
Node<K,V> e; K k;
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
//走到这里, 说明是同一个元素, 不添加.
else {
//具体添加元素的动作......
}
.....
}
}

通过观察源码, 我们发现, HashSet集合保证元素唯一性的原理, 和一个if判断相关, 我们详细看下这个判断:
/*
p: 集合中已经存在的元素.
p.hash: 集合中已经存在的元素的 哈希值.

hash: 表示 要往集合中添加的元素的 哈希值.
key: 表示 要往集合中添加的元素

*/
if ( true && ( false || ( true && false )))
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
//走到这里, 说明是同一个元素, 不添加.
else {
//具体添加元素的动作......
}

分析上述判断的具体流程:
1. 比较两个对象的哈希值是否相同.
如果相同: 说明可能是同一个对象, 程序继续执行.
如果不同: 说明不是同一个对象, 就添加.
2. 比较两个对象的地址值是否相同.
如果相同: 说明是同一个元素, 不添加.
如果不同: 说明可能不是同一个元素, 程序继续执行.
3. 判断要往集合中添加的元素是否为null
如果是: 说明要往集合中添加的元素为null, 就添加.
如果否: 说明可能不是同一个元素, 程序继续执行.
4. 比较两个对象的各个属性值是否相同.
如果相同: 说明是同一个元素, 不添加.
如果不同: 说明不是同一个元素, 就添加.

问: 要判断两个对象是否是同一个对象, 直接调用 equals()方法比较属性值不就行了吗, 为啥要设计的如何繁琐?
答: 这样做的目的就是为了减少调用 equals()方法的次数, 从而节约资源, 提高效率.

原文地址:https://www.cnblogs.com/shan13936/p/13850505.html