前言
关于Java中的排序,我们常见的就是对Array
、List
进行排序,对于Array
,我们可以使用Arrays.sort(数组)
进行排序;对于List,我们可以使用Collections.sort(list)
进行排序
,如果是需要对一个实体类的对象进行排序呢?
两种实现方法
有两种方法可以实现。
- 一种方法是类实现
Comparable<T>
接口,然后调用Collections.sort(List)
方法进行排序。 - 另一种方法是类不实现Comparable接口,而在排序时使用
Collections.sort(List, Comparator<T>)
方法,并实现其中的Comparator<T>
接口。
Comparable
接口有一个comparTo(Object o)
方法,它返回整数类型。对于表达式x.compareTo(y)
,**如果返回值为0,则表示x和y相等,如果返回值大于0,则表示x大于y,如果返回值小于0,则表示x小于y;**这是一个比较器接口。
排序实现
模拟一个Person
对象,要对其进行排序,排序的条件是先根据id排序,当id相等的情况下载根据年龄进行排序,当年龄相等再根据名字。
通过类实现Comparable接口进行排序
Person类
public static class Person implements Comparable<Person> {
//非 int、float等基本类型
private Integer id;
private Integer age;
private String name;
public Person(Integer age, String name, Integer id) {
this.age = age;
this.name = name;
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person [id=" + id + ", age=" + age + ", name=" + name + "]";
}
/*
* (non-Javadoc)
*
* @see java.lang.Comparable#compareTo(java.lang.Object)
* 先根据id比较,如果id相同,就比较age,最后再比较name(按姓名的字典序升序排序)
*/
@Override
public int compareTo(Person o) {
if (this.id > o.getId()) {
return 1;
} else if (this.id < o.getId()) {
return -1;
} else {
if (this.age > o.getAge()) {
return 1;
} else if (this.age < o.getAge()) {
return -1;
} else {
return this.name.compareTo(o.getName());
}
}
}
}
在客户端中测试
public class Compareto {
public static void main(String[] args) {
List<Person> students = new ArrayList<>();
students.add(new Person(25, "LuanYu",0));
students.add(new Person(26, "LuanYu",0));
students.add(new Person(26, "LuanYu",5));
students.add(new Person(27, "LiuBei",1));
students.add(new Person(27, "Zhangi",1));
Collections.sort(students);
for(Person student:students){
System.out.println(student.toString());
}
}
输出结果
Person [id=0, age=25, name=LuanYu]
Person [id=0, age=26, name=LuanYu]
Person [id=1, age=27, name=LiuBei]
Person [id=1, age=27, name=Zhangi]
Person [id=5, age=26, name=LuanYu]
可以看到,按姓名的字典序升序排序。使用这用方法排序不能使用基本类型(int, float)等。
通过Comparable接口实现排序
Person类
/**
* 没有实现Comparable<T>接口的Person类
*/
public static class Person {
private Integer id;
private Integer age;
private String name;
public Person(Integer age, String name, Integer id) {
this.age = age;
this.name = name;
this.id = id;
}
@Override
public String toString() {
return "Person [id=" + id + ", age=" + age + ", name=" + name + "]";
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
main方法
public static void main(String[] args) {
List<Person> persons = new ArrayList<>();
persons.add(new Person(25, "LsanYu", 0));
persons.add(new Person(26, "LuanYu", 0));
persons.add(new Person(26, "LuanYu", 5));
persons.add(new Person(27, "LiuBei", 1));
persons.add(new Person(27, "Zhangi", 1));
Collections.sort(persons, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
// 这里是需要做处理的部分
if (o1.getId() > o2.getId()) {
return 1;
}else if (o1.getId() < o2.getId()) {
return -1;
}else {
if (o1.getAge()>o2.getAge()) {
return 1;
}else if (o1.getAge() < o2.getAge()) {
return -1;
}else {
return o1.getName().compareTo(o2.getName());
}
}
}
});
for(Person person:persons){
System.out.println(person.toString());
}
}
输出结果
Person [id=0, age=25, name=LsanYu]
Person [id=0, age=26, name=LuanYu]
Person [id=1, age=27, name=LiuBei]
Person [id=1, age=27, name=Zhangi]
Person [id=5, age=26, name=LuanYu]
总结
- 第二种方法通过重新定义
Collections.sort(List,Comparator)
实现排序,当需求有变需要按照其他规则(比如id)排序时,只有重新定义一个Comaprator
,而不用修改Person
类,然后修改客户端代码,这样就基本满足了开闭原则,即可以通过增加新类方便的扩充新功能,满足新需求而不用修改原来的代码。 - 如果我们采用让
Person
实现Comaparable
接口,则在想采用新的排序规则时,必须修改Person里的comareTo(Object o)
方法,这样就违反了开闭原则。综上,第二种方法比第一种方法更加灵活。