一、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; }