一、HashSet 非線程安全數組
HashSet的實現是基於Map的存儲方式(Map的實現是基於數組+鏈表的數據結構),以下是HashSet的add的過程源碼:安全
a、調用add方法時,其實是調用map的put方法數據結構
b、在map.put過程當中,源碼以下:線程
首先使用key去計算hash值,根據hash值在數組地址塊中檢查該位置是否已經存放了數據。若是沒有數據,則直接調用addEntry(hash, key, value, i);將數據添加進去。3d
若是數組的該位置已經有數據了,則對比該位置上全部的map鏈表數據,若是存在key徹底同樣,則用新值替換原來的舊值blog
不然就是在原來的map最後加上連接到最新的數據源碼
最後獲得的數據結構以下:hash
二、TreeSet 有序,非線程安全it
TreeSet的存儲過程是使用樹結構,根據key值的比較來肯定在樹的左右,源碼以下:io
public V put(K key, V value) { Entry<K,V> t = root; if (t == null) { // TBD: // 5045147: (coll) Adding null to an empty TreeSet should // throw NullPointerException // // compare(key, key); // type check root = new Entry<K,V>(key, value, null); size = 1; modCount++; return null; } int cmp; Entry<K,V> parent; // split comparator and comparable paths Comparator<? super K> cpr = comparator; if (cpr != null) { do { parent = t; cmp = cpr.compare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } else { if (key == null) throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; do { parent = t; cmp = k.compareTo(t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t != null); } Entry<K,V> e = new Entry<K,V>(key, value, parent); if (cmp < 0) parent.left = e; else parent.right = e; fixAfterInsertion(e); size++; modCount++; return null; }