一、Set 概述
Set 是继承自 Collection 的接口,它的实现结构如下:
|----Set:存储无序的(元素的遍历顺序与添加的顺序无关),不可重复的数据
|-----HashSet:Set 的主要实现类,线程不安全(Set实现)
|-----LinkedHashSet:HashSet 的子类,遍历时可以按照添加的顺序遍历(HashSet子类)
|-----TreeSet:(Set 的另一个实现)
二、HashSet 的存储过程
HashSet 的底层实现是 HashMap,所以这里就主要讲一下大概过程,而不涉及细节,对理解 HashMap 起个帮助作用。
步骤:(添加对象 a)
-
利用 a 的 hashCode 与数组的长度做操作,计算元素的存储位置;
-
添加元素
2.1 如果该位置没有元素,直接添加;
2.2 如果有元素 b,则 a 与元素 b 比较 hashCode,如果 hashCode 不同,就把 a 放到该位置,b 通过链表连在 a 后面(jdk 7 是 a 放在 b 后面),一个位置链了多个元素也是同理;
2.3 如果 hashCode 相同,则通过比较二者的 equals 方法来判断是否相同,如果 equals 返回 false,添加成功;
2.4 如果 equals 返回 true,添加失败。
总结:HashSet 中添加的对象一定要重写 equals 方法和 hashCode 方法,否则 HashSet 将失效。
remove 不会删除掉 p1,因为 p1 的 name 改变之后 hashCode 就变了,remove 不会定位到 p1 所在的位置
hashCode 就变了,remove 不会定位到 p1 所在的位置
后面两个 add 都会成功,第一个是因为 hash 不一样,第二个是因为 equasl 返回false