若是不想看分析過程,可直接拉到文章末尾看結論html
先來看看 Set接口java
public interface Set<E> extends Collection<E> { int size(); boolean isEmpty(); boolean contains(Object o); Object[] toArray(); <T> T[] toArray(T[] a); boolean add(E e); boolean remove(Object o); boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); boolean retainAll(Collection<?> c); boolean removeAll(Collection<?> c); boolean equals(Object o); int hashCode(); }
咱們從以上接口發現Set並無get和set方法,也就是沒有查和改,爲何呢?緣由以下:安全
要弄清楚HashSet如何保證裏面的元素不重複,得從如下兩個方面入手:併發
當咱們弄清楚上面兩個問題以後咱們也能夠明白HashSet爲何是無序的了。code
且看源碼:htm
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable{ static final long serialVersionUID = -5024744406713321676L; private transient HashMap<E,Object> map; // Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); /** * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has * default initial capacity (16) and load factor (0.75). */ public HashSet() { map = new HashMap<>(); } ... }
咱們能夠看出來HashSet的底層存儲結構是一個HashMap,而且HashSet的元素做爲該Map的Key進行存儲,HashMap的Key的存儲是無序而且不可重複,這就解釋了HashSet中如何保證元素不重複blog
public boolean add(E e) {return map.put(e, PRESENT)==null;}
直接put到map當中繼承
由以上內容咱們能夠知道HashSet的底層存儲結構是HashMap,而且插入到HashSet中元素做爲map的key進行存儲,這就保證HashSet的一下特色:索引
咱們從上一小節瞭解到HashSet的底層存儲結構是HashMap,那麼它的增刪也就是map的put和remove接口
public boolean add(E e) {return map.put(e, PRESENT)==null;}
直接put到map當中
public boolean remove(Object o) {return map.remove(o)==PRESENT;}
直接在map中移除便可,很是簡單
在搞清楚CopyOnWriteArraySet爲何能支持併發 這個問題以前,咱們先來想一想如下幾個問題:
我想一旦咱們弄清楚上面兩個問題咱們就是知道 CopyOnWriteArraySet爲何能支持併發?
了
先來看看CopyOnWriteArraySet的部分源碼:
public class CopyOnWriteArraySet<E> extends AbstractSet<E> implements java.io.Serializable { private static final long serialVersionUID = 5457747651344034263L; private final CopyOnWriteArrayList<E> al; /** * Creates an empty set. */ public CopyOnWriteArraySet() { al = new CopyOnWriteArrayList<E>(); } ... }
從源碼中神奇地發現CopyOnWriteArraySet的底層存儲結構居然是CopyOnWriteArrayList,那麼咱們就能夠知道它的名字的由來了,而且知道它支持併發的原理跟CopyOnWriteArrayList是同樣的。
public boolean add(E e) { return al.addIfAbsent(e); }
看方法名咱們就是若是CopyOnWriteArrayList中不存在某元素纔會添加成功
public boolean remove(Object o) { return al.remove(o); }
直接從CopyOnWriteArrayList中移除
HashSet是如何保證元素的不重複和無序
答:由於HashSet的底層存儲結構是HashMap,而且HashSet中的元素是做爲Map的Key存儲到Map中,因此HashMap中Key是不重複且無序,因此HashSet中的元素也就是不重複和無序的
HashSet的增刪(改查?)原理
HashSet的增刪原理很簡單,就是map的put和remove,爲何沒有改查呢?那是由於HashSet中的元素是無序的,沒辦法根據索引進行查詢和修改
CopyOnWriteArraySet支持併發的原理
CopyOnWriteArraySet之因此叫CopyOnWriteArraySet,是由於它的底層存儲結構是CopyOnWriteArrayList,同時也就是保證了它的併發安全性
CopyOnWriteArraySet的增刪(改查?)原理
CopyOnWriteArraySet繼承了AbstractSet,跟HashSet同樣只有增刪,沒有改查,增刪原理也就是調用CopyOnWriteArrayList的增刪方法,只不過增的時候須要判斷一下List中是否存儲該元素