Java容器类源码学习-TreeSet(七)

一、官方介绍

  • 基于TreeMap的NavigableSet实现。元素使用它们的自然顺序排序,或者通过在设置创建时提供的比较器进行排序,这取决于使用的是哪个构造函数。
  • 这个实现为基本操作(添加、删除和包含)提供了保证的log(n)时间开销。
  • 请注意,如果要正确实现set接口,set维护的顺序(不管是否提供显式comparator)必须与equals一致。(参见Comparable或Comparator获得与equals一致的精确定义。)这是因为Set接口是根据equals操作定义的,但是TreeSet实例使用它的compareTo(或compare)方法执行所有的元素比较,根据该方法判断两个元素是否相等。从Set的角度来看,equal。一个Set的行为是定义良好的,即使它的顺序与equals不一致;只是没有遵守Set接口的一般约定。(此段翻译很有争议,恳请指正)
  • 注意,这个实现不是同步的。如果多个线程同时访问tree set,并且至少有一个线程修改tree set,则必须在外部对tree set进行同步。这通常是通过对一些自然封装了集合的对象进行同步来实现的。如果不存在这样的对象,则应该使用集合来“包装”集合。Collections.synchronizedSortedSet方法。这最好在创建时完成,以防止意外的不同步访问Set:
SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));
  • 这个类的iterator和listIterator方法返回的迭代器是 fail-fast的:如果在创建迭代器之后的任何时候,以任何方式(除了通过迭代器自己的删除或添加方法)对列表进行结构修改,迭代器将抛出ConcurrentModificationException异常。因此,在面对并发修改时,迭代器会快速而干净地失败,而不是在将来某个不确定的时间冒任意的、不确定的行为的风险。
  • 注意,不能保证迭代器的快速故障行为,因为通常来说,在存在非同步并发修改的情况下,不可能做出任何严格的保证。Fail-fast迭代器在最大努力的基础上抛出ConcurrentModificationException。因此,编写一个依赖于这个异常的正确性的程序是错误的:迭代器的 fail-fast 行为应该只用于检测bug。
  • 该类是Java集合框架的成员

二、源码分析

大部分方法都是对TreeMap的方法的封装,详细分析还是放在treeMap吧


package java.util;

