TreeSet:
可以对Set集合中的元算进行排序,底层数据结构是二叉树,保证元素唯一性的依据是compareto方法返回0;
TreeSet第一种排序方式:
让元素自身具备比较性,元素需要实现comparable接口,覆盖compareto方法,这种方式也称为元素的自然顺序,或者叫做默认顺序。
例子:往TreeSet集合中存储自定义对象学生,想按照学生的年龄进行排序。(升序)
import java.util.Iterator;
import java.util.TreeSet;
/**Tree小练习,自定义排序规则
* @author Administrator
*/
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<Student>();
ts.add(new Student("a",35));
ts.add(new Student("z",10));
ts.add(new Student("z",10));//重复项,被过滤掉
ts.add(new Student("c",20));
ts.add(new Student("aa",24));
ts.add(new Student("a",40));
Iterator<Student> it = ts.iterator();
while(it.hasNext()){
Student s = it.next();
System.out.println(s.getName()+":"+s.getAge());
}
}
}
/**
* 实现Comparable接口,让元素自身具有比较性
* @author Administrator
*
*/
class Student implements Comparable{
private String name;
private int age;
public Student(String name, int age) {
super();
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;
}
/**自定义排序,按照年龄排序
* @return int
* 比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
*/
@Override
public int compareTo(Object o) {
if (!(o instanceof Student))
throw new RuntimeException("不是学生对象");
Student s = (Student) o;
// System.out.println(this.name+"compareto "+s.name);//验证调用次数而添加的标记
if(this.age > s.age)
return 1;
if(this.age == s.age)
return this.name.compareTo(s.name);
return -1;
// return -1; //这种方式按照插入顺序取出元素,而且是可以有重复元算
}
public String toString() {
return name+age;
}
@Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
System.out.println("这个刚发根本不会调用");
return super.equals(obj);
}
}
TreeSet第二种排序方式:
当元素自身不具备比较性,或者具备的比较性不是所需要的。这里就需要让集合自身具备比较性。在集合初始化时就有了比较方式。实现方式就是自定义比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
例子:以前是按照学生的年龄排序,现在想按照姓名排序,在不该变学生类的前提下。Student类还使用上面的那个。
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
/**当元素自身不具备比较性,或者具备的比较性不是所需要的。
* 这是就需要让集合自身具备比较性。在集合初始化时就有了比较方式。
* 这就需要自定义比较器:定义一个类,实现comparator接口,覆盖compare方法
* @author Administrator
*
*/
public class TreeSetDemo2 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeSet<Student> ts = new TreeSet<Student>(new MyCompare());
ts.add(new Student("a",35));
ts.add(new Student("z",10));
ts.add(new Student("z",10));//重复项,被过滤掉
ts.add(new Student("c",20));
ts.add(new Student("aa",24));
ts.add(new Student("a",40));
Iterator it = ts.iterator();
while(it.hasNext()){
Student s = (Student) it.next();
System.out.println(s.getName()+":"+s.getAge());
}
}
}
/**
* 自己的比较器
* @author Administrator
*
*/
class MyCompare implements Comparator{
/**按照姓名排序,
* @return int
* 比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
*/
@Override
public int compare(Object o1, Object o2) {
Student s1 = (Student)o1;
Student s2 = (Student)o2;
// return s1.getName().compareTo(s2.getName());//按照姓名
int num = s1.getName().compareTo(s2.getName());
if(num == 0){
// return s1.getAge()- s2.getAge();
/*
if(s1.getAge() > s2.getAge())
return 1;
if(s1.getAge() == s2.getAge())
return 0;
return -1;
*/
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
}
return num ;
}
}
注意;排序时,当主要条件相同时,一定要判断次要条件。当两种排序都存在时以比较器为主。
Comparator可以看成一种将算法和数据分离,开发中推荐使用
Comparator也可以在下面两种环境下使用:
1、原类定义时没有实现Comparable,无法自动排序的,可以通过Comparator来实现排序而不必改变对象本身
2、需要使用多种排序标准的,比如升序、降序、按照某些特定规则排序等。
最后提一下:如果是用数组存储元素可以使用Arrays.sort()进行自动排序,因为本例是学习TreeSet,所以没有给出例子。
static
| sort(T[] a,Comparator<? super T> c) | |
static
| sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c) |