HashSet
HashSet 的实现是基于HashMap。看代码
private transient HashMap<E,Object> map;
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
- HashSet的实现是利用了HashMap.是将对象作为Key来存入HashMap.
- 我们都知道HashMap的key重复的话下面会覆盖。所以HashSet是不能重复的。
- 因为HashMap是无序的,所以HashSet也是无序得
特点
- 无序
- 可以插入null值
- 不可插入重复数据
HashMap 为什么是无序得?
答:
- HashMap添加元素时,也就是调用put(key,value)时。程序会根据key与哈希算法来计算出hashcode
- 根据hashcode 和 数组长度 来定位对象在数组中的位置, 所以HashMap是无序的,因为对象在数组上的位置不是按照添加顺序来的,是根据hashcode和HashMap的数组长度通过一定算法来计算出来的
LinkedHashSet
LinkedHashSet继承了HashSet。实现有序是基于LinkedHashMap。看代码
public LinkedHashSet() {
super(16, .75f, true);
}
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
特点
- 有序
- 可以插入null值
- 不可插入重复数据
LinkedHashMap为什么是有序的?
答
- LinkedHashMap 是双向链表和HashMap的集合。双向链表保持了LinkedHashMap的有序
- LinkedHashMap重写了newNode()和Node类
Node代码如下
static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after;
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
before(前一个) 和 after(后一个) 保证了插入顺序
TreeSet
源码真的不想看了,记录下特点吧
- 有序
- 不允许插入null值
- 写入的数据不会出现重复的值,重复会覆盖
Set的遍历
Set<String> set = new HashSet<String>();
set.add("ddd");
set.add("sss");
set.add("fff");
set.add("ggg");
Iterator<String> value = set.iterator();
while (value.hasNext()) {
String s = value.next();
System.out.println(s);
}
// 或者
for (String s : set) {
System.out.println(s);
}
// 或者 (jdk1.8生效)
set.forEach(s -> {
System.out.println(s);
});