java的集合中,set主要有两种实现:HashSet和TreeSet。HashSet比较常用,TreeSet用的比较少,之前也没有对这个集合类型多做了解。这次准备课件的时候,简单写了下TreeSet的例子,发现了几个比较常见的问题,在这里记录一下。
首先,TreeSet是使用树结构来进行存储的,如果你debug一下TreeSet的插入过程,会发现TreeSet的对象说明中,会有一个root节点,也就是说树结构的根节点。对象按升序存储、访问和检索速度快。适用于快速检索的排序信息。
我在书写测试案例的时候,刚开始是这样写的:
`Student s1=new Student();
Student s2=new Student();
Student s3=new Student();
Student s4=new Student();
s1.setName("zhangsan");
s2.setName("lisi");
s3.setName("wangwu");
s4.setName("zhaoliu");
setHash.add(s1);
setHash.add(s2);
setHash.add(s3);
其中,Student的类为:
public class Student extends Person{
private String name;
private String age;
private String address;
@Override
public void say() {
System.out.println(this.name+","+this.age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
然后在运行的时候,提示报错,报错信息为
检查后发现,是因为Student类没有实现Comparable接口。我们上文讲过,TreeSet是树形结构存储且对象按升序存储。如果没有实现Comparable接口,则两个对象无法比较排序,TreeSet中无法确认新插入的数据的存放位置,所以就会提示异常。(当然,不是只有实现Comparable接口一个方法,只需要让两个对象可以比较大小即可)。在为泛型类实现了Comparable接口后,程序可以正常运行。
但紧接着,我又碰到了一个新的问题。代码如下:
在插入完成后,遍历输出TreeSet的数据。输出结果发现,T3的数据怎么都输出不出来。经过查询发现,原来是我Teacher(为了保留案例,我重新创建了个Teacher类替代Student类)的compareTo方法逻辑错误。原有代码为:
public int compareTo(Teacher tc) {
int result=0;
if(this.teachYears<tc.getTeachYears()){
result=-1;
}
return result;
}
这样就导致,新插入的元素的teachYears属性比原有元素大的时候,才会插入set,若比原有元素小,则compareTo的返回值为0,即认为新插入的元素重复了。TreeSet不允许插入重复元素。所以刚刚T3就不能插入到TreeSet了。我对compareTo方法进行了修改后,就可以正常运行了。
@Override
public int compareTo(Teacher tc) {
int result=0;
if(this.teachYears<tc.getTeachYears()){
result=-1;
}else if(this.teachYears>tc.getTeachYears()){
result=1;
}
return result;
}
总结一下:
- TreeSet中,元素是以树形结构存储的,且插入的元素按升序排序进行存储。
- TreeSet插入的对象,必须含有compareTo(或compare)方法,对两个对象进行比较,以便确认插入TreeSet的存储位置。
- TreeSet中不允许插入compareTo(或compare)方法返回值为0的两个对象(即不允许插入重复对象)。