集合框架Set----TreeSet
2018-09-15 本文已影响0人
东风谷123Liter
TreeSet是有序的。
- 保存的元素会自动排序;
- 排序方法是依据ASII码值进行排序的。
简单实现:
运行结果:
下面我们来看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集合对象的排序的。
- 下面我们通过给集合对象增加比较性,来让TreeSet集合对象按照名字的顺序排序。
做法:
- 我们在不改变上面代码的基础上,添加比较器Comparetor接口来完成排序;
- 先创建一个类,用这个类实现Comparetor接口,并重写里面的compare(T o1, T o2)方法,
- 使其优先比较名字,名字相同再比较学号。
- 然后在TreeSet集合定义时,将Comparetor对象作为参数传递给集合对象;这样集合对象就有比较性了!
先查看相关文档:
我们也看一下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;
}
}
运行结果:
总结:
无论哪一种排序方法,底层的数据结构都是二叉树。**