zoukankan      html  css  js  c++  java
  • Collection容器家族(TreeSet源码详解)

    一、在Collection集合体系中的位置及概述 

            TreeSet继承自AbstractSet抽象类,实现了NavigableSet、Serializable、Cloneable、RandomAccess接口。它的特点是存储元素唯一,无序(输入和输出无序)。 TreeSet默认情况下是基于TreeMap实现的,是对TreeMap的封装。默认情况下和TreeMap一样,采用元素的内部比较器Comparable的compareTo方法来比较元素的大小。如果不用内部比较器,就需要在外部传入一个Comparator的实现类来比较。由于TreeMap实现中采用红黑树实现,所以add,remove,contains方法的时间复杂度最坏情况下能保证log( n )。

    二、成员变量

        // 存放元素的Map,必须是实现了NavigableMap接口的类
        private transient NavigableMap<E,Object> m;
    
        // Dummy value to associate with an Object in the backing Map
        // 一个虚拟值,用于添加元素到map中时,key为元素的值,value用此虚拟值代替
        private static final Object PRESENT = new Object();

    三、构造方法

        // 自定义实现了NavigableMap接口的Map来作为实现
        TreeSet(NavigableMap<E,Object> m) {
            this.m = m;
        }
    
        // 默认构造方法用TreeMap来实现
        public TreeSet() {
            this(new TreeMap<E,Object>());
        }
    
        // 以定制排序方式创建一个新的 TreeMap,
        // 根据该 TreeSet 创建一个 TreeSet,
        // 使用该 TreeMap 的 key 来保存 Set 集合的元素
        public TreeSet(Comparator<? super E> comparator) {
            this(new TreeMap<>(comparator));
        }
    
        //使用参数集合的元素构造本集合
        public TreeSet(Collection<? extends E> c) {
            // 无参构造器创建一个TreeSet,底层以TreeMap保存集合元素
            this();
            // 向TreeSet中添加Collection集合c里的所有元素
            addAll(c);
        }
    
        public TreeSet(SortedSet<E> s) {
            // 调用带比较器参数的构造器创建衣蛾TreeSet,底层以TreeMap保存集合元素
            this(s.comparator());
            // 向TreeSet中添加SortedSet集合s里的所有元素
            addAll(s);
        }

    其中涉及到addAll方法

        // 将参数集合中所有元素添加到本集合中
        public  boolean addAll(Collection<? extends E> c) {
            // Use linear-time version if applicable
            // 条件:本集合为空、参数集合有元素、参数集合是SortedSet类型、m是TreeMap类型
            if (m.size()==0 && c.size() > 0 &&
                c instanceof SortedSet &&
                m instanceof TreeMap) {
                SortedSet<? extends E> set = (SortedSet<? extends E>) c;
                TreeMap<E,Object> map = (TreeMap<E, Object>) m;
                Comparator<?> cc = set.comparator();    // 获取比较器
                Comparator<? super E> mc = map.comparator();    // 获取比较器
                if (cc==mc || (cc != null && cc.equals(mc))) {  // 如果本集合比较器和参数集合比较器相同
                    map.addAllForTreeSet(set, PRESENT); // 使用TreeMap的addAllForTreeSet方法将参数集合所有元素添加到本集合
                    return true;
                }
            }
            return super.addAll(c); // 不满足上诉条件,则调用AbstractCollection超类的addAll方法添加
        }

    其中涉及到TreeMap的addAllForTreeSet方法,查看我之前的博客。

    四、常用API

    1.添加元素

        // 添加元素
        public boolean add(E e) {
            // 调用TreeMap的put方法添加
            return m.put(e, PRESENT)==null;
        }
    
        // 将参数集合中所有元素添加到本集合中
        public  boolean addAll(Collection<? extends E> c) {
            // Use linear-time version if applicable
            // 条件:本集合为空、参数集合有元素、参数集合是SortedSet类型、m是TreeMap类型
            if (m.size()==0 && c.size() > 0 &&
                c instanceof SortedSet &&
                m instanceof TreeMap) {
                SortedSet<? extends E> set = (SortedSet<? extends E>) c;
                TreeMap<E,Object> map = (TreeMap<E, Object>) m;
                Comparator<?> cc = set.comparator();    // 获取比较器
                Comparator<? super E> mc = map.comparator();    // 获取比较器
                if (cc==mc || (cc != null && cc.equals(mc))) {  // 如果本集合比较器和参数集合比较器相同
                    map.addAllForTreeSet(set, PRESENT); // 使用TreeMap的addAllForTreeSet方法将参数集合所有元素添加到本集合
                    return true;
                }
            }
            return super.addAll(c); // 不满足上诉条件,则调用AbstractCollection超类的addAll方法添加
        }

    2.删除元素

        // 清空集合所有元素
        public void clear() {
            // 调用TreeMap方法清除
            m.clear();
        }
    
        // 移除参数元素
        public boolean remove(Object o) {
            // 调用TreeMap方法清除
            return m.remove(o)==PRESENT;
        }

    3.遍历操作

        public Iterator<E> iterator() {
            // 调用TreeMap方法清除
            return m.navigableKeySet().iterator();
        }

    五、总结

            TreeSet原码中方法比较少,原因是因为他是TreeMap的封装类对象。提的的就不在此赘述了。

  • 相关阅读:
    原生js实现 table表格列宽拖拽
    vue.js 利用SocketCluster实现动态添加数据及排序
    angular-websocket.js 使用
    判断当前页面是否是激活状态。
    remove ---会报错discard不会报错
    .pop ----remove 删除
    add添加
    #将相同值输出,取一个值
    集合
    __delattr__\__delitem__
  • 原文地址:https://www.cnblogs.com/IdealSpring/p/11871181.html
Copyright © 2011-2022 走看看