Jdk源码分析

文章40 |   阅读 14790 |   点赞0

来源:https://yumbo.blog.csdn.net/category_10384063.html

简化 java.util.concurrent.CopyOnWriteArraySet 源码并总结知识点

x33g5p2x  于2021-12-18 转载在 其他  
字(3.2k)|赞(0)|评价(0)|浏览(398)

通过查看源码会发现CopyOnWriteArraySet 底层用的是CopyOnWriteArrayList

因此我们需要借鉴CopyOnWriteArrayList的源码

资料:
简化 java.util.concurrent.CopyOnWriteArrayList 源码并总结知识点

会发现CopyOnWriteArraySet会比CopyOnWriteArrayList代码量少一些,因为本质就是给CopyOnWriteArrayList套了一层壳。
这里我们需要思考的问题是Set是一个元素不重复的集合,那么CopyOnWriteArraySet是如果包装不重复元素?

我们都知道HashSet 他是利用HashMap作为底层支撑。
HashSet中的元素都存在HashMap的key中,而key则会通过hash算法得到hash值,再通过无符号右移按位与操作得到索引将元素存入HashMap的key中,而value则是一个常量对象new Object()得到。同时也存在扩容,扩容因子是0.75,扩容条件是容量*0.75。扩容规律是2倍原容量。

public class CopyOnWriteArraySet<E> extends AbstractSet<E> implements java.io.Serializable {
    private static final long serialVersionUID = 5457747651344034263L;

    private final java.util.concurrent.CopyOnWriteArrayList<E> al;

    /** * 空的set集合,底层是new了一个CopyOnWriteArrayList对象 */
    public CopyOnWriteArraySet() {
        al = new CopyOnWriteArrayList<E>();
    }

    /** * 带集合的方式创建一个Set集合 */
    public CopyOnWriteArraySet(Collection<? extends E> c) {
        if (c.getClass() == CopyOnWriteArraySet.class) {
            @SuppressWarnings("unchecked") CopyOnWriteArraySet<E> cc =
                (CopyOnWriteArraySet<E>)c;
            al = new java.util.concurrent.CopyOnWriteArrayList<E>(cc.al);
        }
        else {
            al = new CopyOnWriteArrayList<E>();
            al.addAllAbsent(c);
        }
    }

    /** * 返回元素个数 */
    public int size() {
        return al.size();
    }

    /** * 判空 */
    public boolean isEmpty() {
        return al.isEmpty();
    }

    /** * 是否包含元素o,底层用元素o的equals方法做比较 */
    public boolean contains(Object o) {
        return al.contains(o);
    }

    /** * 转换成数组 */
    public Object[] toArray() {
        return al.toArray();
    }

    /** * 转换成带泛型的数组 */
    public <T> T[] toArray(T[] a) {
        return al.toArray(a);
    }

    /** * 清空集合 */
    public void clear() {
        al.clear();
    }

    /** * 移除元素o */
    public boolean remove(Object o) {
        return al.remove(o);
    }

    /** * 添加元素o */
    public boolean add(E e) {
        return al.addIfAbsent(e);
    }

    /** * c中所有元素是否独占集合中 */
    public boolean containsAll(Collection<?> c) {
        return (c instanceof Set)
            ? compareSets(al.getArray(), (Set<?>) c) >= 0
            : al.containsAll(c);
    }

    

    /** * 添加索引元素 */
    public boolean addAll(Collection<? extends E> c) {
        return al.addAllAbsent(c) > 0;
    }

    /** * 求 A - A交B,A中保留B没有的元素 */
    public boolean removeAll(Collection<?> c) {
        return al.removeAll(c);
    }

    /** * 求交集 set集合和c的交集 */
    public boolean retainAll(Collection<?> c) {
        return al.retainAll(c);
    }

    /** * 获取迭代器 */
    public Iterator<E> iterator() {
        return al.iterator();
    }

    /** * 两集合是否相等 */
    public boolean equals(Object o) {
        return (o == this)
            || ((o instanceof Set)
                && compareSets(al.getArray(), (Set<?>) o) == 0);
    }

    /** * 断言型接口 */
    public boolean removeIf(Predicate<? super E> filter) {
        return al.removeIf(filter);
    }

    /** * java8的forEach循环 */
    public void forEach(Consumer<? super E> action) {
        al.forEach(action);
    }

    /** * 并行迭代器 */
    public Spliterator<E> spliterator() {
        return Spliterators.spliterator
            (al.getArray(), Spliterator.IMMUTABLE | Spliterator.DISTINCT);
    }
    /** 私有方法 * 比较两集合 */
    private static int compareSets(Object[] snapshot, Set<?> set) {
        // Uses O(n^2) algorithm, that is only appropriate for small
        // sets, which CopyOnWriteArraySets should be.
        //
        // Optimize up to O(n) if the two sets share a long common prefix,
        // as might happen if one set was created as a copy of the other set.

        final int len = snapshot.length;
        // Mark matched elements to avoid re-checking
        final boolean[] matched = new boolean[len];

        // j is the largest int with matched[i] true for { i | 0 <= i < j }
        int j = 0;
        outer: for (Object x : set) {
            for (int i = j; i < len; i++) {
                if (!matched[i] && Objects.equals(x, snapshot[i])) {
                    matched[i] = true;
                    if (i == j)
                        do { j++; } while (j < len && matched[j]);
                    continue outer;
                }
            }
            return -1;
        }
        return (j == len) ? 0 : 1;
    }
}

相关文章