详述HashSet集合中remove()方法的执行过程
程序员文章站
2022-05-14 07:50:02
...
一、实现HashSet集合中remove()方法
1、创建HashSet对象
HashSet<Object> hashSet = new HashSet<Object>();
查看HashSet的构造方法
public HashSet() {
map = new HashMap<>();
}
2、在HashSet中添加元素
hashSet.add("1");
hashSet.add("2");
hashSet.add("3");
3、执行remove方法
hashSet.remove("2");
System.out.println(hashSet);
4、结果
1,3
二、HashSet的remove方法的执行过程
1、HashSet类中的remove方法
public boolean remove(Object o) {
//调用了map对象(HashMap类)的remove方法
return map.remove(o)==PRESENT;
}
2、HashMap类中的remove方法
public V remove(Object key) {
Node<K,V> e;
//调用了hash方法和removeNode方法
return (e = removeNode(hash(key), key, null, false, true)) == null ?
null : e.value;
}
其中
- hash方法
static final int hash(Object key) {
int h;
//如果对象不为null怎返回传入对象调用hashCode的返回值
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
- 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;
//1.因为前面调用了HashSet的add方法中又调用了putVal方法
//在putVal方法中对table已经初始化过了默认为16
//因为传入的是字符串"2",他们调用hashCode方法的范围值和之前的添加的"2"是相同的
//所以这里可以得到之前添加的元素对应的索引
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 &&
// 2.这里传入的字符串"2"的hash值和之前存入的"2"的hash值相同
// 传入对象和目标对象地址相同,所以这里把p的地址值赋值给node
// *但是如果出入对象和要删除的对象地址值不同,则需要调用传入对象的equals方法
// 如果返回的是true则把p的地址值赋给node
((k = p.key) == key || (key != null && key.equals(k))))
node = p;
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 = e;
break;
}
p = e;
} while ((e = e.next) != null);
}
}
//3.由于node不为null,上面传入的matchValue为false所以这里进入if语句
//返回node,则remove方法返回node,在add方法中可以知道node的value是之前添加元素的value
//所以返回node它的value就是传入对象的PRESENT,比较之后返回true删除成功
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;
}
}
注意:
String类比较特殊,因为如果直接使用赋值的方法创建String对象,如果第一次创建就在常量池中存储该字符串对象,后来创建的字符串如果和常量池中的字符串相同,则直接把常量池中的地址赋值给新的对象,则前后两次创建的对象指向同一个地址,该地址在常量池中并且存储了对应的String对象。
上一篇: Android中的消息机制二(Handler的工作过程)
下一篇: Handler消息机制
推荐阅读
-
MySQL 存储过程中执行动态SQL语句的方法_MySQL
-
Mybaits 源码解析 (六)----- 全网最详细:Select 语句的执行过程分析(上篇)(Mapper方法是如何调用到XML中的SQL的?)
-
Mybaits 源码解析 (六)----- 全网最详细:Select 语句的执行过程分析(上篇)(Mapper方法是如何调用到XML中的SQL的?)
-
MySQL存储过程中实现执行动态SQL语句的方法_MySQL
-
【转载】C#中List集合使用Remove方法移除指定的对象
-
详述ArrayList类中的contains方法(Java:集合与泛型(五))
-
Python中执行存储过程及获取返回值的方法介绍
-
MySQL 存储过程中执行动态SQL语句的方法
-
详述HashSet集合中remove()方法的执行过程
-
Python中执行存储过程及获取返回值的方法介绍