Java對象排序之Comparator與Comparable

前言

關於Java中的排序,我們常見的就是對ArrayList進行排序,對於Array,我們可以使用Arrays.sort(數組)進行排序;對於List,我們可以使用Collections.sort(list)進行排序,如果是需要對一個實體類的對象進行排序呢?

兩種實現方法

有兩種方法可以實現。

  1. 一種方法是類實現Comparable<T>接口,然後調用Collections.sort(List)方法進行排序。
  2. 另一種方法是類不實現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]

總結

  1. 第二種方法通過重新定義Collections.sort(List,Comparator)實現排序,當需求有變需要按照其他規則(比如id)排序時,只有重新定義一個Comaprator,而不用修改Person類,然後修改客戶端代碼,這樣就基本滿足了開閉原則,即可以通過增加新類方便的擴充新功能,滿足新需求而不用修改原來的代碼。
  2. 如果我們採用讓Person實現Comaparable接口,則在想採用新的排序規則時,必須修改Person裏的comareTo(Object o)方法,這樣就違反了開閉原則。綜上,第二種方法比第一種方法更加靈活。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章