首先,让我们来看看JDK中TreeSet类的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 ? e2==null : 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;
}

注意抛出的异常~~

* @throws ClassCastException if the specified object cannot be compared with the elements currently in this set

也就是说,如果添加的元素不能和已有元素做比较就抛出ClassCastException异常~
那两个元素如果判断可比呢?
有两种办法,其中一种就是实现 Comparable接口
JDK中很多类都实现了Comparable接口,比如Integer
至于TreeSet为什么要这样设计,是因为这个类需要实现元素排序的功能
那如何实现的排序呢?
我们来看 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>());
}
 /**
* Constructs a set backed by the specified navigable map.
*/
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}

你可以发现,排序功能实际上是由TreeMap实现的
TreeSet的add方法实际上就是调用的的TreeMap的put方法~~
最后~看看put方法的源码

/**
* Associates the specified value with the specified key in this map.
* If the map previously contained a mapping for the key, the old
* value is replaced.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
*
* @return the previous value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
* (A <tt>null</tt> return can also indicate that the map
* previously associated <tt>null</tt> with <tt>key</tt>.)
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
* and this map uses natural ordering, or its comparator
* does not permit null keys
*/
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
// TBD:
// 5045147: (coll) Adding null to an empty TreeSet should
// throw NullPointerException
//
// compare(key, key); // type check
root = new Entry<K,V>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
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;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<K,V>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}

你可以发现,这个二叉树排序中有一条这样的语句来判断大小

cmp = k.compareTo(t.key);

这里k,也就是我们TreeSet.add(k) 方法传入的参数

Comparable<? super K> k = (Comparable<? super K>) key;

可见,插入TreeSet的对象必须实现Compareble接口

TreeSet集合为什么要实现Comparable?的更多相关文章

  1. TreeSet集合排序方式一:自然排序Comparable

    TreeSet集合默认会进行排序.因此必须有排序,如果没有就会报类型转换异常. 自然排序 Person class->实现Comparable,实现compareTo()方法 package H ...

  2. TreeSet集合的自然排序与比较器排序、Comparable接口的compareTo()方法

    [自然排序] package com.hxl; public class Student implements Comparable<Student> { private String n ...

  3. TreeSet集合深入了解--------攻击原理

    Set接口Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false.(无序,不可重复 )Set判断两个对象相同不是使用==运算符,而是根据equals方法.也就是说 ...

  4. TreeSet集合

    TreeSet集合 TreeSet集合是一个依靠TreeMap实现的有序集合,内部存储元素是自动按照自然排序进行排列,所以如果想要保留存储时的顺序,那么就不建议使用TreeSet. TreeSet继承 ...

  5. Java TreeSet集合排序 && 定义一个类实现Comparator接口,覆盖compare方法 && 按照字符串长度排序

    package TreeSetTest; import java.util.Iterator; import java.util.TreeSet; import javax.management.Ru ...

  6. TreeSet集合如何保证元素唯一

    TreeSet: 1.特点 TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列 2.使用方式 a.自然顺序(Comparable) TreeSet类的add()方法中会 ...

  7. TreeSet集合解析

    TreeSet是实现Set接口的实现类.所以它存储的值是唯一的,同时也可以对存储的值进行排序,排序用的是二叉树原理.所以要理解这个类,必须先简单理解一下什么是二叉树. 二叉树原理简析 假如有这么一个集 ...

  8. TreeSet集合的add()方法源码解析(01.Integer自然排序)

    >TreeSet集合使用实例 >TreeSet集合的红黑树 存储与取出(图) >TreeSet的add()方法源码     TreeSet集合使用实例 package cn.itca ...

  9. java基础33 Set集合下的HashSet集合和TreeSet集合

    单例集合体系: ---------| collection  单例集合的根接口--------------| List  如果实现了list接口的集合类,具备的特点:有序,可重复       注:集合 ...

随机推荐

  1. 举个通俗易懂的例子告诉你IAAS,SAAS,PAAS的区别

    作者:何足道链接:https://www.zhihu.com/question/21641778/answer/62523535来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

  2. angular2.0学习笔记6.编程风格指南

    1.组件的类名应该是大驼峰形式,并且以Component结尾. 因此英雄详情组件的类名是HeroDetailComponent. 组件的文件名应该是小写中线形式,每个单词之间用中线分隔,并且以.com ...

  3. hdu (kruska and prime) 继续畅通工程

    题目http://acm.hdu.edu.cn/showproblem.php?pid=1879 复习一下最小生成树的两个基本算法. 由于存在道路是否已修建的问题,如果已修建,那么该条道路的成本即为0 ...

  4. MacDev.GetArchOfLibrary

    1. static library How to check target architecture of a static library http://changhoward.blogspot.c ...

  5. iOS.-.cxx_destruct

    -.cxx_destruct 方法: 该方法是由编译器生成的方法. 1. “ARC actually creates a -.cxx_destruct method to handle freeing ...

  6. javascript 高级程序设计 四

    新的一天开始,让我们伴随者轻快的心情,开始今天的笔记 1.操作符: (1): *./.-在ECMAScript中操作的时候,如果遇到有一个操作值不是数值型(Number),那么就会在后台调用numbe ...

  7. 洛谷4054 [JSOI2009]计数问题

    原题链接 二维树状数组模板题. 对每一种颜色开一棵二维树状数组统计即可. #include<cstdio> using namespace std; const int N = 310; ...

  8. 脚本路径问题_dirname

    pwd可获取命令当前的路径 可是若我们想在脚本中获取脚本所在文件夹的路径,这种方法是不够用的. 例如,我们的脚本放在/home/user/script/下,名字叫做getpath.sh getpath ...

  9. UI设计教程分享:让你彻底读懂字体

    一份普普通通.规规矩矩的设计 一份让人印象深刻.新颖有趣的设计 差在哪?其实就差在三个字上! “优秀的设计不是每一个细节都有亮点,而是弱化其他元素,让某一个亮点最大化.” 今天“骉叔的设计心得”就来总 ...

  10. 10个办法让设计小白迅速get海报设计要点!

    对于设计师而言,海报和宣传单的设计,几乎是每一个设计师的必修课.如今网页上的 Banner.宣传和促销的数字海报,大多脱胎于我们所熟知的海报设计. 对于推销产品.连接客户,海报始终是一种最为有趣和实用 ...