香港色情电影,死磕 java调集之CopyOnWriteArraySet源码剖析——内含奇妙规划,大雁塔音乐喷泉

频道:微博新闻 日期: 浏览:200

问题

(1)CopyOnWriteArraySet是用Map完成的吗?

(2)CopyOnWriteArraySet是有序的吗?

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

(4)CopyOnWriteArraySet以何种办法确保元素不重复?

(5)怎样比较两个Set中的元素是否彻底一致?

简介

CopyOnWriteArraySet底层是运用CopyOnWriteArrayList存储元素的,所以它并不是运用Map来存储元素的。

可是,咱们知道CopyOnWriteArrayList底层其实是一个数组,它是答应元素重复的,那么用它来完成CopyOnWriteArraySet怎样确保元素不重复呢?

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

源码分析

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

Set之类的简略源码合适泛读,首要是把握一些不常见的用法,做到心里有说,坐个车三五分钟或许就看完了。

像ConcurrentHashMap、ConcurrentSkipListMap之类的比较长的咱们仍是倾向分析首要的办法,合适精读,首要是把握完成原理以及一些不错的思维,或许需求一两个小时才能看木香的成效与作用完一整篇文章。

public class CopyOnWriteArraySet extends AbstractSet
implements java.io.Serializable {
private static final long serialVersionUID = 5457747651344034263L;
// 内部运用CopyOnWriteArrayList存储元素
private final C北纬30度opyOnWriteArrayList al;
// 结构办法
public CopyOnWriteArraySet() {
al = new CopyOnWri香港色情电影,死磕 java集结之CopyOnWriteArraySet源码分析——内含美妙规划,大雁塔音乐喷泉teArrayList();
}

// 将集结c中的元素初始化到CopyOnWriteArraySet中
public CopyOnWrit芳华帅哥eArraySet(Collection
if (c.getClass() == CopyOnWriteArraySet.class) {
// 假如c是CopyOnWriteArraySet类型,阐明没有重复元素,
// 直接调用CopyOnWriteArrayList的结构办法初始化
@SuppressWarnings("unchecked") CopyOnWriteArraySet cc =
(CopyOnWriteArraySet)c;
al = new CopyOnWriteArrayList(cc.al);
}
else {
// 假如c不是CopyOnWriteArraySet类型,阐明有重复元素
// 调用CopyOnWriteArrayList的addAllAbsent()办法初始化
// 它会把重复元素排除去
al = new CopyOnWriteArrayList();
al.addAllAbsent(c);
}
}

// 获取元素个数
public int size() {
ret回春医疗保健操urn al.size();
}
// 查看集结是否为空
public boolean isEmpty() {
return al.isEm空手指pty();
}

// 查看是否包括某个元素
public boolean contains(Object o) {
return al.contains(o);
}
// 集结转数组
public Object[] toArray() {
return al.toArray();
}
// 集结转数组,这儿是或许有bug的,概况见ArrayList中分析
public T[] toArray(T[] a) {
return al.toArray(a);
}

// 清空一切元素
public void clear() {
al.clear();
}

// 删去元素
public boolean remove(Object o) {
return al.remove(o);
}

// 增加元素
// 这儿是调用C肚脐眼opyOnWriteArrayList的addIfAbsent()办法
// 它会检测元素不存在的时分才增加
// 还记得这个办法吗?其时有分析过的,主张把CopyOnWriteArrayList拿出来再看看
public boolean add团结便是力量(E e) {
return al.addIfAbsent(e);
}

// 是否包括c中的一切元素
public boolean containsAll(Collection
return al.containsAll(c);
}

// 并集
public boolean add香港色情电影,死磕 java集结之CopyOnWriteArraySet源码分析——内含美妙规划,大雁塔音乐喷泉All(Collection七星
return al.addAllAbsent(c) > 0;
}
// 单方向差集
public boolean removeAll(Collection
return al.removeAll(c);
}
// 交集
public boolean retainAll(Collection
return al.retainAll(c);
}

// 迭代器
public Iterator iterator() {
return al.iterator();
}

// equals()办法
public boolean equals(Object o) {
// 假如两者是同一个目标,回来true
if (o =香港色情电影,死磕 java集结之CopyOnWriteArraySet源码分析——内含美妙规划,大雁塔音乐喷泉= this)
return t塔塔杨rue;
// 假如o不是Set目标,回来false
if (!(o instanceof Set))
return false;
Set
Iterator
// 集结元素数组的快照
Object[] elements = al.getArray();
int len = e相敬如宾lements.length;

// 我觉得这儿的规划不太好
// 首要,Set中的元素原本便是不重复的,所以不需求再用个matched[]数组记载有没有呈现过
// 其次,两个集结的元素个数假如不持平,那必定不持平了,这个是不是应该作为榜首要素先查看
boolean[] matched = new boolean[len];
int k = 0;
// 从o这个集结开端遍历
outer: while (it.hasNext()) {
// 假如k>len了,阐明o中元素多了
if (++k > len)
return false;
// 香港色情电影,死磕 java集结之CopyOnWriteArraySet源码分析——内含美妙规划,大雁塔音乐喷泉取值
Object x = it.next();
// 遍历查看是否在当时集结中
for (int i = 0; i 王光美< len; ++i) {
if (!matched[i] && eq(x, elements[i])) {
matched[i] = true;
continue outer;
}
}
// 假如不在当时集结中,回来false
return false;
}
return k == len;
}
// 移除满意过滤条件的元素
public boolean removeIf(Predicate
return al.removeIf(filter);陌上花开
}
// 遍历元素
public void forEach(Consumer
al.forEach(action);
}
// 切割的迭代器
public Spliterator spliterator() {
return Spliterators.spliterator
(al.getArray(), Spliterator.IMMUTABLE | Spliterator.DISTINCT);
}

// 比较两个元素是否持平
private static boolean eq(Object o1, Object o2) {
return (o1 == null) ? o2 == null : o1.e香港色情电影,死磕 java集结之CopyOnWriteArraySet源码分析——内含美妙规划,大雁塔音乐喷泉quals(o2);
}
}

