1.HashSet
*它应该是用得最多得Set接口实现类了,主要记住几个重要的点就OK了。- 里面的元素是无重复的、无序的,但是可以有null值
- 它对于重复元素的定义
- 他是线程不安全的
其实他的底层是通过HashMap来实现的,当我们执行new HashSet();的时候发生了什么呢?
来看看HashSet的源码
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable
{
private transient HashMap<E,Object> map;
public HashSet() {
map = new HashMap<>();
}
...
}
发现了吗?其实就是实例化了一个HashMap对象,没错就是这么简单
下面再来看看,当我们往里面加元素的时候,它干了什么
private static final Object PRESENT = new Object();
...
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
其实,就是把输入的元素作为key,放到了hashmap中,所以加入到hashset中的元素显然是不能重复的。(其实它的很多东西和hashmap是相同的,比如线程不安全)
关于元素重复的定义
我们使用HashMap的结构来思考
首先key的位置是由它的hashcode决定的,所以当要加入的元素hashcode不同时,显然是可以放置在不同的bucket中的;其次,当元素的hashcode相同,但是equals不同时,显然是会放置在链表中的。
所以,要是想满足我们对set的定义,显然在自定义类中,重写hashcode和equal方法时,要注意一致性的问题。