Java基础——TreeSet
Posted 长河落日圆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java基础——TreeSet相关的知识,希望对你有一定的参考价值。
TreeSet是SortedSet接口的实现类,Sorted的英文意思是分类的;选择的。
TreeSet可以确保集合元素处于排序状态。与HashSet集合相比,TreeSet还提供了如下几个额外方法:
方法名称 | 解释 |
Comparator comparator(); | 如果TreeSet采用了定制排序,则该方法返回定制排序所使用Comparator;如果TreeSet采用了自然排序,则返回null; |
Object first(); | 返回集合中的第一个元素; |
Object last(); | 返回集合中的最后一个元素; |
Object lower(Object o); | 返回集合中位于指定元素之前的元素(即小于指定元素的最大元素,参考元素不需要是TreeSet集合里的元素); |
Object higher(Object o); | 返回集合中位于指定元素之后的元素(即大于指定元素的最小元素,参考元素不需要是TreeSet集合里的元素); |
SortedSet subSet(Object fromElement,Object toElement); | 返回此Set的子集合,返回从fromElement,Object (包含到)toElement(不包含); |
SortedSet headSet(Object toElement); | 返回此Set的子集,由小于toElement的元素组成; |
SortedSet tailSet(Object fromElement); | 返回此Set的子集,由大于或等于fromElement的元素组成; |
1 import java.util.Set; 2 import java.util.TreeSet; 3 4 public class TreeS { 5 public static void main(String[] args) { 6 Set<String> set = new TreeSet<String>();// 定义了泛型 7 set.add("Java"); 8 set.add("Js"); 9 set.add("php"); 10 set.add("C#"); 11 set.add("C++"); 12 set.add(".Net"); 13 // 打印集合 14 System.out.println(set); 15 16 // 输出集合的容量 17 System.out.println(set.size()); 18 19 // 如果此 set 不包含任何元素,则返回 true 20 System.out.println(set.isEmpty()); 21 22 } 23 }
output: [.Net, C#, C++, Java, Js, PHP] 6 false
与HashSet集合采用通过hash算法来决定元素的存储位置不同,TreeSet采用红黑树的数据结构来存储集合元素。
TreeSet支持两只排序方法:自然排序与自定义。
一、自然排序:
TreeSet会调用集合元素的compareTo(Object o)方法来比较元素之间的大小关系,然后将集合元素按升序排列,这种方式是自然排序。
Java提供了一个Comparable接口,该接口定义一个compareTo(Object
o)方法,该方法返回一个整数值,实现该接口的类必须实现该方法,实现该接口的类的对象就可以比较大小。
例一&例二:
1 import java.util.TreeSet; 2 3 public class T { 4 public static void main(String[] args) { 5 6 // 例一:数字排序 7 /* 8 * TreeSet a = new TreeSet(); 9 * a.add(10); 10 * a.add(55); 11 * a.add(4); 12 * a.add(6); 13 * a.add(-1); 14 * a.add(-77); 15 * a.add(0); 16 * 17 * System.out.println(a);//打印:[-77, -1, 0, 4, 6, 10, 55] 18 */ 19 20 //例二:字母排序 21 TreeSet ts=new TreeSet(); 22 ts.add("b"); 23 ts.add("ee"); 24 ts.add("d"); 25 ts.add("abc"); 26 ts.add("ca"); 27 28 /* abc 29 b 30 c 31 ca 32 d 33 ee*/ 34 35 System.out.println(ts); //[abc, b, ca, d, ee] 36 } 37 }
例三:(下面这个例子没有写具体的比较规则。)
1 import java.util.Set; 2 import java.util.TreeSet; 3 4 class TreeS implements Comparable<Object> { 5 6 int score; 7 8 public TreeS(int score) { 9 this.score = score; 10 } 11 12 public int compareTo(Object o) { 13 return 1; 14 } 15 16 public boolean equals(Object obj) { 17 return true; 18 } 19 20 public static void main(String[] args) { 21 Set<Object> set = new TreeSet<Object>(); 22 23 // 计划在添加两个对象 24 set.add(new TreeS(77)); 25 set.add(new TreeS(7)); 26 27 System.out.println(set); 28 29 } 30 }
output:
[TreeS@67064, TreeS@bcda2d]
例四:(这个例子为了引出自定义计较方法,其实已经用上一点了)
判断两个对象的是否相等的参照标准如下:
1 import java.util.Set; 2 import java.util.TreeSet; 3 4 class TreeS implements Comparable<Object> { 5 6 int score; 7 8 public TreeS(int score) { 9 this.score = score; 10 } 11 12 public int compareTo(Object o) { 13 TreeS d=(TreeS)o;//强制类型转换 14 return this.score>d.score? 1:this.score<d.score? -1:0; 15 } 16 17 public boolean equals(Object obj) { 18 if(this==obj){ 19 return true; 20 }else if(obj!=null&&obj.getClass()==TreeS.class){ 21 TreeS d=(TreeS)obj; 22 return d.score==this.score; 23 } 24 return false; 25 } 26 27 public static void main(String[] args) { 28 Set<Object> set = new TreeSet<Object>(); 29 30 // 计划在添加两个对象 31 set.add(new TreeS(77)); 32 set.add(new TreeS(77));//没有被打印 33 set.add(new TreeS(20)); 34 set.add(new TreeS(3)); 35 set.add(new TreeS(44)); 36 set.add(new TreeS(44));//没有被打印 37 set.add(new TreeS(6)); 38 set.add(new TreeS(-11)); 39 set.add(new TreeS(9)); 40 set.add(new TreeS(0)); 41 42 System.out.println(set); 43 44 } 45 }
output:
[TreeS@97d01f, TreeS@e0a386, TreeS@feb48, TreeS@11ff436, TreeS@da3a1e, TreeS@11dba45, TreeS@b03be0, TreeS@2af081]
注意:
与HashSet类似的是,如果TreeSet中包含了可变对象,当可变对象的示例变量被修改时,TreeSet在处理这些对象时将非常复杂,而且容易出错。为了让程序更加健壮,推荐不要修改放入HashSet和TreeSet集合中元素的关键实例变量。
二、自定义排序
TessSet 的自然排序是根据集合元素的大小,TreeSet将它们以升序排列。如果需要实现定制排序,例如以降序排列,则可通过Comparator接口的帮助。
例一:
//使用TreeSet对学生考试成绩排序 //怎么做? //1 让对象实现 Comparable 接口 //2 然后重写compareTo 方法 //interface Comparable<T> Comparable 接口 //int compareTo(T o) Comparable接口中的方法 返回负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。 public class Student implements Comparable<Object>{ int age; int score; String name; @Override //在自己重写的时候,先写上它,可以帮你报错 public String toString(){ return this.name+":"+this.age+":"+this.score; } public Student(int age,int score,String name){ this.name=name; this.age=age; this.score=score; } @Override //用返回值是正数、负数或者零来判断大小 public int compareTo(Object obj){ if(!(obj instanceof Student)){ throw new RuntimeException("输入的不是本类对象,请重新输入"); } Student stu=(Student)obj; if(this.score>stu.score){ return 1; //设置为是正数就行了 }else if(this.score<stu.score){ return -1; }else { //设置如果相等的例子,上面有个例子,相等的情况会丢失数据,这里要考虑到 int result=this.name.compareTo(stu.name); if(result==0) return 1; return result; } } }
测试类:
import java.util.Iterator; import java.util.Set; import java.util.TreeSet; public class Test { public static void main(String[] args) { Set<Student> treeSet = new TreeSet<Student>(); treeSet.add(new Student(11, 80, "李平")); treeSet.add(new Student(23, 40, "王芳")); treeSet.add(new Student(10, 60, "赵磊")); treeSet.add(new Student(12, 40, "王小二")); treeSet.add(new Student(10, 60, "马苗")); treeSet.add(new Student(18, 60, "马苗")); treeSet.add(new Student(25, 70, "姜浩")); Iterator<Student> it = treeSet.iterator(); while (it.hasNext()) { Student stu = (Student) it.next(); System.out.println(stu); } } }
例二:
//例子 往 treeset中放字符串,按字符串长度排序 class MyComparator implements Comparator{ @Override public int compare(Object o1, Object o2) { Student stu1=(Student)o1; Student stu2=(Student)o2; if(stu1.score>stu2.score){ return 10; //只要是正为数就行 } else if(stu1.score<stu2.score){ return -10; } else{ //return 0; return stu1.name.compareTo(stu2.name); } } } main 方法中 Set set=new TreeSet(new StrLenComparator()); set.add("cc"); set.add("b"); set.add("dddddddd"); set.add("kkkkkkkkkkk"); set.add("v"); set.add("ee"); set.add("sssss"); Iterator it2=set.iterator(); while(it2.hasNext()){ System.out.println(it2.next()); }
例三:
附: 使用匿名类 Set set=new TreeSet(new Comparator() { //这里使用了匿名类 @Override public int compare(Object o1, Object o2) { String str1=(String)o1; String str2=(String)o2; if(str1.length()>str2.length()){ return 1; } else if(str1.length()<str2.length()){ return -1; } else{ //return 0; return 1; //如果相等,反回1的目的,是怕丢数据 } } }
总结:
TreeSet是依靠TreeMap来实现的,所以是根据实现的Compareble接口或Comparator接口来判断元素是否重复,其排序与TreeMap一样。
以上是关于Java基础——TreeSet的主要内容,如果未能解决你的问题,请参考以下文章
java基础33 Set集合下的HashSet集合和TreeSet集合
Java集合Collection 体系集合详解(ArrayList,LinkedList,HashSet,TreeSet...)