能够看到,在增加元素时调用了CopyOnWriteArrayList的addIfAbsent()办法来确保元素不重复。

还记得这个办法的完成原理吗?点击直达【死磕 java集结之CopyOnWriteArrayList源码分析】。

总结

(1)CopyOnWriteArraySet是用CopyOnWriteArrayList完成的;

(2)CopyOnWriteArraySet是有序的,由于底层其实是数组,数组是不是票房榜有序的?!

(3)CopyOnWriteArraySet是并发安全的,并且完成了读写别离;

(4)CopyOnWriteArraySet经过调用CopyOnWriteArrayList的addIfAbsent()办法来确保元素不重复;

彩蛋

(1)怎样比较两个Set中的元素是否彻底持平?

假设有两个Set,一个是A,一个是B。

最简略的办法便是判别是否A中的元素都在B中,B中的元素是否都在A中,也便是两次两层循环。

其实,并不需求。

由于Set中的元素并不重复,所以只需先比较两个Set的元素个数是否持平,再作一次两层循环就能够了,需求细心体会。代码如下:

public 香港色情电影,死磕 java集结之CopyOnWriteArraySet源码分析——内含美妙规划,大雁塔音乐喷泉class CopyOnWriteArraySe香港色情电影,死磕 java集结之CopyOnWriteArraySet源码分析——内含美妙规划,大雁塔音乐喷泉tTest {
public static void main(String[] args) {
Set set1 = new CopyOnWriteArraySet<>();
set1.add(1);
set1.add(5);
set1.add(2);
set1.add(7);
// set1.add(3);
set1.add(4);
Set set2 = new HashSet<>();
set2.add(1);
set2.add(5);
set2.add(2);
set2.add(7);
set2.add(3);
System.out.println(eq(set1, set2));
System.out.println(eq(set2,三水气候 set1));
}
private static boolean eq(Set set1, Set set2) {
if (set1.size() != set2.size()) {
return false;
}
for (T t : set1) {
// contains相当于一层for循环
if (!set2.contains(t)) {
return false;
}
}
return true;
}
}

(2)那么,怎样比较两个List中的元素是否彻底持平呢?

咱们知道,List中元素是能够重复的,那是不是要做两次两层循环呢?

其实,也不需求做两次两层遍历,一次也能够搞定,设定一个符号数组,符号某个方位的元素是否找到过,请细心体会陈抟老祖的睡功图解。代码如下:

pu墨刑blic class ListEqTest {
public static void main(String[] args) {
List list1 = new ArrayList<>();
list1.add(1);
list1.add(3);
list1.add(6);
list1.add(3);
list1.add(8);
list1.add(5);
List list2 = new ArrayList<>();
list2.add(3);
list2.add(1);
list2.add(3);
list2.add(8);
list2.add(5);
list2.add(6);
System.out.println(eq(list1,星空壁纸 楚兰菊list2));
System.out.println(eq(list2, list1));
}
private static boolean eq(List list1, List list2) {
if (list1.size() != list2.size()) {
return false;
}

// 符号某个元素是否找到过,避免重复
boolean matched[] = new boolean[list2.size()];
outer: for (T t : list1) {
for (int i = 0; i < list2.size(); i++) {
// i这个方位没找到过才比较巨细
if (!matched[i] && list2.get(i).equals(t)) {
matched[i] = true;
cont超市inue outer;
}
}
return false;
}
return true;
}
}

这种规划是不是很奇妙?^^

热门
最新
推荐
标签