集合之TreeSet(含JDK1.8源码分析)

一、前言

  前面分析了Set接口下的hashSet和linkedHashSet,下面接着来看treeSet,treeSet的底层实现是基于treeMap的。

  四个关注点在treeSet上的答案

二、treeSet的数据结构

  因为treeSet的底层是基于treeMap的,所以treeSet的数据结构就是treeMap的数据结构:红黑树,因为前面已经分析过了treeMap的数据结构,这里不再赘述。集合之TreeMap(含JDK1.8源码分析)

三、treeSet源码分析-属性及构造函数

  3.1 类的继承关系

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable

  说明:实现了NavigableSet接口,定义了一些共有的操作。

  3.2 类的属性

/**
     * 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();

    //版本号
    private static final long serialVersionUID = -2479143000061671589L;

  说明:属性m为NavigableMap接口,treeSet的一些操作都是基于此map的,而前面分析treeMap的时候,发现treeMap实现了NavigableMap接口,所以hashSet中基于NavigableMap接口的操作实际上都是基于其实现类treeMap的操作,此处也是多态的概念。

  treeMap的继承实现关系:

public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable

  而对于Object类型的属性PRESENT,在分析hashSet的时候已经做了说明,因为map(treeSet中是NavigableMap)是存储key-value键值对的,所以PRESENT只是配一下key-value中value的位置,起个占位的作用,没有什么实际的意义,所有通过treeSet添加进来的key都对应同一个value值,PRESENT。

  3.3 类的构造函数

  1、TreeSet(NavigableMap<E,Object> m)型

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

  说明:构建一个treeSet,基于navigable map(其实现类treeMap)实现的。

  2、TreeSet()型

/**
     * Constructs a new, empty tree set, sorted according to the
     * natural ordering of its elements.  All elements inserted into
     * the set must implement the {@link Comparable} interface.
     * Furthermore, all such elements must be <i>mutually
     * comparable</i>: {@code e1.compareTo(e2)} must not throw a
     * {@code ClassCastException} for any elements {@code e1} and
     * {@code e2} in the set.  If the user attempts to add an element
     * to the set that violates this constraint (for example, the user
     * attempts to add a string element to a set whose elements are
     * integers), the {@code add} call will throw a
     * {@code ClassCastException}.
     */
    public TreeSet() {
        this(new TreeMap<E,Object>());
    }

  说明:构建一个treeSet,排序是基于插入元素的自然顺序。

  3、TreeSet(Comparator<? super E> comparator)型

/**
     * Constructs a new, empty tree set, sorted according to the specified
     * comparator.  All elements inserted into the set must be <i>mutually
     * comparable</i> by the specified comparator: {@code comparator.compare(e1,
     * e2)} must not throw a {@code ClassCastException} for any elements
     * {@code e1} and {@code e2} in the set.  If the user attempts to add
     * an element to the set that violates this constraint, the
     * {@code add} call will throw a {@code ClassCastException}.
     *
     * @param comparator the comparator that will be used to order this set.
     *        If {@code null}, the {@linkplain Comparable natural
     *        ordering} of the elements will be used.
     */
    public TreeSet(Comparator<? super E> comparator) {
        this(new TreeMap<>(comparator));
    }

  说明:构建一个treeSet,排序是基于自定义的比较器的排序规则。

  4、TreeSet(Collection<? extends E> c)型

/**
     * Constructs a new tree set containing the elements in the specified
     * collection, sorted according to the <i>natural ordering</i> of its
     * elements.  All elements inserted into the set must implement the
     * {@link Comparable} interface.  Furthermore, all such elements must be
     * <i>mutually comparable</i>: {@code e1.compareTo(e2)} must not throw a
     * {@code ClassCastException} for any elements {@code e1} and
     * {@code e2} in the set.
     *
     * @param c collection whose elements will comprise the new set
     * @throws ClassCastException if the elements in {@code c} are
     *         not {@link Comparable}, or are not mutually comparable
     * @throws NullPointerException if the specified collection is null
     */
    public TreeSet(Collection<? extends E> c) {
        this();
        addAll(c);
    }

  说明:构建一个treeSet,包含参数c中的元素,排序是基于元素的自然顺序。

  5、TreeSet(SortedSet<E> s)型

