zoukankan      html  css  js  c++  java
  • TreeSet集合的add()方法的源码解析

    用TreeSet存储Integer类型数据并遍历

      20,18,23,22,17,24,19,18,24

     1 package cn.itcast_05;
     2 
     3 import java.util.TreeSet;
     4 
     5 /*
     6  * TreeSet:能够对元素按照某种规则进行排序。
     7  *         排序有两种方式(具体那种方式取决于使用TreeSet的构造方法)
     8  *             A:自然排序
     9  *             B:比较器排序
    10  * 
    11  * TreeSet集合的特点:排序和唯一
    12  * 
    13  * 通过观察TreeSet的add()方法,我们知道最终要看TreeMap的put()方法。
    14  */
    15 public class TreeSetDemo {
    16     public static void main(String[] args) {
    17         // 创建集合对象
    18         // TreeSet的无参构造:自然顺序进行排序
    19         TreeSet<Integer> ts = new TreeSet<Integer>();
    20 
    21         // 创建元素并添加进集合
    22         // 20,18,23,22,17,24,19,18,24
    23         // Integer i1 = new Integer(200);
    24         // ts.add(i1);
    25         ts.add(20); // 自动装箱
    26         ts.add(18);
    27         ts.add(23);
    28         ts.add(22);
    29         ts.add(17);
    30         ts.add(24);
    31         ts.add(19);
    32         ts.add(18);
    33         ts.add(24);
    34 
    35         // 遍历集合
    36         for (Integer i : ts) {
    37             System.out.println(i);
    38         }
    39     }
    40 }

    TreeSet集合的add()方法的源码

    ---------------------------------------
    interface Collection {
        ...
    }
    
    interface Set extends Collection {
        ...
    }
    ---------------------------------------
    class TreeSet implements Set {
        ...
        private static final Object PRESENT = new Object();
        private transient NavigableMap<E,Object> m;
        
        public TreeSet() {
             this(new TreeMap<E,Object>());
        }
    
        public boolean add(E e) {
            return m.put(e, PRESENT)==null;
        }
        ...
    }
    ---------------------------------------
    class TreeMap implements NavigableMap {
        ...
        public V put(K key, V value) {
           Entry<K,V> t = root; // 先造根,TreeSet集合底层数据结构是红黑树(是一个自平衡的二叉树)
           if (t == null) {
               compare(key, key); // type (and possibly null) check
    
               root = new Entry<>(key, value, null);
               size = 1;
               modCount++;
               return null;
           }
           
           int cmp;
           Entry<K,V> parent;
           // split comparator and comparable paths
           Comparator<? super K> cpr = comparator; // 因为用的是TreeSet的无参构造方法,是自然排序,没有用到comparator比较器
           if (cpr != null) {                      // 所以此时的comparator = null,则程序执行else里面的代码
               do {
                   parent = t;
                   cmp = cpr.compare(key, t.key);
                   if (cmp < 0)
                       t = t.left;
                   else if (cmp > 0)
                       t = t.right;
                   else
                       return t.setValue(value);
               } while (t != null);
           } else {
               if (key == null)
                   throw new NullPointerException();
               Comparable<? super K> k = (Comparable<? super K>) key; // 此接口Comparable强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。。
               do {                                                   // 举例中我们使用的是包装类Intrger,而Integer类实现了Comparable接口。此例子是向上转型。
                   parent = t;
                   cmp = k.compareTo(t.key); // 类的 compareTo 方法被称为它的自然比较方法。
                   if (cmp < 0)              // int compareTo(T o) 比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。 
                       t = t.left;
                   else if (cmp > 0)
                       t = t.right;
                   else
                       return t.setValue(value);
               } while (t != null);
           }
           
           Entry<K,V> e = new Entry<>(key, value, parent);
           if (cmp < 0)
               parent.left = e;
           else
               parent.right = e;
           fixAfterInsertion(e);
           size++;
           modCount++;
           return null;
       }
       ...
    }
    ---------------------------------------
        由上可知:真正的比较是依赖于元素的compareTo()方法,而这个方法compareTo()是定义在 Comparable接口里面的(抽象方法)。
        所以,你要想重写该方法,就必须是先实现 Comparable接口。这个接口表示的就是自然排序。
    ---------------------------------------
  • 相关阅读:
    PHP 求多个数组的笛卡尔积,适用于求商品规格组合 【递归思想, 类似广度优先搜索】【原创】
    CCF推荐期刊会议
    SCI分区
    值和指针接收者的区别
    程序员练级攻略
    保险
    golang 有缓冲channel和无缓冲channel
    后台学习路线
    golang之反射
    atomic和mutex
  • 原文地址:https://www.cnblogs.com/chenmingjun/p/8661063.html
Copyright © 2011-2022 走看看