问题场景:
TreeSet
是采用有序的二叉树进行存取,有序且是自然顺序,如果不是自然顺序就会出现一些小问题
问题描述:
存储系统默认的自然顺序
package train4.train4_3;
import java.util.*;
public class treeset {
public static void main(String[] args) {
TreeSet<Integer> data = new TreeSet<>();
data.add(1);
data.add(3);
data.add(4);
data.add(2);
data.add(0);
for(int i:data) {
System.out.println(i);
}
}
}
使用了forEach迭代循环遍历输出
结果:
0
1
2
3
4
当我们所创建的TreeSet
数据不是系统默认的自然数据而是自定义的Person
内容,就会出现问题,例如。
package train4.train4_3;
import java.util.*;
public class treeset2 {
public static void main(String[] args) {
TreeSet<Person> data = new TreeSet<>();
Person p1 = new Person("张三",18);
Person p2 = new Person("李四",20);
Person p3 = new Person("王二",17);
data.add(p1);
data.add(p2);
data.add(p3);
for(Person p:data) {
System.out.println(p);
}
}
//定义Person类
static class Person{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
}
这里定义了一个Person
类型的TreeSet
数据。
TreeSet<Person> data = new TreeSet<>();
运行结果:
java.lang.ClassCastException
类型转换异常,意思是将treeset2
文件中的Person
类转成Comparable
类转换失败
原因分析:
因为我们所存储的数据是自定义的Person
类型,当然不能用系统定义的方法去实现,系统也不知道你定义的数据如何排序。
解决方案:
Comparable
是一个接口,我们可以实现这个接口进行重写,我们自己去规定比较大小的规则。
static class Person implements Comparable<Person>
这个时候还是会报错,是因为接口是抽象的,我们需要实现抽象方法。
@Override
public int compareTo(Person arg0) {
// TODO Auto-generated method stub
return 0;
}
现在我们来解决问题,重写这个compareTo
方法。
比较的原理就是通过
Person
调用compareTo
方法,然后把另一个要比较的数据传进来,进行比较,实际上是通过this
与arg0
进行比较。
@Override
public int compareTo(Person arg0) {
//this 与 arg0 在比较
//返回的数据:负数(表示this小)||零(表示一样大)||正数(表示this大)
if(this.age>arg0.age) {
return 1;
}else if(this.age==arg0.age){
return 0;
}
return -1;
}
完整代码如下:
package train4.train4_3;
import java.util.*;
public class treeset2 {
public static void main(String[] args) {
TreeSet<Person> data = new TreeSet<>();
Person p1 = new Person("张三",18);
Person p2 = new Person("李四",20);
Person p3 = new Person("王二",17);
data.add(p1);
data.add(p2);
data.add(p3);
for(Person p:data) {
System.out.println(p);
}
}
static class Person implements Comparable<Person>{
private String name;
private int age;
@Override
public int compareTo(Person arg0) {
//this 与 arg0 在比较
//返回的数据:负数(表示this小)||零(表示一样大)||正数(表示this大)
if(this.age>arg0.age) {
return 1;
}else if(this.age==arg0.age){
return 0;
}
return -1;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
}
运行结果:
Person [name=王二, age=17]
Person [name=张三, age=18]
Person [name=李四, age=20]
我们知道TreeSet
是Set
集合的一种,而Set
集合有一个特点:不允许重复的数据存在,如果存储了一下数据。
Person p1 = new Person("张三",18);
Person p2 = new Person("李四",20);
Person p3 = new Person("王二",17);
Person p4 = new Person("麻子",17);
data.add(p1);
data.add(p2);
data.add(p3);
data.add(p4);
则麻子的数据是存储失败的,因为在进行compareTo
方法时,返回的时0,存储失败,运行结果如下:
Person [name=王二, age=17]
Person [name=张三, age=18]
Person [name=李四, age=20]