/**
     * Constructs a new tree set containing the same elements and
     * using the same ordering as the specified sorted set.
     *
     * @param s sorted set whose elements will comprise the new set
     * @throws NullPointerException if the specified sorted set is null
     */
    public TreeSet(SortedSet<E> s) {
        this(s.comparator());
        addAll(s);
    }

  说明:构建一个treeSet,排序是基于SortedSet指定的排序规则。

四、treeSet源码分析-核心函数

  4.1 增:add函数----存储元素

/**
     * Adds the specified element to this set if it is not already present.
     * More formally, adds the specified element {@code e} to this set if
     * the set contains no element {@code e2} such that
     * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
     * If this set already contains the element, the call leaves the set
     * unchanged and returns {@code false}.
     *
     * @param e element to be added to this set
     * @return {@code true} if this set did not already contain the specified
     *         element
     * @throws ClassCastException if the specified object cannot be compared
     *         with the elements currently in this set
     * @throws NullPointerException if the specified element is null
     *         and this set uses natural ordering, or its comparator
     *         does not permit null elements
     */
    public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }

  说明:添加一个原先set中未存在的元素,返回true,若是该元素已经存在,set不做改变,返回false。

  可以看到其方法内部调用navigableMap的put方法,因为treeMap是其实现类,所以实际执行的时候,调用的是treeMap的put方法。可参见:集合之TreeMap(含JDK1.8源码分析)

  4.2 增:remove函数----删除元素

/**
     * Removes the specified element from this set if it is present.
     * More formally, removes an element {@code e} such that
     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>,
     * if this set contains such an element.  Returns {@code true} if
     * this set contained the element (or equivalently, if this set
     * changed as a result of the call).  (This set will not contain the
     * element once the call returns.)
     *
     * @param o object to be removed from this set, if present
     * @return {@code true} if this set contained the specified element
     * @throws ClassCastException if the specified object cannot be compared
     *         with the elements currently in this set
     * @throws NullPointerException if the specified element is null
     *         and this set uses natural ordering, or its comparator
     *         does not permit null elements
     */
    public boolean remove(Object o) {
        return m.remove(o)==PRESENT;
    }

  说明:若set中存在要删除的元素,删除,返回true,不存在,返回false。

  可以看到其方法内部调用navigableMap的remove方法,因为treeMap是其实现类,所以实际执行的时候,调用的是treeMap的remove方法。可参见:集合之TreeMap(含JDK1.8源码分析)

  4.3 contains函数----是否存在该元素

/**
     * Returns {@code true} if this set contains the specified element.
     * More formally, returns {@code true} if and only if this set
     * contains an element {@code e} such that
     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
     *
     * @param o object to be checked for containment in this set
     * @return {@code true} if this set contains the specified element
     * @throws ClassCastException if the specified object cannot be compared
     *         with the elements currently in the set
     * @throws NullPointerException if the specified element is null
     *         and this set uses natural ordering, or its comparator
     *         does not permit null elements
     */
    public boolean contains(Object o) {
        return m.containsKey(o);
    }

  说明:若set中存在该元素,返回true,不存在,返回false。

  可以看到其方法内部调用navigableMap的containsKey方法,因为treeMap是其实现类,所以实际执行的时候,调用的是treeMap的containsKey方法。

五、总结

  总之,treeSet底层是基于treeMap实现的,可以自定义比较器对元素进行排序,或是使用元素的自然顺序。

原文地址:https://www.cnblogs.com/zfyang2429/p/10457895.html

时间: 2024-10-20 18:43:15

集合之TreeSet(含JDK1.8源码分析)的相关文章

集合之HashSet(含JDK1.8源码分析)

一.前言 我们已经分析了List接口下的ArrayList和LinkedList,以及Map接口下的HashMap.LinkedHashMap.TreeMap,接下来看的是Set接口下HashSet和LinkedHashSet,其实在分析完了HashMap.LinkedHashMap之后,再来看HashSet和LinkedHashSet就会非常简单. 二.hashSet的数据结构 因为hashSet的底层是基于hashMap或linkedHashMap的(new hashSet的时候可以指定),

集合之LinkedHashSet(含JDK1.8源码分析)

