若是不想看分析过程,可直接拉到文章末尾看结论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中是否存储该元素