Java集合(6):TreeSet
一.TreeSet介绍
与HashSet是基于HashMap实现一样,TreeSet是基于TreeMap实现的。TreeSet是一个有序集合,TreeSet中的元素将按照升序排列,缺省是按照自然排序进行排列,Integer能排序(有默认顺序), String能排序(有默认顺序), 如果想把自定义类的对象存入TreeSet进行排序, 那么必须实现Comparable接口。或者有一个自定义的比较器。我们可以在构造TreeSet对象时,传递实现Comparator接口的比较器对象。
1.TreeSet的继承关系
public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializable
2.TreeSet的类图关系如下:
通过源码我们知道TreeSet继承自AbstractSet,实现了NavigableSet、Cloneable、Serializable接口。其中AbstractSet提供 Set 接口的骨干实现,从而最大限度地减少了实现此接口所需的工作。NavigableSet是扩展的 SortedSet,具有了为给定搜索目标报告最接近匹配项的导航方法,这就意味着它支持一系列的导航方法。比如查找与指定目标最匹配项。Cloneable支持克隆,Serializable支持序列化。
二.TreeSet源码解析
1.私有属性
1 private transient NavigableMap<E,Object> m; 2 3 //PRESENT会被当做Map的value与key构建成键值对 4 private static final Object PRESENT = new Object();
2.TreeSet的构造方法
1 //默认构造方法,根据其元素的自然顺序进行排序 2 public TreeSet() { 3 this(new TreeMap<E,Object>()); 4 } 5 6 //构造一个包含指定 collection 元素的新 TreeSet,它按照其元素的自然顺序进行排序。 7 public TreeSet(Collection<? extends E> c) { 8 this(); 9 addAll(c); 10 } 11 12 //构造一个新的空 TreeSet,它根据指定比较器进行排序。 13 public TreeSet(Comparator<? super E> comparator) { 14 this(new TreeMap<>(comparator)); 15 } 16 17 //构造一个与指定有序 set 具有相同映射关系和相同排序的新 TreeSet。 18 public TreeSet(SortedSet<E> s) { 19 this(s.comparator()); 20 addAll(s); 21 } 22 23 TreeSet(NavigableMap<E,Object> m) { 24 this.m = m; 25 }
3.其他方法
3.1 add
public boolean add(E e)
将指定的元素添加到此 set(如果该元素尚未存在于 set 中)。
3.2 addAll
public boolean addAll(Collection<? extends E> c)
将指定 collection 中的所有元素添加到此 set 中。
3.3 remove
public boolean remove(Object o)
将指定的元素从 set 中移除(如果该元素存在于此 set 中)。
3.4 clear
public void clear()
移除此 set 中的所有元素。
3.5 clone
public Object clone()
返回 TreeSet 实例的浅表副本。属于浅拷贝。
3.6 size
public int size()
返回 set 中的元素数(set 的容量)。
3.7 isEmpty
public boolean isEmpty()
如果此 set 不包含任何元素,则返回 true。
3.8 comparator
public Comparator<? super E> comparator()
返回对此 set 中的元素进行排序的比较器;如果此 set 使用其元素的自然顺序,则返回 null。
3.9 contains
public boolean contains(Object o)
如果此 set 包含指定的元素,则返回 true。
3.10 iterator
public Iterator<E> iterator()
返回在此 set 中的元素上按升序进行迭代的迭代器。
3.11 first
public E first()
返回此 set 中当前第一个(最低)元素。
3.12 last
public E last()
返回此 set 中当前最后一个(最高)元素。
3.13 higher
public E higher(E e)
返回此 set 中严格大于给定元素的最小元素;如果不存在这样的元素,则返回 null。
3.14 lower
public E lower(E e)
返回此 set 中严格小于给定元素的最大元素;如果不存在这样的元素,则返回 null。
3.15 ceiling
public E ceiling(E e)
返回此 set 中大于等于给定元素的最小元素;如果不存在这样的元素,则返回 null。
3.16 floor
public E floor(E e)
返回此 set 中小于等于给定元素的最大元素;如果不存在这样的元素,则返回 null。
还有一些其他的方法,太多了,这里就不写了,都快写成中文API了,上面这些都是些较为常用的方法,其他的方法用到的时候查下源码吧。
三.TreeSet使用示例
1.String 类的排序
1 public class TreeSetTest { 2 public static void main(String[] args) { 3 Set ts = new TreeSet(); 4 ts.add("abc"); 5 ts.add("xyz"); 6 ts.add("rst"); 7 Iterator it = ts.iterator(); 8 while (it.hasNext()) { 9 System.out.println(it.next()); 10 } 11 } 12 }
输出结果:
abc
rst
xyz
打印结果不是和先前加入的顺序一样,它是按照一个字母的排序法进行排序的。这是因为String 类实现了Comparable接口。
2.自定义类的排序
如果我们自己定义的一个类的对象要加入到TreeSet当中,那么这个类必须要实现Comparable接口。
1 public class test_treeset { 2 @SuppressWarnings("unchecked") 3 public static void main(String[] args) { 4 Set ts = new TreeSet(); 5 ts.add(new Teacher("zhangsan", 1)); 6 ts.add(new Teacher("lisi", 2)); 7 ts.add(new Teacher("wangmazi", 3)); 8 ts.add(new Teacher("wangwu",4)); 9 ts.add(new Teacher("mazi", 3)); 10 Iterator it = ts.iterator(); 11 while (it.hasNext()) { 12 System.out.println(it.next()); 13 } 14 } 15 } 16 class Teacher implements Comparable { 17 int num; 18 String name; 19 20 Teacher(String name, int num) { 21 this.num = num; 22 this.name = name; 23 } 24 25 public String toString() { 26 return "学号:" + num + "\t\t姓名:" + name; 27 } 28 29 //o中存放时的红黑二叉树中的节点,从根节点开始比较 30 public int compareTo(Object o) { 31 Teacher ss = (Teacher) o; 32 int result = num < ss.num ? 1 : (num == ss.num ? 0 : -1);//降序 33 //int result = num > ss.num ? 1 : (num == ss.num ? 0 : -1);//升序 34 if (result == 0) { 35 result = name.compareTo(ss.name); 36 } 37 return result; 38 } 39 }
运行结果: 学号:4 姓名:wangwu 学号:3 姓名:mazi 学号:3 姓名:wangmazi 学号:2 姓名:lisi 学号:1 姓名:zhangsan
注意:如果将int result = num > ss.num ? 1 : (num == ss.num ? 0 : -1);写成了int result = ss.num > num ? 1 : (ss.num == num ? 0 : -1);那么得到的结果就是倒序排列的,并不是升序的。
3.比较器
在使用TreeSet对加入到其中的元素进行排序的时候可以像Arrays对数组中的元素进行排序和Collections对集合中的元素进行排序一样,传递一个比较器。
构造一个新的空TreeSet,它根据指定比较器进行排序。插入到该 set 的所有元素都必须能够由指定比较器进行相互比较:对于 set 中的任意两个元素 e1 和e2,执行 comparator.compare(e1, e2) 都不得抛出 ClassCastException。如果用户试图将违反此约束的元素添加到 set 中,则 add 调用将抛出 ClassCastException。
1 class Teacher { 2 int num; 3 String name; 4 5 Teacher(String name, int num) { 6 this.num = num; 7 this.name = name; 8 } 9 10 public String toString() { 11 return "学号:" + num + " 姓名:" + name; 12 } 13 14 static class TeacherCompare implements Comparator {// 老师自带的一个比较器 15 public int compare(Object o1, Object o2) { 16 Teacher s1 = (Teacher) o1;// 转型 17 Teacher s2 = (Teacher) o2;// 转型 18 int result = s1.num > s2.num ? 1 : (s1.num == s2.num ? 0 : -1); 19 if (result == 0) { 20 result = s1.name.compareTo(s2.name); 21 } 22 return result; 23 } 24 } 25 }
运行结果: 学号:1 姓名:lisi 学号:2 姓名:zhangsan 学号:3 姓名:mazi 学号:3 姓名:wangmazi
参考:http://cmsblogs.com/?p=1162
http://www.cnblogs.com/meng72ndsc/archive/2010/12/23/1914477.html