一.前言 上篇已经分析了Set接口下HashSet,我们发现其操作都是基于hashMap的,接下来看LinkedHashSet,其底层实现都是基于linkedHashMap的. 二.linkedHashSet的数据结构 因为linkedHashSet的底层是基于linkedHashMap实现的,所以linkedHashSet的数据结构就是linkedHashMap的数据结构,因为前面已经分析过了linkedHashMap的数据结构,这里不再赘述.集合之LinkedHashMap(含JDK1.8源

集合之LinkedList(含JDK1.8源码分析)

LinkedList的数据结构 LinkedList的增删改查 增:add 说明:add函数用于向LinkedList中添加一个元素,并且添加到链表尾部.具体添加到尾部的逻辑是由linkLast函数完成的. 举例: public class Test { public static void main(String[] args) { List<String> list = new LinkedList<>(); list.add("zhangsan"); li

【集合框架】JDK1.8源码分析之Collections &amp;&amp; Arrays(十)

一.前言 整个集合框架的常用类我们已经分析完成了,但是还有两个工具类我们还没有进行分析.可以说,这两个工具类对于我们操作集合时相当有用,下面进行分析. 二.Collections源码分析 2.1 类的属性   2.2 构造函数 private Collections() { } 说明:私有构造函数,在类外无法调用. 2.3 方法分析 下面是Collections的所有方法. 可以看到,Collections的方法包含了各种各样的操作.下面分析最常用的方法. 1. sort函数 该函数有两个重载函

【集合框架】JDK1.8源码分析之Collections &amp;&amp; Arrays

一.前言 整个集合框架的常用类我们已经分析完成了,但是还有两个工具类我们还没有进行分析.可以说,这两个工具类对于我们操作集合时相当有用,下面进行分析. 二.Collections源码分析 2.1 类的属性 public class Collections { // 二分查找阈值 private static final int BINARYSEARCH_THRESHOLD = 5000; // 反向阈值 private static final int REVERSE_THRESHOLD = 1

【集合框架】JDK1.8源码分析之HashMap(一) 转载

一.前言 在分析jdk1.8后的HashMap源码时,发现网上好多分析都是基于之前的jdk,而Java8的HashMap对之前做了较大的优化,其中最重要的一个优化就是桶中的元素不再唯一按照链表组合,也可以使用红黑树进行存储,总之,目标只有一个,那就是在安全和功能性完备的情况下让其速度更快,提升性能.好~下面就开始分析源码. 二.HashMap数据结构 说明:上图很形象的展示了HashMap的数据结构(数组+链表+红黑树),桶中的结构可能是链表,也可能是红黑树,红黑树的引入是为了提高效率.所以可见

【JUC】JDK1.8源码分析之ConcurrentHashMap(一)

一.前言 最近几天忙着做点别的东西,今天终于有时间分析源码了,看源码感觉很爽,并且发现ConcurrentHashMap在JDK1.8版本与之前的版本在并发控制上存在很大的差别,很有必要进行认真的分析,下面进行源码分析. 二.ConcurrentHashMap数据结构 之前已经提及过,ConcurrentHashMap相比HashMap而言,是多线程安全的,其底层数据与HashMap的数据结构相同,数据结构如下 说明:ConcurrentHashMap的数据结构(数组+链表+红黑树),桶中的结构

【JUC】JDK1.8源码分析之SynchronousQueue(九)

一.前言 本篇是在分析Executors源码时,发现JUC集合框架中的一个重要类没有分析,SynchronousQueue,该类在线程池中的作用是非常明显的,所以很有必要单独拿出来分析一番,这对于之后理解线程池有很有好处,SynchronousQueue是一种阻塞队列,其中每个插入操作必须等待另一个线程的对应移除操作 ,反之亦然.同步队列没有任何内部容量,甚至连一个队列的容量都没有. 二.SynchronousQueue数据结构 由于SynchronousQueue的支持公平策略和非公平策略,所

【JUC】JDK1.8源码分析之ConcurrentHashMap

一.前言 最近几天忙着做点别的东西,今天终于有时间分析源码了,看源码感觉很爽,并且发现ConcurrentHashMap在JDK1.8版本与之前的版本在并发控制上存在很大的差别,很有必要进行认真的分析,下面进行源码分析. 二.ConcurrentHashMap数据结构 之前已经提及过,ConcurrentHashMap相比HashMap而言,是多线程安全的,其底层数据与HashMap的数据结构相同,数据结构如下 说明:ConcurrentHashMap的数据结构(数组+链表+红黑树),桶中的结构