【集合类】HashSet & CopyOnWriteArraySet

1. HashSet

HashSet实际上是一个HashMap实例,都是一个存放链表的数组。

在这里插入图片描述

它不保证存储元素的迭代顺序;此类允许使用null元素。

HashSet中不允许有重复元素,这是因为HashSet是基于HashMap实现的,HashSet中的元素都存放在HashMap的key上面,而value中的值都是统一的一个固定对象

private static final Object PRESENT = new Object();

如下图所示,底层的map的value值都是同一个obj,map的key存储我们的hashset:
在这里插入图片描述
当迭代hashset的时候,本质就是迭代hashmap的keys:

    public Iterator<E> iterator() {
    
    
        return map.keySet().iterator();
    }

在这里插入图片描述

2. CopyOnWriteArraySet

2.1继承关系

在这里插入图片描述

它是线程安全的无序的集合,可以将它理解成线程安全的HashSet

有意思的是,CopyOnWriteArraySet和HashSet虽然都继承于共同的父类AbstractSet;但是,HashSet是通过“散列表(HashMap)”实现的,而CopyOnWriteArraySet则是通过“动态数组(CopyOnWriteArrayList)”实现的,并不是散列表。

和CopyOnWriteArrayList类似,其实CopyOnWriteSet底层包含一个CopyOnWriteList,几乎所有操作都是借助CopyOnWriteList,就像HashSet包含HashMap。

2.2. 特性

CopyOnWriteArraySet具有以下特性:

  1. 它最适合于具有以下特征的应用程序:Set 大小通常保持很小,读多写少的操作,需要在遍历期间防止线程间的冲突。
    CopyOnWriteList的适应场景就是读多写少,因为利用复制新数组模式,如果写多的话,会频繁产生复制操作,影响资源。
  2. 它是线程安全的。
    CopyOnWriteList本身是线程安全的
  3. 因为通常需要复制整个基础数组,所以可变操作(add()、set() 和 remove() 等等)的开销很大。
  4. 迭代器支持hasNext(), next()等不可变操作,但不支持可变 remove()等 操作。
  5. 使用迭代器进行遍历的速度很快,并且不会与其他线程发生冲突。在构造迭代器时,迭代器依赖于不变的数组快照。

2.3. 源码

 public boolean add(E e) {
    
    
        //这个al就是CopyOnWriteArrayList,也就是说CopyOnWriteArraySet内部是用CopyOnWriteArrayList来实现的
        return al.addIfAbsent(e);
    }

CopyOnWriteArraySet是通过CopyOnWriteArrayList实现的,它的API基本上都是通过调用CopyOnWriteArrayList的API来实现的。相信对CopyOnWriteArrayList了解的话,对CopyOnWriteArraySet的了解是水到渠成的事;所以,这里就不再对CopyOnWriteArraySet的代码进行详细的解析了

猜你喜欢

转载自blog.csdn.net/m0_45406092/article/details/114183605
今日推荐