在项目开发中,经常回用到容器排序,而它们的写法比较固定,今天就来总结一下.
pojo类如下:
package com.ldh;
public class Student implements Comparable<Student> {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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 o) {
return new Integer(age).compareTo(new Integer(o.getAge()));
}
}
再创建四个Student对象:
Student st1 = new Student();
st1.setName("zhangsan1");
st1.setId(1);
st1.setAge(30);
Student st2 = new Student();
st2.setName("zhangsan2");
st2.setId(2);
st2.setAge(20);
Student st3 = new Student();
st3.setName("zhangsan3");
st3.setId(3);
st3.setAge(10);
Student st4 = new Student();
st4.setName("zhangsan4");
st4.setId(4);
st4.setAge(10);
用TreeSet对上述四个Student对象排序并打印出结果:
Set<Student> set = new TreeSet<Student>();
set.add(st1);
set.add(st2);
set.add(st3);
set.add(st4);
for(Student st : set){
System.out.println(st.getAge());
}
System.out.println(set.size());
打印出的结果如下:
10
20
30
3
TreeSet底层排序算法是二叉树,如果两个元素比较的结果为0,就被视为同一个元素.如果 Student没有实现Comparable接口,也可以通过以下方式实现排序:
Set<Student> set = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return new Integer(o1.getAge()).compareTo(new Integer(o2.getAge()) );
}
});
最终打印出的结果和实现Comparable接口一样.TreeSet的底层实现结构是TreeMap,TreeSet就是value都相同的TreeMap,因此TreeMap也有上述两种排序方式.
再看来看一下List的排序,同样是上面的四个对象,都实现Comparable接口.
List<Student> slist = new LinkedList<Student>();
slist.add(st1);
slist.add(st2);
slist.add(st3);
slist.add(st4);
Collections.sort(slist);
for(Student st : slist){
System.out.println(st.getAge());
}
System.out.println(slist.size());
上面这段代码打印的结果是
10
10
20
30
4
通过上面的结果可以看到,List排序四个元素都打印出来,并且按正序排序,如果想按倒序排序,只需要
@Override
public int compareTo(Student o) {
return -new Integer(age).compareTo(new Integer(o.getAge()));
}
在原来的基础上加一个"-"负号就可以了.
同样List也可以用实现Comparator接口进行排序,如下:
List<Integer> list = new LinkedList<Integer>();
list.add(new Integer(5));
list.add(new Integer(3));
list.add(new Integer(4));
list.add(new Integer(3));
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
for(Integer letter : list){
System.out.println(letter);
}
System.out.println(list.size());
排序结果:
3
3
4
5
4
List的实现ArrayList也同样可以上面的两种排序,
LinkedList是链表结构,增加,删除效率高,但查找由于要移动指针,效率就低了.
ArrayList底层的
实现了基于动态数组的数据结构,查找效率高,但
增加,删除由于涉及到数据移动,效率就没有
LinkedList高了.实际项目具体用哪一个,看实际情况.
对于容器排序是实现
Comparable接口还是
Comparator接口,我推荐
Comparator接口,因为
Comparator与原来的代码的耦合性低,比如刚开始的需求不需要排序,而后来又需要排序,但又想尽量少动原来的代码,
Comparator接口就比较适合了.同时对于同一个对象,有的地方想这样排,另一个地方又想那样排,这是你发现还是
Comparator比较好,多实现几个
Comparator就行了.