前言
關於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)
方法,這樣就違反了開閉原則。綜上,第二種方法比第一種方法更加靈活。