HashSet
HashSet实现于Set接口,使用HashMap作为数据支撑,它不会保证遍历的顺序,允许null元素。
注意方法不是同步的,如果有多线程进行操作需要进行同步处理。也可以使用
Set s = Collections.synchronizedSet(new HashSet(...))
来创建一个线程安全的Set。
创建HashSet
// HashSet的数据真正的储存在HashMap中
private transient HashMap<E,Object> map;
// HashSet中存储的所有value值同一个静态变量值
private static final Object PRESENT = new Object();
如果你还不了解HashMap的原理,请查看HashMap。
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
}
仅仅是初始化了HashMap。
添加值
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
通过HashMap的内部原理可知,其put方法会在新添加元素至HashMap时;或者如果新添加的值产生了hash冲突,并且在Node链中找不到与key对应的值时才会返回null。所以我们得知在这两种情况下,HashSet才算把元素添加成功!
删除值
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
通过HashMap的内部原理可知,当待删除的对象被成功删除后会返回一个非null的Node。而我们存储的是同一个PRESENT对象,所以可以使用等于符号判断是否是删除成功。
iterator遍历
public Iterator<E> iterator() {
return map.keySet().iterator();
}
通过HashMap的内部原理可知,HashSet此时可以创建一个可以遍历的Iterator对象。该对象遍历HashMap的key值,而HashSet中的值就是存储在HashMap中的key中,因此此时可以获取到HashSet中的值。
性能问题
由于HashSet中使用HashMap存储,所以其性能受制于HashMap,请查看其实现原理。