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接口。这个接口表示的就是自然排序。
---------------------------------------

 

我的GitHub地址: https://github.com/heizemingjun
我的博客园地址: http://www.cnblogs.com/chenmingjun
我的蚂蚁笔记博客地址: http://blog.leanote.com/chenmingjun
Copyright ©2018 黑泽明军
【转载文章务必保留出处和署名,谢谢!】
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. Set(集合)里面的元素是无序的,但没有重复的元素 2. 两个实现类HashSet(LinkHashSet)和TreeSet,TreeSet有排序功能(Set set=new TreeSet();set.add(new Integer(8)); set.add(new Integer(4)); set.add(new Integer(7));)输出后的结果是:4 7 8 Eg: package test; import java.util.*; public class Set{ public static void main(String[] args) { //先实例化一个set Set<String> stringSet=new HashSet<String>(); //向set里面添加元素 stringSet.add("123"); stringSet.add("wer"); stringSet.add("345"); //将set里的元素取出 Iterator<String> stringIter=stringSet.iterator(); while(stringIter.hasNext()){ String str=stringIter.next(); System.out.println(str); System.out.println("~~~~~~~~~~~"); } System.out.println("stringSet里面有"+stringSet.size()+"元素"); } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~2.List(列表<接口>)以线性方式存储,有序,允许重复主要实现类有LinkList(采用链表数据结构)和ArrayList(代表可大可小的数组) Eg: package test; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; public class Map { public static void main(String[] args) { List list=new ArrayList(); list.add(10); list.add(2); list.add(34); //对list数组进行自然排序 Collections.sort(list); //依次检索输出list的所有对象 // for(int i=0;i<list.size();i++){ // System.out.println(list.get(i)); // } Iterator Iter=list.iterator(); while(Iter.hasNext()){ System.out.println(Iter.next()); } } } 3.Map(映射<集合>)是无序的,是一种把键对象和值对象进行映射的集合,它每一个元素都包含一对键对象和值对象,给出键对象就可以得到值对象,键对象不允许重复,对值没有要求,多个任意键对象可以映射到一个值对象上;如果有相同键对象,最后一次加入的键对象和值对象将会覆盖以前的; Eg: package test; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeMap; public class NewMap { public static void main(String[] args) { //向map里添加键值对 //如果要对键进行排序Map map=new TreeMap(); Map<Integer,String> map=new TreeMap<Integer,String>(); //Map map=new HashMap(); map.put(1, "yi"); map.put(23, "er"); map.put(12, "san"); map.put(3, "si"); //遍历map Set keys=map.keySet(); Iterator<Integer> stringIter=keys.iterator(); while(stringIter.hasNext()){ int key=stringIter.next(); String value=(String) map.get(key);//根据键key得到value的值 System.out.println(key+"---"+value); } } }

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值