https://www.sxt.cn/Java_jQuery_in_action/nine-setinterface.html
https://www.sxt.cn/Java_jQuery_in_action/nine-hashset-bottomimplementation.html
https://www.bilibili.com/video/BV1ct411n7oG?p=159
Set容器特点:无序、不可重复。无序指Set中的元素没有索引,我们只能遍历查找;不可重复指不允许加入重复的元素。更确切地讲,新元素如果和Set中某个元素通过equals()方法对比为true,则不能加入;甚至,Set中也只能放入一个null元素,不能多个。
Set:没有顺序,不可重复。
List:有顺序(有索引),可以重复。
Set容器源码:
public interface Set<E> extends Collection<E> {......}
可以看到,Set继承自Collection。
Set的方法和Collection一模一样,Set里没有新加什么方法:
import java.util.HashSet;
import java.util.Set;
public class Test {
public static void main(String[] args) {
Set<String> set1 = new HashSet<>();
set1.add("aa");
set1.add("bb");
set1.add("aa");
System.out.println(set1);
set1.remove("bb");
System.out.println(set1);
Set<String> set2 = new HashSet<>();
set2.add("学习JAVA");
set2.addAll(set1);
System.out.println(set2);
}
}
输出结果:
[aa, bb]
[aa]
[aa, 学习JAVA]
HashSet是采用哈希算法实现,底层实际是用HashMap实现的(HashSet本质就是一个简化版的HashMap)。
打开HashSet源码:
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{......}
里面有一个核心的属性map:
private transient HashMap<E,Object> map;
往HashSet这个容器里放东西的话,都是往map里面放。
HashSet里所有的元素都是作为map的Key
Value都是:
private static final Object PRESENT = new Object();
固定地,每个Value都是它,这样就不用重复创建了。
所以new一个HashSet对象时,它把这个map也new好了:
public HashSet() {
map = new HashMap<>();
}
添加元素:
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
把加的元素放在Key里,Value都是创建好的Object对象PRESENT
所以,Set也是一个Map,加的元素都是Map的Key。
Map的Key不能重复,这就是为什么Set里面不能重复的原因。