1、HashSet主要的成员变量及构造方法
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
// 存储数据
private transient HashMap<E,Object> map;
// 该变量无变化
private static final Object PRESENT = new Object();
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初始化创建的实例为HashMap或者LinkedHashMap,而且从源码看出创建的实例功能方法调用还是其实例对应方法的调用
2、add添加内容
// HashMap中的内部类Node
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
.......................
}
// 添加方法
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
// HashMap中的put方法
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
// HashMap中的putVal方法,添加内容
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;
// 先赋值,判断第一个节点的元素是否为null
if ((p = tab[i = (n - 1) & hash]) == null)
// 没有内容的时候直接添加
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
// 判断第一个节点的键的hash值,键名是否不为空,是否相等
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
// 判断p变量是不是TreeNode的实例
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
// 判断当前节点的下一个节点是否为空
if ((e = p.next) == null) {
// 将新添加的节点的内容赋值给当前节点的p.next属性
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
3、contains是否包含某个键
// HashMap中的内部类Node
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
.......................
}
public boolean contains(Object o) {
return map.containsKey(o);
}
// HashMap中的containsKey方法
public boolean containsKey(Object key) {
return getNode(hash(key), key) != null;
}
// HashMap中的getNode方法
final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
// 先赋值判断
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
// 检查第一个节点
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
// 检查下一个节点
if ((e = first.next) != null) {
if (first instanceof TreeNode)
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
// 当前节点的指向的下一个节点不为null时,执行循环查找
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}
4、remove移除节点
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
// HashMap中的remove方法
public V remove(Object key) {
Node<K,V> e;
return (e = removeNode(hash(key), key, null, false, true)) == null ?
null : e.value;
}
// HashMap中的removeNode方法
final Node<K,V> removeNode(int hash, Object key, Object value,
boolean matchValue, boolean movable) {
Node<K,V>[] tab; Node<K,V> p; int n, index;
// 先赋值再判断
if ((tab = table) != null && (n = tab.length) > 0 &&
(p = tab[index = (n - 1) & hash]) != null) {
Node<K,V> node = null, e; K k; V v;
// 判断当前节点的属性是否相等
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
node = p;
// 判断当前节点指向的下一个节点是否为null
else if ((e = p.next) != null) {
if (p instanceof TreeNode)
node = ((TreeNode<K,V>)p).getTreeNode(hash, key);
else {
do {
// 判断当前节点的指向的下一个节点的属性与需要查询的属性是否相等
if (e.hash == hash &&
((k = e.key) == key ||
(key != null && key.equals(k)))) {
//找到了,当前节点的指向的下一个节点,赋值给变量node
node = e;
break;
}
// 没有找到,当前节点的指向的下一个节点,赋值给当前节点
p = e;
} while ((e = e.next) != null);
}
}
// 判断node变量是否为null
if (node != null && (!matchValue || (v = node.value) == value ||
(value != null && value.equals(v)))) {
if (node instanceof TreeNode)
((TreeNode<K,V>)node).removeTreeNode(this, tab, movable);
// 判断是否相等
else if (node == p)
tab[index] = node.next;
else
p.next = node.next;
++modCount;
--size;
afterNodeRemoval(node);
return node;
}
}
return null;
}
5、clear清空
public void clear() {
map.clear();
}
// HashMap中的clear方法
public void clear() {
Node<K,V>[] tab;
modCount++;
if ((tab = table) != null && size > 0) {
size = 0;
for (int i = 0; i < tab.length; ++i)
tab[i] = null;
}
}