zoukankan      html  css  js  c++  java
  • Java 集合系列 17 TreeSet

    java 集合系列目录:

    Java 集合系列 01 总体框架

    Java 集合系列 02 Collection架构

    Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例

    Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例 

    Java 集合系列 05 Vector详细介绍(源码解析)和使用示例

    Java 集合系列 06 Stack详细介绍(源码解析)和使用示例

    Java 集合系列 07 List总结(LinkedList, ArrayList等使用场景和性能分析)

    Java 集合系列 08 Map架构

    Java 集合系列 09 HashMap详细介绍(源码解析)和使用示例

    Java 集合系列 10 Hashtable详细介绍(源码解析)和使用示例

    Java 集合系列 11 hashmap 和 hashtable 的区别

    Java 集合系列 12 TreeMap

    Java 集合系列 13 WeakHashMap

    Java 集合系列 14 hashCode

    Java 集合系列 15 Map总结

    Java 集合系列 16 HashSet

    Java 集合系列 17 TreeSet

    概述

    第1 部分 TreeSet介绍

    第2 部分 TreeSet数据结构

    第3 部分 TreeSet 源码分析

    第1 部分 TreeSet介绍

    TreeSet 是一个有序的集合,它的作用是提供有序的Set集合。它继承于AbstractSet抽象类,实现了NavigableSet<E>, Cloneable, java.io.Serializable接口。
    TreeSet 继承于AbstractSet,所以它是一个Set集合,具有Set的属性和方法。
    TreeSet 实现了NavigableSet接口,意味着它支持一系列的导航方法。比如查找与指定目标最匹配项。
    TreeSet 实现了Cloneable接口,意味着它能被克隆。
    TreeSet 实现了java.io.Serializable接口,意味着它支持序列化。

    TreeSet是基于TreeMap实现的。TreeSet中的元素支持2种排序方式:自然排序 或者 根据创建TreeSet 时提供的 Comparator 进行排序。这取决于使用的构造方法。
    TreeSet为基本操作(add、remove 和 contains)提供受保证的 log(n) 时间开销。
    另外,TreeSet是非同步的。 它的iterator 方法返回的迭代器是fail-fast的。

    在TreeSet中定义了如下几个变量

    private transient NavigableMap<E,Object> m;
            
    //PRESENT会被当做Map的value与key构建成键值对
     private static final Object PRESENT = new Object();

    TreeSet的构造函数

    // 默认构造函数。使用该构造函数,TreeSet中的元素按照自然排序进行排列。
    TreeSet()
    
    // 创建的TreeSet包含collection
    TreeSet(Collection<? extends E> collection)
    
    // 指定TreeSet的比较器
    TreeSet(Comparator<? super E> comparator)
    
    // 创建的TreeSet包含set
    TreeSet(SortedSet<E> set)

    TreeSet的API

     boolean add(E e) 
              将指定的元素添加到此 set(如果该元素尚未存在于 set 中)。 
     boolean addAll(Collection<? extends E> c) 
              将指定 collection 中的所有元素添加到此 set 中。 
     E ceiling(E e) 
              返回此 set 中大于等于给定元素的最小元素;如果不存在这样的元素,则返回 nullvoid clear() 
              移除此 set 中的所有元素。 
     Object clone() 
              返回 TreeSet 实例的浅表副本。 
     Comparator<? super E> comparator() 
              返回对此 set 中的元素进行排序的比较器;如果此 set 使用其元素的自然顺序,则返回 nullboolean contains(Object o) 
              如果此 set 包含指定的元素,则返回 true。 
     Iterator<E> descendingIterator() 
              返回在此 set 元素上按降序进行迭代的迭代器。 
     NavigableSet<E> descendingSet() 
              返回此 set 中所包含元素的逆序视图。 
     E first() 
              返回此 set 中当前第一个(最低)元素。 
     E floor(E e) 
              返回此 set 中小于等于给定元素的最大元素;如果不存在这样的元素,则返回 null。 
     SortedSet<E> headSet(E toElement) 
              返回此 set 的部分视图,其元素严格小于 toElement。 
     NavigableSet<E> headSet(E toElement, boolean inclusive) 
              返回此 set 的部分视图,其元素小于(或等于,如果 inclusive 为 true)toElement。 
     E higher(E e) 
              返回此 set 中严格大于给定元素的最小元素;如果不存在这样的元素,则返回 nullboolean isEmpty() 
              如果此 set 不包含任何元素,则返回 true。 
     Iterator<E> iterator() 
              返回在此 set 中的元素上按升序进行迭代的迭代器。 
     E last() 
              返回此 set 中当前最后一个(最高)元素。 
     E lower(E e) 
              返回此 set 中严格小于给定元素的最大元素;如果不存在这样的元素,则返回 null。 
     E pollFirst() 
              获取并移除第一个(最低)元素;如果此 set 为空,则返回 null。 
     E pollLast() 
              获取并移除最后一个(最高)元素;如果此 set 为空,则返回 nullboolean remove(Object o) 
              将指定的元素从 set 中移除(如果该元素存在于此 set 中)。 
     int size() 
              返回 set 中的元素数(set 的容量)。 
     NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) 
              返回此 set 的部分视图,其元素范围从 fromElement 到 toElement。 
     SortedSet<E> subSet(E fromElement, E toElement) 
              返回此 set 的部分视图,其元素从 fromElement(包括)到 toElement(不包括)。 
     SortedSet<E> tailSet(E fromElement) 
              返回此 set 的部分视图,其元素大于等于 fromElement。 
     NavigableSet<E> tailSet(E fromElement, boolean inclusive) 
              返回此 set 的部分视图,其元素大于(或等于,如果 inclusive 为 true)fromElement。 

    说明

    (01) TreeSet是有序的Set集合,因此支持add、remove、get等方法。
    (02) 和NavigableSet一样,TreeSet的导航方法大致可以区分为两类,一类是提供元素项的导航方法,返回某个元素;另一类时提供集合的导航方法,返回某个集合。
    lower、floor、ceiling 和 higher 分别返回小于、小于等于、大于等于、大于给定元素的元素,如果不存在这样的元素,则返回 null。

    第2 部分 TreeSet数据结构

     TreeSet的继承关系

    java.lang.Object
       ↳     java.util.AbstractCollection<E>
             ↳     java.util.AbstractSet<E>
                   ↳     java.util.TreeSet<E>
    
    public class TreeSet<E> extends AbstractSet<E>        
        implements NavigableSet<E>, Cloneable, java.io.Serializable{}

    TreeSet与Collection关系如下图:

    从图中可以看出:
    (01) TreeSet继承于AbstractSet,并且实现了NavigableSet接口。
    (02) TreeSet的本质是一个"有序的,并且没有重复元素"的集合,它是通过TreeMap实现的。TreeSet中含有一个"NavigableMap类型的成员变量"m,而m实际上是"TreeMap的实例"。

    第3 部分 TreeSet 源码分析

      1 package java.util;
      2 
      3 
      4 public class TreeSet<E> extends AbstractSet<E>
      5     implements NavigableSet<E>, Cloneable, java.io.Serializable
      6 {
      7     // NavigableMap对象
      8     private transient NavigableMap<E,Object> m;
      9 
     10         // TreeSet是通过TreeMap实现的,
     11     // PRESENT是键-值对中的值。
     12     private static final Object PRESENT = new Object();
     13 
     14     // 将TreeMap赋值给 "NavigableMap对象m"
     15     TreeSet(NavigableMap<E,Object> m) {
     16         this.m = m;
     17     }
     18 
     19    // 不带参数的构造函数。创建一个空的TreeMap
     20     public TreeSet() {
     21         this(new TreeMap<E,Object>());
     22     }
     23 
     24     // 带比较器的构造函数。
     25     public TreeSet(Comparator<? super E> comparator) {
     26         this(new TreeMap<>(comparator));
     27     }
     28 
     29    // 创建TreeSet,并将集合c中的全部元素都添加到TreeSet中
     30     public TreeSet(Collection<? extends E> c) {
     31         this();
     32         // 将集合c中的元素全部添加到TreeSet中
     33         addAll(c);
     34     }
     35 
     36     // 创建TreeSet,并将s中的全部元素都添加到TreeSet中
     37     public TreeSet(SortedSet<E> s) {
     38         this(s.comparator());
     39         addAll(s);
     40     }
     41 
     42     // 返回TreeSet的顺序排列的迭代器。
     43     // 因为TreeSet时TreeMap实现的,所以这里实际上时返回TreeMap的“键集”对应的迭代器
     44     public Iterator<E> iterator() {
     45         return m.navigableKeySet().iterator();
     46     }
     47 
     48     // 返回TreeSet的逆序排列的迭代器。
     49     // 因为TreeSet时TreeMap实现的,所以这里实际上时返回TreeMap的“键集”对应的迭代器
     50     public Iterator<E> descendingIterator() {
     51         return m.descendingKeySet().iterator();
     52     }
     53 
     54     /**
     55      * @since 1.6
     56      */
     57     public NavigableSet<E> descendingSet() {
     58         return new TreeSet<>(m.descendingMap());
     59     }
     60 
     61     // 返回TreeSet的大小
     62     public int size() {
     63         return m.size();
     64     }
     65 
     66     // 返回TreeSet是否为空
     67     public boolean isEmpty() {
     68         return m.isEmpty();
     69     }
     70 
     71      // 返回TreeSet是否包含对象(o)
     72     public boolean contains(Object o) {
     73         return m.containsKey(o);
     74     }
     75 
     76     // 添加e到TreeSet中
     77     public boolean add(E e) {
     78         return m.put(e, PRESENT)==null;
     79     }
     80 
     81     // 删除TreeSet中的对象o
     82     public boolean remove(Object o) {
     83         return m.remove(o)==PRESENT;
     84     }
     85 
     86     // 清空TreeSet
     87     public void clear() {
     88         m.clear();
     89     }
     90 
     91     // 将集合c中的全部元素添加到TreeSet中
     92     public  boolean addAll(Collection<? extends E> c) {
     93         // Use linear-time version if applicable
     94         if (m.size()==0 && c.size() > 0 &&
     95             c instanceof SortedSet &&
     96             m instanceof TreeMap) {
     97             SortedSet<? extends E> set = (SortedSet<? extends E>) c;
     98             TreeMap<E,Object> map = (TreeMap<E, Object>) m;
     99             Comparator<? super E> cc = (Comparator<? super E>) set.comparator();
    100             Comparator<? super E> mc = map.comparator();
    101             if (cc==mc || (cc != null && cc.equals(mc))) {
    102                 map.addAllForTreeSet(set, PRESENT);
    103                 return true;
    104             }
    105         }
    106         return super.addAll(c);
    107     }
    108 
    109     // 返回子Set,实际上是通过TreeMap的subMap()实现的。
    110     public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
    111                                   E toElement,   boolean toInclusive) {
    112         return new TreeSet<>(m.subMap(fromElement, fromInclusive,
    113                                        toElement,   toInclusive));
    114     }
    115 
    116     // 返回Set的头部,范围是:从头部到toElement。
    117     // inclusive是是否包含toElement的标志
    118     public NavigableSet<E> headSet(E toElement, boolean inclusive) {
    119         return new TreeSet<>(m.headMap(toElement, inclusive));
    120     }
    121 
    122     // 返回Set的尾部,范围是:从fromElement到结尾。
    123     // inclusive是是否包含fromElement的标志
    124     public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
    125         return new TreeSet<>(m.tailMap(fromElement, inclusive));
    126     }
    127 
    128     // 返回子Set。范围是:从fromElement(包括)到toElement(不包括)。
    129     public SortedSet<E> subSet(E fromElement, E toElement) {
    130         return subSet(fromElement, true, toElement, false);
    131     }
    132 
    133     // 返回Set的头部,范围是:从头部到toElement(不包括)。
    134     public SortedSet<E> headSet(E toElement) {
    135         return headSet(toElement, false);
    136     }
    137 
    138      // 返回Set的尾部,范围是:从fromElement到结尾(不包括)。
    139     public SortedSet<E> tailSet(E fromElement) {
    140         return tailSet(fromElement, true);
    141     }
    142 
    143         // 返回Set的比较器
    144     public Comparator<? super E> comparator() {
    145         return m.comparator();
    146     }
    147 
    148     // 返回Set的第一个元素
    149     public E first() {
    150         return m.firstKey();
    151     }
    152 
    153     // 返回Set的最后一个元素
    154     public E last() {
    155         return m.lastKey();
    156     }
    157 
    158     // NavigableSet API methods
    159 
    160     // 返回Set中小于e的最大元素
    161     public E lower(E e) {
    162         return m.lowerKey(e);
    163     }
    164 
    165     // 返回Set中小于/等于e的最大元素
    166     public E floor(E e) {
    167         return m.floorKey(e);
    168     }
    169 
    170     // 返回Set中大于/等于e的最小元素
    171     public E ceiling(E e) {
    172         return m.ceilingKey(e);
    173     }
    174 
    175     // 返回Set中大于e的最小元素
    176     public E higher(E e) {
    177         return m.higherKey(e);
    178     }
    179 
    180     // 获取第一个元素,并将该元素从TreeMap中删除。
    181     public E pollFirst() {
    182         Map.Entry<E,?> e = m.pollFirstEntry();
    183         return (e == null) ? null : e.getKey();
    184     }
    185 
    186     // 获取最后一个元素,并将该元素从TreeMap中删除。
    187     public E pollLast() {
    188         Map.Entry<E,?> e = m.pollLastEntry();
    189         return (e == null) ? null : e.getKey();
    190     }
    191 
    192     // 克隆一个TreeSet,并返回Object对象
    193     public Object clone() {
    194         TreeSet<E> clone = null;
    195         try {
    196             clone = (TreeSet<E>) super.clone();
    197         } catch (CloneNotSupportedException e) {
    198             throw new InternalError();
    199         }
    200 
    201         clone.m = new TreeMap<>(m);
    202         return clone;
    203     }
    204 
    205     // java.io.Serializable的写入函数
    206     // 将TreeSet的“比较器、容量,所有的元素值”都写入到输出流中
    207     private void writeObject(java.io.ObjectOutputStream s)
    208         throws java.io.IOException {
    209         // Write out any hidden stuff
    210         s.defaultWriteObject();
    211 
    212         // Write out Comparator
    213         s.writeObject(m.comparator());
    214 
    215         // Write out size
    216         s.writeInt(m.size());
    217 
    218         // Write out all elements in the proper order.
    219         for (E e : m.keySet())
    220             s.writeObject(e);
    221     }
    222 
    223     // java.io.Serializable的读取函数:根据写入方式读出
    224     // 先将TreeSet的“比较器、容量、所有的元素值”依次读出
    225     private void readObject(java.io.ObjectInputStream s)
    226         throws java.io.IOException, ClassNotFoundException {
    227         // Read in any hidden stuff
    228         s.defaultReadObject();
    229 
    230         // Read in Comparator
    231         Comparator<? super E> c = (Comparator<? super E>) s.readObject();
    232 
    233         // Create backing TreeMap
    234         TreeMap<E,Object> tm;
    235         if (c==null)
    236             tm = new TreeMap<>();
    237         else
    238             tm = new TreeMap<>(c);
    239         m = tm;
    240 
    241         // Read in size
    242         int size = s.readInt();
    243 
    244         tm.readTreeSet(size, s, PRESENT);
    245     }
    246 
    247     private static final long serialVersionUID = -2479143000061671589L;
    248 }

    总结

    (01) TreeSet实际上是TreeMap实现的。当我们构造TreeSet时;若使用不带参数的构造函数,则TreeSet的使用自然比较器;若用户需要使用自定义的比较器,则需要使用带比较器的参数。
    (02) TreeSet是非线程安全的。
    (03) TreeSet实现java.io.Serializable的方式。当写入到输出流时,依次写入“比较器、容量、全部元素”;当读出输入流时,再依次读取。

  • 相关阅读:
    highcharts绘制股票k线
    利用meta标签将http请求换成https请求
    path.join 与 path.resolve 的区别
    【转】弧度和角度的转换
    块级元素和行内元素的区别 (block vs. inline)
    ubuntu下安装Apache + PHP + Mysql
    [读书笔记] CSS权威指南2: 结构和层叠
    [读书笔记] CSS权威指南1: 选择器
    [读书笔记] Head First 设计模式
    深入浅出React Native 3: 从零开始写一个Hello World
  • 原文地址:https://www.cnblogs.com/xingele0917/p/3939163.html
Copyright © 2011-2022 走看看