死磕java集合之CopyOnWriteArraySet源码分析——内含巧妙设计

  

问题

  

(1) CopyOnWriteArraySet是用地图实现的吗?

  

(2) CopyOnWriteArraySet是有序的吗?

  

(3) CopyOnWriteArraySet是并发安全的吗?

  

(4) CopyOnWriteArraySet以何种方式保证元素不重复?

  

(5)如何比较两个组中的元素是否完全一致?

  

简介

  

CopyOnWriteArraySet底层是使用CopyOnWriteArrayList存储元素的,所以它并不是使用地图来存储元素的。

  

但是,我们知道CopyOnWriteArrayList底层其实是一个数组,它是允许元素重复的,那么用它来实现CopyOnWriteArraySet怎么保证元素不重复呢?

  

CopyOnWriteArrayList回顾请点击【死磕java集合之CopyOnWriteArrayList源码分析】。

  

源码分析

  

设置类的源码一般都比较短,所以我们直接贴源码上来一行一行分析吧。

  

设置之类的简单源码适合泛读,主要是掌握一些不常见的用法,做到心里有说,坐个车三五分钟可能就看完了。

  

像ConcurrentHashMap, ConcurrentSkipListMap之类的比较长的我们还是倾向分析主要的方法,适合精读,主要是掌握实现原理以及一些不错的思想,可能需要一两个小时才能看完一整篇文章。

  
 <代码类="语言java ">公共类CopyOnWriteArraySet扩展AbstractSet
  java实现。可序列化的{
  私有静态最终长serialVersionUID=5457747651344034263 l;//内部使用CopyOnWriteArrayList存储元素
  私人最终CopyOnWriteArrayList基地;//构造方法
  公共CopyOnWriteArraySet () {
  艾尔=new CopyOnWriteArrayList ();
  }//将集合c中的元素初始化到CopyOnWriteArraySet中
  公共CopyOnWriteArraySet (Collection<?E>延伸;c) {
  如果(c.getClass ()==CopyOnWriteArraySet.class) {//如果c是CopyOnWriteArraySet类型,说明没有重复元素,//直接调用CopyOnWriteArrayList的构造方法初始化
  @SuppressWarnings (“unchecked”) CopyOnWriteArraySetcc=(CopyOnWriteArraySet (cc.al);
  }
  其他{//如果c不是CopyOnWriteArraySet类型,说明有重复元素//调用CopyOnWriteArrayList的addAllAbsent()方法初始化//它会把重复元素排除掉
  艾尔=new CopyOnWriteArrayList ();
  al.addAllAbsent (c);
  }
  }//获取元素个数
  公共int大小(){
  返回al.size ();
  }//检查集合是否为空
  公共布尔isEmpty () {
  返回al.isEmpty ();
  }//检查是否包含某个元素
  公共逻辑包含(对象o) {
  返回al.contains (o);
  }//集合转数组
  公共对象[]toArray () {
  返回al.toArray ();
  }//集合转数组,这里是可能有错误的,详情见ArrayList中分析
  公共& lt; T>T [] toArray (T []) {
  返回al.toArray(一个);
  }//清空所有元素
  公共空间clear () {
  al.clear ();
  }//删除元素
  公共逻辑删除对象(o) {
  返回al.remove (o);
  }//添加元素//这里是调用CopyOnWriteArrayList的addIfAbsent()方法//它会检测元素不存在的时候才添加//还记得这个方法吗?当时有分析过的,建议把CopyOnWriteArrayList拿出来再看看
  公共逻辑加(E E) {
  返回al.addIfAbsent (e);
  }//是否包含c中的所有元素
  公共布尔containsAll (Collection<?比;c) {
  返回al.containsAll (c);
  }//并集
  公共布尔addAll (Collection<?E>延伸;c) {
  返回al.addAllAbsent (c)的在0;
  }//单方向差集
  公共布尔removeAll (Collection<?比;c) {
  返回al.removeAll (c);
  }//交集
  公共布尔retainAll (Collection<?比;c) {
  返回al.retainAll (c);
  }//迭代器
  公共Iteratoriterator () {
  返回al.iterator ();
  }//equals()方法
  公共布尔=(对象o) {//如果两者是同一个对象,返回现实
  如果(o==)
  返回true;//如果不啊是设置对象,返回错误的
  如果(!(o instanceof集))
  返回错误;
  Set<?比;设置=(Set<?祝辞)(o);
  Iterator<?比;它=set.iterator ();//集合元素数组的快照
  元素对象[]=al.getArray ();
  int len=elements.length;//我觉得这里的设计不太好//首先,设置中的元素本来就是不重复的,所以不需要再用个匹配[]数组记录有没有出现过//其次,两个集合的元素个数如果不相等,那肯定不相等了,这个是不是应该作为第一要素先检查
  布尔匹配[]=新布尔(len);
  int k=0;//从o这个集合开始遍历
  外:尽管(it.hasNext ()) {//如果k>兰了,说明o中元素多了
  如果(+ + k比;兰)
  返回错误;//取值
  对象x=it.next ();//遍历检查是否在当前集合中
  for (int i=0;我& lt;兰;+ + i) {
  如果(!匹配(我),,eq (x,元素[我])){
  匹配[我]=true;
  继续外;
  }
  }//如果不在当前集合中,返回错误的
  返回错误;
  }
  返回k==兰;
  }//移除满足过滤条件的元素
  公共布尔removeIf (Predicate<?超级E>过滤器){
  返回al.removeIf(过滤器);
  }//遍历元素
  公共空间forEach (Consumer<?超级E>动作){
  al.forEach(行动);
  }//分割的迭代器
  公共Spliterator

死磕java集合之CopyOnWriteArraySet源码分析——内含巧妙设计