Java(Android)数据结构汇总(二)-- Set(下)

传送门:Java(Android)数据结构汇总 -- 总纲

简介

Setjava.util.concurrent包下的主要有CopyOnWriteArraySetConcurrentSkipListSet两个实现类。

一、CopyOnWriteArraySet

上一章讲了HashSet是一个无序的、元素不重复的、线程不安全的集合,CopyOnWriteArraySet在此基础上实现了线程安全。也就是说它是一个无序的、元素不重复的、线程安全的集合。

CopyOnWriteArraySet内部使用的是CopyOnWriteArrayList来实现的(HashSet内部是使用HashMap来实现的),对CopyOnWriteArrayList不熟悉的可以看前面的章节。源码如下:

public class CopyOnWriteArraySet<E> extends AbstractSet<E>
        implements java.io.Serializable {

    // 使用一个CopyOnWriteArrayList来存放元素
    private final CopyOnWriteArrayList<E> al;

    public CopyOnWriteArraySet() {
        al = new CopyOnWriteArrayList<E>();
    }

    public boolean add(E e) {
        // 注意这里调用的是CopyOnWriteArrayList的addIfAbsent方法,这个方法保证了元素的唯一性,
        // 从而保证了CopyOnWriteArraySet的元素不重复
        return al.addIfAbsent(e);
    }
}

我们再来看看CopyOnWriteArrayList的addIfAbsent()方法:

public boolean addIfAbsent(E e) {
    // 内部数组
    Object[] snapshot = getArray();

    // indexOf方法用于在这个数组中查找要插入的元素,
    // 如果找到了就返回false,否则调用addIfAbsent(e, snapshot)来进行插入操作
    return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false : addIfAbsent(e, snapshot);
}

private boolean addIfAbsent(E e, Object[] snapshot) {
    // 前面我们讲了,CopyOnWriteArrayList在修改数据的时候要加锁同步
    synchronized (lock) {
        Object[] current = getArray();
        int len = current.length;
        // 判断数组长度是否发生了变化
        if (snapshot != current) {
            // Optimize for lost race to another addXXX operation
            int common = Math.min(snapshot.length, len);
            for (int i = 0; i < common; i++)
                if (current[i] != snapshot[i] && Objects.equals(e, current[i]))
                    return false;
            if (indexOf(e, current, common, len) >= 0)
                    return false;
        }
        Object[] newElements = Arrays.copyOf(current, len + 1);
        newElements[len] = e;
        setArray(newElements);
        return true;
    }
}

可见,CopyOnWriteArraySet还是非常简单的,这里就不多讲。

二、ConcurrentSkipListSet

上一章讲了TreeSet,它是一个有序的、元素不重复的、线程不安全的集合。ConcurrentSkipListSet在此基础上增加了线程安全。也就是说它是一个有序的、元素不重复的、线程安全的集合。

ConcurrentSkipListSet内部使用的是ConcurrentSkipListMap来实现的(TreeSet内部使用的TreeMap实现)。对ConcurrentSkipListMap不清楚的可以看第四章对Map的介绍。除了上面这些特点之外,其他的和TreeSet一样。

总结

内部实现 元素是否重复 元素是否有序 线程安全否 备注
HashSet HashMap 不重复 无序 -
TreeSet TreeMap 不重复 有序 -
ArraySet 数组 不重复 无序 HashSet的内存优化版本
CopyOnWriteArraySet CopyOnWriteArrayList 不重复 无序 HashSet的线程安全版本
ConcurrentSkipListSet ConcurrentSkipListMap 不重复 有序 TreeSet的线程安全版本

推荐阅读更多精彩内容

  • pdf下载地址:Java面试宝典 第一章内容介绍 20 第二章JavaSE基础 21 一、Java面向对象 21 ...
    王震阳阅读 77,486评论 25 510
  • Java要点2 JAVA 集合类 1.JAVA常用集合类功能、区别和性能 两大类:Collections,Map;...
    Charle_Lin阅读 46评论 0 0
  • 上一篇文章介绍了Set集合的通用知识。Set集合中包含了三个比较重要的实现类:HashSet、TreeSet和En...
    Ruheng阅读 9,345评论 1 50
  • java笔记第一天 == 和 equals ==比较的比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量...
    jmychou阅读 538评论 0 2
  • 明明你自己考试得了77分,觉得挺满意的,然而你看到班上的同学个个都是八十多分,那你就不会开心起来了。与其说是为了让...
    烟雨萧萧阅读 38评论 0 0