问题
(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”) CopyOnWriteArraySet cc=(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); }//迭代器 公共Iterator iterator () { 返回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源码分析——内含巧妙设计