public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializable
{
    /**
     * The backing map.
     */
    private transient NavigableMap<E, Object> m;

    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();

    /**
     * Constructs a set backed by the specified navigable map.
     */
    TreeSet(NavigableMap<E, Object> m)
    {
        this.m = m;
    }

    /**
     * 构造一个新的nullTreeMap,根据其元素的自然顺序排序。所有插入到集合中的元素必须实现可比接口。此外,所有这些元素都必须相互可比
     */
    public TreeSet()
    {
        this(new TreeMap<E, Object>());
    }

    /**
     * 构造一个新的nullTreeMap,根据指定的比较器排序。所有元素插入到集合必须由指定比较器相互可比
     * 
     * @param comparator
     */
    public TreeSet(Comparator<? super E> comparator)
    {
        this(new TreeMap<>(comparator));
    }

    /**
     * 构造一个新的nullTreeMap,根据其元素的自然顺序排序。所有插入到集合中的元素必须实现可比接口。此外,所有这些元素都必须相互可比
     * 
     * @param c
     */
    public TreeSet(Collection<? extends E> c)
    {
        this();
        addAll(c);
    }

    /**
     * 构造一个包含相同元素的TreeMap,并使用与指定的已排序集相同的顺序。
     * 
     * @param s
     */
    public TreeSet(SortedSet<E> s)
    {
        this(s.comparator());
        addAll(s);
    }

    /**
     * 以升序返回此集合中元素的迭代器.
     *
     * @return an iterator over the elements in this set in ascending order
     */
    public Iterator<E> iterator()
    {
        return m.navigableKeySet().iterator();
    }

    /**
     * 按降序返回该集合中元素的迭代器。
     *
     * @return an iterator over the elements in this set in descending order
     * @since 1.6
     */
    public Iterator<E> descendingIterator()
    {
        return m.descendingKeySet().iterator();
    }

    /**
     * @since 1.6
     */
    public NavigableSet<E> descendingSet()
    {
        return new TreeSet<>(m.descendingMap());
    }

    /**
     * Returns the number of elements in this set (its cardinality).
     *
     * @return the number of elements in this set (its cardinality)
     */
    public int size()
    {
        return m.size();
    }

    /**
     * Returns {@code true} if this set contains no elements.
     *
     * @return {@code true} if this set contains no elements
     */
    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 void clear()
    {
        m.clear();
    }

    public boolean addAll(Collection<? extends E> c)
    {
        // 如果符合,使用线性时间版本 具体介绍见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);
                return true;
            }
        }
        return super.addAll(c);
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if {@code fromElement} or {@code toElement}
     *             is null and this set uses natural ordering, or its comparator
     *             does not permit null elements
     * @throws IllegalArgumentException {@inheritDoc}
     * @since 1.6
     */
    public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive)
    {
        return new TreeSet<>(m.subMap(fromElement, fromInclusive, toElement, toInclusive));
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if {@code toElement} is null and this set
     *             uses natural ordering, or its comparator does not permit null
     *             elements
     * @throws IllegalArgumentException {@inheritDoc}
     * @since 1.6
     */
    public NavigableSet<E> headSet(E toElement, boolean inclusive)
    {
        return new TreeSet<>(m.headMap(toElement, inclusive));
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if {@code fromElement} is null and this set
     *             uses natural ordering, or its comparator does not permit null
     *             elements
     * @throws IllegalArgumentException {@inheritDoc}
     * @since 1.6
     */
    public NavigableSet<E> tailSet(E fromElement, boolean inclusive)
    {
        return new TreeSet<>(m.tailMap(fromElement, inclusive));
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if {@code fromElement} or {@code toElement}
     *             is null and this set uses natural ordering, or its comparator
     *             does not permit null elements
     * @throws IllegalArgumentException {@inheritDoc}
     */
    public SortedSet<E> subSet(E fromElement, E toElement)
    {
        return subSet(fromElement, true, toElement, false);
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if {@code toElement} is null and this set
     *             uses natural ordering, or its comparator does not permit null
     *             elements
     * @throws IllegalArgumentException {@inheritDoc}
     */
    public SortedSet<E> headSet(E toElement)
    {
        return headSet(toElement, false);
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if {@code fromElement} is null and this set
     *             uses natural ordering, or its comparator does not permit null
     *             elements
     * @throws IllegalArgumentException {@inheritDoc}
     */
    public SortedSet<E> tailSet(E fromElement)
    {
        return tailSet(fromElement, true);
    }

    public Comparator<? super E> comparator()
    {
        return m.comparator();
    }

    /**
     * @throws NoSuchElementException {@inheritDoc}
     */
    public E first()
    {
        return m.firstKey();
    }

    /**
     * @throws NoSuchElementException {@inheritDoc}
     */
    public E last()
    {
        return m.lastKey();
    }

    // NavigableSet API methods

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if the specified element is null and this
     *             set uses natural ordering, or its comparator does not permit
     *             null elements
     * @since 1.6
     */
    public E lower(E e)
    {
        return m.lowerKey(e);
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if the specified element is null and this
     *             set uses natural ordering, or its comparator does not permit
     *             null elements
     * @since 1.6
     */
    public E floor(E e)
    {
        return m.floorKey(e);
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if the specified element is null and this
     *             set uses natural ordering, or its comparator does not permit
     *             null elements
     * @since 1.6
     */
    public E ceiling(E e)
    {
        return m.ceilingKey(e);
    }

    /**
     * @throws ClassCastException {@inheritDoc}
     * @throws NullPointerException if the specified element is null and this
     *             set uses natural ordering, or its comparator does not permit
     *             null elements
     * @since 1.6
     */
    public E higher(E e)
    {
        return m.higherKey(e);
    }

    /**
     * @since 1.6
     */
    public E pollFirst()
    {
        Map.Entry<E, ?> e = m.pollFirstEntry();
        return (e == null) ? null : e.getKey();
    }

    /**
     * @since 1.6
     */
    public E pollLast()
    {
        Map.Entry<E, ?> e = m.pollLastEntry();
        return (e == null) ? null : e.getKey();
    }

    /**
     * Returns a shallow copy of this {@code TreeSet} instance. (The elements
     * themselves are not cloned.)
     *
     * @return a shallow copy of this set
     */
    @SuppressWarnings ("unchecked")
    public Object clone()
    {
        TreeSet<E> clone;
        try
        {
            clone = (TreeSet<E>)super.clone();
        }
        catch (CloneNotSupportedException e)
        {
            throw new InternalError(e);
        }

        clone.m = new TreeMap<>(m);
        return clone;
    }

    /**
     * Save the state of the {@code TreeSet} instance to a stream (that is,
     * serialize it).
     *
     * @serialData Emits the comparator used to order this set, or {@code null}
     *             if it obeys its elements' natural ordering (Object), followed
     *             by the size of the set (the number of elements it contains)
     *             (int), followed by all of its elements (each an Object) in
     *             order (as determined by the set's Comparator, or by the
     *             elements' natural ordering if the set has no Comparator).
     */
    private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException
    {
        // Write out any hidden stuff
        s.defaultWriteObject();

        // Write out Comparator
        s.writeObject(m.comparator());

        // Write out size
        s.writeInt(m.size());

        // Write out all elements in the proper order.
        for (E e : m.keySet())
            s.writeObject(e);
    }

    /**
     * Reconstitute the {@code TreeSet} instance from a stream (that is,
     * deserialize it).
     */
    private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException
    {
        // Read in any hidden stuff
        s.defaultReadObject();

        // Read in Comparator
        @SuppressWarnings ("unchecked")
        Comparator<? super E> c = (Comparator<? super E>)s.readObject();

        // Create backing TreeMap
        TreeMap<E, Object> tm = new TreeMap<>(c);
        m = tm;

        // Read in size
        int size = s.readInt();

        tm.readTreeSet(size, s, PRESENT);
    }

    /**
     * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em>
     * and <em>fail-fast</em> {@link Spliterator} over the elements in this set.
     * <p>
     * The {@code Spliterator} reports {@link Spliterator#SIZED},
     * {@link Spliterator#DISTINCT}, {@link Spliterator#SORTED}, and
     * {@link Spliterator#ORDERED}. Overriding implementations should document
     * the reporting of additional characteristic values.
     * <p>
     * The spliterator's comparator (see
     * {@link java.util.Spliterator#getComparator()}) is {@code null} if the
     * tree set's comparator (see {@link #comparator()}) is {@code null}.
     * Otherwise, the spliterator's comparator is the same as or imposes the
     * same total ordering as the tree set's comparator.
     *
     * @return a {@code Spliterator} over the elements in this set
     * @since 1.8
     */
    public Spliterator<E> spliterator()
    {
        return TreeMap.keySpliteratorFor(m);
    }

    private static final long serialVersionUID = -2479143000061671589L;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值