HashSet的存储原理:
1、将要传入的数据根据系统的hash算法得到一个hash值;
2、根据hash值可以得出该数据在hash表中的位置;
3、判断该位置上是否有值,没有值则把数据插入进来;如果有值则再次判断传入的值与原值是否地址或equals相同,如果相同则不存,否则通过链表的方式 存储到该位置。
如果两个对象equals,但是没有重写hashcode,就会导致集合中存储多个相等的对象!所以必须重写!
比如:
Set<Integer> set = new HashSet<Integer>();
set.add( e );//add方法是return map.put( e , PRESENT) == null;
本质是实例化医个HashMap对象 ---->map = new HashMap<>();
然后是map.put()方法,
public V put(K key,V value){
if(table == EMPTY_TABLE){
inflateTable(threshold); //此处是初始化一张哈希表,表为数组结构
}
int hash = hash(key); //根据key值,计算出对应的int类型的hash值
int i = inexFor(hash,table.length): //通过hash值在table表中得到一个存储的位置
//判断指定下标的位置是否为空,如果为空则跳出循环,直接添加
//否则与该位置上的链表元素一一比较,如果哈希值相同且地址或equals相同,则返回
//否则添加进来
for(Entry<K,V> e = table[i]; e != null; e = e.next){
Object k ;
//如果哈希值相等并且地址相等(需重写equals)
if(e.hash == hash && ((k = e.key) == key || key.equals(k)){
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i); //以链表的方式添加元素
return null;
}