集合框架Set----TreeSet

2018-09-15  本文已影响0人  东风谷123Liter

TreeSet是有序的。

需求:

用TreeeSet集合存储自定义对象Student;
使其按学号进行排序,如果学号相同就按照名字的ASII值排序。

思路:

由于前路未卜,我们走一步看一步:

import java.util.*;
//定义Student类型
class Student {
     private String name;
     private int number;
     Student(String n, int nu){
           this.name = name;
           this.number = number;
     }
     public String getName() {
           return name;
     }
     public int getNumber() {
           return number;
     }
}
class treeSetStudent {
     public static void main(String[] args) {
           //定义TreeSet集合来存储Student类型对象。
           TreeSet ts = new TreeSet();    
           ts.add(new Student("tom01",12));
           ts.add(new Student("tom07",22));
           ts.add(new Student("tom09",12));
           Iterator it = ts.iterator();
           while(it.hasNext()) {
                Student st = (Student)it.next();
                System.out.println(st.getName()+"....."+st.getNumber());
           }
     }
}

看似很完美,但结果却出乎意料:

Exception in thread "main" java.lang.ClassCastException: jihe.Student cannot be cast to java.base/[java.lang.Comparable](http://java.lang.comparable/)
     at java.base/[java.util.TreeMap.compare](http://java.util.treemap.compare/)(TreeMap.java:1291)
     at java.base/java.util.TreeMap.put(TreeMap.java:536)
     at java.base/java.util.TreeSet.add(TreeSet.java:255)
     at jihe.treeSetStudent.main(treeSetStudent.java:25)

从上面报错信息,我们可以发现类型映射异常:
他说Student类型没办法映射到java.lang.Comparable类型!
所以我们得先看一下java.lang.Comparable到底是个什么鬼。


我们发现他是个接口,不是类;


其实到这里我相信大家都猜到了,问题就是Comparable接口中的方法无法比较两个Student对象。所以在这我要重写compareTo()方法!!!
TreeSet集合中对象都需要具备可比性。

添加的代码如下:

public int compareTo(Object obj) {//重写compareTo方法。
           if(!(obj instanceof Student))
                throw new RuntimeException("not a Student.");
           Student st = (Student)obj;
           System.out.println(this.name+"....compare with..."+st.name);
           //当此对象大于指定对象时,返回1(正数就可以);
           //当此对象等于指定对象时,返回0;
           //当此对象大于指定对象时,返回-1(负数就可以);
           if(this.number>st.number)
                return 1;
           if(this.number==st.number)
                return 0;
           return -1;
     }
     public String getName() {
           return name;
     }
     public int getNumber() {
           return number;
     }
}

运行结果:


说明,代码还不够完善;为了让它知道学号相同并不是同一个对象,并且当学号相同的时候,再根据名字的ASII的值来排序。我们改进为:

public int compareTo(Object obj) {//重写compareTo方法。
           if(!(obj instanceof Student))
                throw new RuntimeException("not a Student.");
           Student st = (Student)obj;
           System.out.println(this.name+"....compare with..."+st.name);
           //当此对象大于指定对象时,返回1(正数就可以);
           //当此对象等于指定对象时,返回0;
           //当此对象大于指定对象时,返回1(负数就可以);
           if(this.number>st.number)
                return 1;
           if(this.number==st.number)
                //String类也实现了Comparable接口。
                return this.name.compareTo(st.name);
           return -1;
     }

运行结果:


好了大功告成!
TreeSet底层的数据结构:

添加元素时,就是在画二叉树;
取元素时,遵循数据结构中以左中右的方式读取数据。

现在:如何实现怎么存进去就怎么取出来?

很简单:只要重写compareTo方法事,只返回正数或者负数;原理就是:compareTo方法返回负数就存在根元素的左边,如果返回负数就存在根元素的右边。
TreeSet保证元素的唯一性的方法:return 0;

总结:

TreeSet排序的方式就是通过继承Comparable接口,重写compareTo方法。

问题:

做法:

先查看相关文档:



我们也看一下TreeSet的构造方法有哪些?


接下就要看代码了:

import java.util.*
//定义Student类型
class Student implements Comparable {//继承Comparable接口
     private String name;
     private int number;
     Student(String n, int nu){
           this.name = n;
           this.number = nu;
     }
     public int compareTo(Object obj) {//重写compareTo方法。
           if(!(obj instanceof Student))
                throw new RuntimeException("not a Student.");
           Student st = (Student)obj;
           System.out.println(this.name+"....compare with..."+st.name);
           //当此对象大于指定对象时,返回1(正数就可以);
           //当此对象等于指定对象时,返回0;
           //当此对象大于指定对象时,返回1(负数就可以);
           if(this.number>st.number)
                return 1;
           if(this.number==st.number)
                //String类也实现了Comparable接口。
                return this.name.compareTo(st.name);
           return -1;
     }
     public String getName() {
           return name;
     }
     public int getNumber() {
           return number;
     }
}
class treeSetStudent {
     public static void main(String[] args) {
           TreeSet ts = new TreeSet(new myCompare()); //定义TreeSet集合来存储Student类型对象。
           //TreeSet专门针对比较器的使用有一个构造方法,参数就是Comparator接口实现的对象。
           //如果一个程序中元素和几何对象都具有比较性,那么优先使用集合的比较器!
           ts.add(new Student("tom01",12));
           ts.add(new Student("tom07",22));
           ts.add(new Student("tom07",24));
           ts.add(new Student("tom09",12));
           Iterator it = ts.iterator();
           while(it.hasNext()) {
                Student st = (Student)it.next();
                System.out.println(st.getName()+"....."+st.getNumber());
           }
     }
}
class myCompare implements Comparator{
     public int compare(Object o1, Object o2) {
           Student s1 = (Student)o1;
           Student s2 = (Student)o2;
           int n = s1.getName().compareTo(s2.getName());
           if(n == 0) {
                if(s1.getNumber()>s2.getNumber())
                     return 1;
                if(s1.getNumber()==s2.getNumber())
                     return 0;
                return -1;
                //上面这段代码有点复杂,我们还可以用Integer整型对象调用compareTo()来代替。
                //return new Integer(s1.getNumber()).compareTo(new Integer(s2.getNumber()))
                //注意只要是类型对象都实现了compareTo()方法,他是java.lang报下面的方法。
           }
           if(n>0)
                return 1;
           return -1;
     }
}

运行结果:

总结:

无论哪一种排序方法,底层的数据结构都是二叉树。**

上一篇下一篇

猜你喜欢

热点阅读