与HashMap相同,HashSet也要求元素重写hashCode和equals方法,且对于两个对象如果equals相同,则hashCode也必须相同,如果元素是自定义类,需要注意这一点。
HashSet的应用场景:
1、 排重
2、 保存特殊值,比如保存用户黑白名单,来判断用户是否有某权限
3、集合运算,,set可以方便的进行交集,并集等运算
HashSet的内部实现
HashSet内部是用一个HashMap实现的:
private transient HashMap<E,Object> map;
HashSet相当于只有键,值都是相同的值:
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
基于这个内部组成,他的实现就很好懂了:
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
c.size()/.75f 用来计算loadFactor的默认值;
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
add方法就是直接调用map的put方法;
public boolean contains(Object o) {
return map.containsKey(o);
}
contains就是直接调用map的containsKey方法
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
public Iterator<E> iterator() {
return map.keySet().iterator();
}
remove和iterator方法也是直接是用的map的方法,简单的超乎想象。
特点小结:
1、 没有重复元素
2、可以高效的添加、删除元素、判断元素是否存在,效率为O(1)
3、 没有顺序
如果要保持添加的顺序,可以是用HashSet的子类:LinkedHashSet。Set还有一个重要的实现类TreeSet,他可以进行排序。