前言
那么有没有人告诉你Set本质是什么?
Map
上一回我们说完Queue,
没看过的老铁可以看看我整理的系列:光头佳的求职之旅
https://blog.csdn.net/u013351145/category_11030408.html
Set
set是无序、不可重复的
主要方法基本和Colletion接口一致
/**
* 返回当前集合的个数,如果超过2147483647
* (即Integer的最大值)后也只能返回这个数值)
*/
int size();
// 判断当前集合是否为空,如果为空就返回true
boolean isEmpty();
// 判断当前集合是否包含输入参数对象
boolean contains(Object o);
// 迭代器(至于迭代的时候的顺序,要看你当前的集合,例如List可以保证顺序)
Iterator<E> iterator();
// 将集合转化为数组
Object[] toArray();
// 在集合中新增一个元素
boolean add(E e);
// 删除一个元素,这里提供的方法有个坑,后面再提
boolean remove(Object o);
// 判断当前集合是否包含另一个集合
boolean containsAll(Collection<?> c);
// 在当前集合里新增输入的集合元素
boolean addAll(Collection<?> c);
// 在当前集合里删除输入的集合元素
boolean removeAll(Collection<?> c);
//此处和Collection接口由区别
Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.DISTINCT);
}
HashSet
HashSet中的Hash是HashMao的Hash
下方为继承关系图
初始化
// 使用HashMap来存储HashSet的元素
private transient HashMap<E,Object> map;
// HashMap中存储的value值
private static final Object PRESENT = new Object();
// 构造一个空的hashSet,实际会初始化一个空的HashMap
public HashSet() {
map = new HashMap<>();
}
// 构造一个包含指定集合中元素的新集合
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
// 以指定的initialCapacity和loadFactor构造一个空的HashSet。
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
}
新增元素
实际将将该元素作为key放入HashMap,Value为默认的PRESENT。
由于HashMap的put()方法添加key-value对时,当新放入HashMap的Entry中key与集合中原有Entry的key相同(hashCode()返回值相等,通过equals比较也返回true),
新添加的Entry的value会将覆盖原来Entry的value,但key不会有任何改变,
因此如果向HashSet中添加一个已经存在的元素时,新添加的集合元素将不会被放入HashMap中,
原来的元素也不会有任何改变,这也就满足了Set中元素不重复的特性。
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
// 删除也是同样的原理
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
小结
HashSet中底层依靠HashMap实现,因此它的默认是加载因子(0.75),默认长度16,你可以认为HashSet就是一个value固定而key在变化的特殊HashMap。
LinkedHashSet
下图为继承关系
初始化
LinkedHashSet是HashSet的子类,基本方法和HashSet区别不大,
唯一的不同点在于LinkedHashSet中用于存储值的实现LinkedHashMap,
而HashSet使用的是HashMap。
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
public LinkedHashSet() {
super(16, .75f, true);
}
小结
LinkedHashSet中用LinkedHashMap来实现存储值。