ONE.Set集合
one.Set集合的特点
无序,唯一
TWO.HashSet集合
1.底层数据结构是哈希表(是一个元素为链表的数组)
2.那么HashSet如何来实现元素的唯一性的呢?
通过一HashSet添加字符串的案例查看HashSet中add()的源码,看为什么相同的字符串没有被加入HashSet中
interface Collection {
...
}
interface Set extends Collection {
...
}
class HashSet implements Set {
private static final Object PRESENT = new Object();
private transient HashMap<E,Object> map;
//1.从这一步我们可以看出来,HashSet()其实使用HashMap()实现的
public HashSet() {
map = new HashMap<>();
}
public boolean add(E e) { //e=hello,world
//2.add()方法的内部也是HashMap的实例对象调用方法,这里e是被添加的对象,而PRESENT是一个
private static final Object PRESENT = new Object();对象。
return map.put(e, PRESENT)==null;
}
}
class HashMap implements Map {
//3.来到HashMap实现的put方法
public V put(K key, V value) { //key=e=hello,world
//4.看哈希表是否为空,如果空,就开辟空间
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
//5.判断对象是否为null
if (key == null)
return putForNullKey(value);
//6_1.调用hash()方法,通过查看这个方法我们知道这个方法的返回值和对象的hashCode()方法相关
int hash = hash(key);
//7.在哈希表中查找hash值
int i = indexFor(hash, table.length);
//8.这里for循环的的初始条件是把table[i]赋值给e,如果在哈希表中找不到这个hash值得话,
就不会进入for循环比较,如果有的话,就会进入比较
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
//9.如果hash值一样(说实话,这一步每太看懂,既然能够查询到,说明两者的hash值必然相等),
并且地址值或者equls一样的话,不会添加进来
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
//走这里其实是没有添加元素
}
}
modCount++;
//9.把元素添加
addEntry(hash, key, value, i);
return null;
}
transient int hashSeed = 0;
//6_2.这是HashMap中的hash方法,从这个方法的实现我们可以看出,这个方法的唯一变量是
hashCode()
final