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);
});