Java集合源码解析系列
HashSet
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
static final long serialVersionUID = -5024744406713321676L;
private transient HashMap<E,Object> map;
//因为底层是HashMap,这个PRESENT是默认的value
private static final Object PRESENT = new Object();
/**
* HashSet底层是HashMap
*/
public HashSet() {
map = new HashMap<>();
}
/**
* 这个构造方法是用于LinkedHashSet来调用的,可以保证插入的顺序
*
*/
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
public int size() {
return map.size();
}
public boolean isEmpty() {
return map.isEmpty();
}
public boolean contains(Object o) {
return map.containsKey(o);
}
/**
* 这里可以看到PRESENT作为value值,而插入的对象作为key存入HashMap
* HashMap的put方法会通过key计算除哈希值,找到对应的位置的数据,如果已经存在就会替换老的数据,并把老的数据返回,相当于没有插入key
* HashSet以此来保证不会有重复的数据插入
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
/**
* 同样是调用HashMap的remove方法来删除数据
*/
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
/**************equals方法在AbstractSet中,通过这个方法来判断是否是同一个对象***************/
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Set))
return false;
Collection c = (Collection) o;
if (c.size() != size())
return false;
try {
return containsAll(c);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
}
}
- HashSet底层是基于HashMap来实现,所以也不是线程安全的
- HashSet中不能插入相同的对象,且允许插入null
- HashSet仅仅存储对象,而不是键值对
- HashSet没有get方法,通过add方法存储对象
- LinkedHashSet底层是基于LinkedHashMap实现
以上是基于Java1.8
应用
面试时有时候会碰到一个问题:从2个数组里面选出相同的数
其中一个思路就可以用HashSet来实现:
- 首先把其中一个数组中的元素添加到HashSet中
- 然后把另外一个数组中的元素添加到HashSet中
- HashSet的add方法返回false的就是重复的元素
当然还有更好的方法,这里只是提供一个思路。
欢迎关注我的微信公众号,和我一起每天进步一点点!