CopyOnWriteArraySet源码分析

 分析完CopyOnWriteArrayList之后接着看CopyOnWriteArraySet。CopyOnWriteArraySet与CopyOnWriteArrayList相比不同之处就是不能添加重复的元素,Set集合没有按索引直接获取或修改或添加或删除的方法(get(int index),add(int index,E e),set(int index,E e),remove(int index))。

CopyOnArraySet类结构如下:
public class CopyOnWriteArraySet<E> extends AbstractSet<E> implements java.io.Serializable;AbstractSet是set接口的骨干实现,从而最大限度的减少了实现此接口所需的工作。
1、对于CopyOnWriteArraySet需要掌握以下几点:
·构造方法:CopyOnWriteArraySet();
·添加元素:即add(E)方法;
·删除对象:即remove(E)方法;
·遍历所有对象:即iterator(),在实际中更常用的是增强型的for循环去做遍历。
以上操作底层都是对CopyOnWriteArrayList操作,分析过CopyOnWriteArrayList,这些方法就比较简单了。
2、构造方法:
/**

  • 创建一个空的set
    */
    public CopyOnWriteArraySet() {
    al = new CopyOnWriteArrayList<E>(); //底层转化为了对CopyOnWriteArrayList的操作
    }

/**

  • Creates a set containing all of the elements of the specified
  • collection. 使用指定的元素创建set
  • @param c the collection of elements to initially contain
  • @throws NullPointerException if the specified collection is null
    */
    public CopyOnWriteArraySet(Collection<? extends E> c) {
    al = new CopyOnWriteArrayList<E>();
    al.addAllAbsent(c); //元素不存在时添加
    }
    3、添加元素
  • @param e element to be added to this set
  • @return <tt>true</tt> if this set did not already contain the specified
  • element
    */
    public boolean add(E e) {
    return al.addIfAbsent(e);//元素不存在时添加
    }

    /**

    • Append the element if not present.如果元素不存在,则追加元素
    • @param e element to be added to this list, if absent
    • @return <tt>true</tt> if the element was added
      */
      public boolean addIfAbsent(E e) {
      final ReentrantLock lock = this.lock;
      lock.lock(); //尝试申请独占锁
      try {
      // Copy while checking if already present. 复制数组,同时检查元素是否存在
      // This wins in the most common case where it is not present
      Object[] elements = getArray();//获取当前数组
      int len = elements.length;
      Object[] newElements = new Object[len + 1];
      for (int i = 0; i < len; ++i) {
      if (eq(e, elements[i]))
      return false; // exit, throwing away copy 退出判断,并扔掉副本
      else
      newElements[i] = elements[i]; //当前元素不存在,则直接拷贝
      }
      newElements[len] = e; //遍历完整个数组,还是不存在则直接添加到数组末尾。
      setArray(newElements);
      return true;
      } finally {
      lock.unlock(); //最终都要释放锁
      }
      }
      注意:CopyOnWriteArraySet每次add都要遍历数组,性能要低于CopyOnWriteArrayList。

4、删除元素
public boolean remove(Object o) {
return al.remove(o);//调用CopyOnWriteArrayList的remove(Object o)方法
}

5、遍历所有元素
public Iterator<E> iterator() {
return al.iterator(); //调用CopyOnWriteArrayList的iterator方法
}

CopyOnWriteArraySet底层就是一个CopyOnWriteArrayList
CopyOnWriteArraySet在add元素的时候要遍历一遍数组,从而起到不添加重复元素的作用,但是由于要遍历数组,效率也会低于CopyOnWriteArrayList的add
Set集合没有按索引直接获取或修改或添加或删除的方法(get(int index),add(int index,E e),set(int index,E e),remove(int index))。

猜你喜欢

转载自blog.51cto.com/3265857/2317506