Java中TreeSet集合也是Set集合的一种。
其特点是唯一,有序。
TreeSet集合的排序方式有两种:
A:自然排序
B:比较器排序
1.自然排序
TreeSet<Student> st=new TreeSet<Student>();
TreeSet的无参构造默认其排序方式是自然排序,实现方法如下:
package Test1;
import java.util.TreeSet;
import Test2.Student;
/*
* TreeSet<Student> st=new TreeSet<Student>();
* 这是无参构造,默认为自然排序,所以Student类需要实现Comparable<Student>接口
*
* 按照年龄排序
*/
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Student> st=new TreeSet<Student>();
Student s1=new Student("小明", 22);
Student s2=new Student("小红", 30);
Student s3=new Student("小刚", 20);
Student s4=new Student("小李", 30);
Student s5=new Student("小王", 24);
Student s6=new Student("小明", 22);
Student s7=new Student("小智", 22);
st.add(s1);
st.add(s2);
st.add(s3);
st.add(s4);
st.add(s5);
st.add(s6);
st.add(s7);
for(Student s:st) {
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
package Test1;
public class Student implements Comparable<Student>{
private String name;
private int age;
public Student(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;
}
@Override
public int compareTo(Student s) {
//判断年龄
int num=this.age-s.age;
//判断姓名
//compareTo() 字符串比较,如果相同返回0
//如果num等于0(说明年龄相同),就比较姓名
int num2=num==0?this.name.compareTo(s.name):num;
return num2;
}
}
需要注意的是在Student类中需要实现接口 Comparable<Student>的compareTo()方法,在实现过程中要注意主要排序规则和次要排序规则都要判断。比如这里的主要排序规则是年龄,但是姓名也是需要进行判断的。
2.比较器排序
TreeSet<Student> st=new TreeSet<Student>(new MyComparator());
比较器排序采用带参构造,其参数是对象,较自然排序而言稍微复杂了一点。
实现方法如下:
package Test2;
import java.util.Comparator;
import java.util.TreeSet;
/*
* 按照姓名长度排序
*
* 比较器排序
*/
public class TreeSetDemo {
public static void main(String[] args) {
//TreeSet<Student> st=new TreeSet<Student>();
TreeSet<Student> st=new TreeSet<Student>(new MyComparator());
Student s1=new Student("xiaoming", 22);
Student s2=new Student("xiaomei", 30);
Student s3=new Student("xiaogang", 20);
Student s4=new Student("xiaoli", 30);
Student s5=new Student("xiaowang", 24);
Student s6=new Student("xiaoming", 22);
Student s7=new Student("xiaozhi", 22);
st.add(s1);
st.add(s2);
st.add(s3);
st.add(s4);
st.add(s5);
st.add(s6);
st.add(s7);
for(Student s:st) {
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
package Test2;
public class Student{
private String name;
private int age;
public Student(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;
}
}
package Test2;
import java.util.Comparator;
public class MyComparator implements Comparator<Student>{
@Override
//在自然排序中,因为Student中有this表示当前的对象,所以在
//compareTo()方法中只有一个参数,但是在这里因为没有this,所以要有两个参数
public int compare(Student s1, Student s2) {
//判断姓名长度
//因为在Student类中成员变量是private,所以不能直接访问
int num=s1.getName().length()-s2.getName().length();
//判断姓名内容
int num2=num==0?s1.getName().compareTo(s2.getName()):num;
//判断年龄
int num3=num2==0?s1.getAge()-s2.getAge():num2;
return num3;
}
}
在这里Students类不需要在实现 Comparator<Student>接口,但是需要再写一个类MyComparator,在这个类中实现compare()方法,以此实现排序。那么问题来了,如果使用比较器排序,还需要再写一个类,较自然排序就要麻烦一点,那我们为什么要使用比较器排序呢?
其实在开发过程中,比较器排序还是比较常用的,因为它还有另外一种写法。
package Test2;
import java.util.Comparator;
import java.util.TreeSet;
/*
* 按照姓名长度排序
*
* 比较器排序
*/
public class TreeSetDemo {
public static void main(String[] args) {
//TreeSet<Student> st=new TreeSet<Student>();
//如果一个方法的参数是接口,那么真正要的是接口实现类的对象
//而匿名内部类就可以实现这个东西
TreeSet<Student> st=new TreeSet<Student>(new Comparator<Student>() {
public int compare(Student s1, Student s2) {
//判断姓名长度
//因为在Student类中成员变量是private,所以不能直接访问
int num=s1.getName().length()-s2.getName().length();
//判断姓名内容
int num2=num==0?s1.getName().compareTo(s2.getName()):num;
//判断年龄
int num3=num2==0?s1.getAge()-s2.getAge():num2;
return num3;
}
});
Student s1=new Student("xiaoming", 22);
Student s2=new Student("xiaomei", 30);
Student s3=new Student("xiaogang", 20);
Student s4=new Student("xiaoli", 30);
Student s5=new Student("xiaowang", 24);
Student s6=new Student("xiaoming", 22);
Student s7=new Student("xiaozhi", 22);
st.add(s1);
st.add(s2);
st.add(s3);
st.add(s4);
st.add(s5);
st.add(s6);
st.add(s7);
for(Student s:st) {
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
使用匿名内部类直接实现排序,当排序方式改变时,只需要在造对象时直接实现就可以了,不需要在改别的代码 ,这样就大大的提高了程序的灵活性,更贴合面向对象的思想。