Java集合容器系列09 - TreeSet

1、TreeSet介绍

    TreeMap是底层基于TreeMap的NavigableSet实现,容器的元素存储在TreeMap键值对映射的key中,它使用元素的天然顺序或者传入的比较器Comparator对元素进行排序。它为基本操做例如add、remove、contain提供了log(n)的时间复杂度保证。注意TreeSet不是线程同步的容器,若是有多个线程同时访问它,且至少有一个线程修改了容器的结构,那么他必须在外部进行同步处理。通常都是经过对天然封装该Set实例的对象进行同步操做来完成,若是没有这样的对象,那么可使用Collections.synChronizedSortedSet包装TreeSet为一个线程安全的容器。java

    该TreeSet容器返回的迭代器是快速失败的(fail-fast),即在生成迭代器以后,若是该容器发生告终构部性修改除了经过迭代iterator.remove方法删除元素以外,迭代器将会抛出ConcurrentModificationException异常,该异常并不能绝对保证,应该只用于检测异常。安全

 

2、TreeSet数据结构

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable
{
    /** 内部TreeMap实例 **/
    private transient NavigableMap<E,Object> m;

    //静态对象充当TreeMap实例中的键值对中的value,全部key的value都是该对象
    private static final Object PRESENT = new Object();

}

    TreeSet继承自AbstractSet,AbstractSet提供了Set的一些基本方法实现,大大减小实现TreeSet的工做量,此外它实现了NavigableSet接口,扩展了倒序、获取给定目标最接近匹配等功能,实现了Clonable支持克隆、java.io.Serializable支持序列化数据结构

3、TreeSet的源码分析

1 - 构造函数

/**
     * 构造方法,指定NavigableMap实例
     */
    TreeSet(NavigableMap<E,Object> m) {
        this.m = m;
    }

    /**
     * 无参构造方法,默认建立一个TreeMap实例
     */
    public TreeSet() {
        this(new TreeMap<E,Object>());
    }

    /**
     * 构造方法,建立一个空的TreeMap实例并按照方法指定的比较器对元素进行排序
     */
    public TreeSet(Comparator<? super E> comparator) {
        this(new TreeMap<>(comparator));
    }

    /**
     * 构造方法,建立一个空的TreeSet实例,并将方法指定集合c的全部元素填充到TreeSet实例中
     */
    public TreeSet(Collection<? extends E> c) {
        this();
        addAll(c);
    }

    /**
     * 构造方法,建立一个空的TreeSet实例,比较器取方法参数SortedSet对象的s的内部比较器,
     * 将容器s中的全部元素填充到内部TreeMap实例
     */
    public TreeSet(SortedSet<E> s) {
        this(s.comparator());
        addAll(s);
    }

    经过对TreeSet构造函数的分析,咱们能够了解到TreeSet的底层与HashSet相似,只不过它的底层存储结构是一个NavagableMap实例,通常是TreeMap对象,全部TreeSet的操做最终都是反映到底层对TreeMap的操做。函数

2 - 其余成员方法

/**
     * 返回一个遍历当前容器元素的迭代器
     */
    public Iterator<E> iterator() {
        return m.navigableKeySet().iterator();
    }

    /**
     * 判断当前容器是否为空
     */
    public boolean isEmpty() {
        return m.isEmpty();
    }

    /**
     * 返回当前容器是否包含指定元素
     */
    public boolean contains(Object o) {
        return m.containsKey(o);
    }

    /**
     * 添加元素
     */
    public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }

    /**
     * 删除元素
     */
    public boolean remove(Object o) {
        return m.remove(o)==PRESENT;
    }

    /**
     * 获取容器第一个元素
     */
    public E first() {
        return m.firstKey();
    }

    /**
     * 获取容器最后一个元素
     */
    public E last() {
        return m.lastKey();
    }

    经过对TreeSet成员方法的分析,咱们能够发现它们的实现彻底依赖于底层的NavigableMap实例(通常状况下能够简单视为TreeMap实例),容器元素对应的是TreeMap实例键值对的Key,若想研读底层实现能够直接去研读TreeMap响应方法的源码。源码分析

相关文章
相关标签/搜索