Java ArrayList中對象的排序 (Comparable VS Comparator)


我們通常使用Collections.sort()方法來對一個簡單的數據列表排序。但是當ArrayList是由自定義對象組成的,就需要使用comparable或者comparator接口了。在使用這兩者進行排序之前,先嘗試不實現任何接口來進行排序。

考慮下面的例子——有一個Student類,具有三個屬性:name, rollno, age

public class Student  {
    private String name;
    private int rollno;
    private int age;
    
    /* 有參構造 ...*/   
    /* getter and setter ...*/   
}

然后需要一個Student組成的ArrayList:

import java.util.*;
public class ArrayListSorting  {

     public static void main(String args[]){
       ArrayList<Student> arraylist = new ArrayList<Student>();
       arraylist.add(new Student(223, "Chaitanya", 26));
       arraylist.add(new Student(245, "Rahul", 24));
       arraylist.add(new Student(209, "Ajeet", 32));

       Collections.sort(arraylist);

       for(Student str: arraylist){
            System.out.println(str);
       }
     }
}

這里嘗試去調用Collections.sort()方法,但是出錯了:

Exception in thread “main” java.lang.Error: Unresolved compilation problem:
Bound mismatch: The generic method sort(List) of type Collections is not applicable for the arguments (ArrayList). The inferred type Student is not a valid substitute for the bounded parameter > at beginnersbook.com.Details.main(Details.java:11)

原因:對於排序的ArrayList,除非其中元素實現了Comparable或者Comparator接口,否則不能調用Collections.sort方法。

使用Comparable對ArrayList<Object>進行排序

我們想要根據age對Student進行排序——實現Comparable接口,重寫compareTo方法。

package beginnersbook.com;

public class Student implements Comparable {
    private String name;
    private int rollno;
    private int age;

    /* 有參構造 */
    ...
    //getter and setter methods
    ...
    @Override
    public int compareTo(Student comparestu) {
        int compareAge=((Student)comparestu).getAge();
        /* 正序排列 */
        return this.age-compareAge;

        /* 逆序排列 */
        //return compareAge-this.age;
    }

    @Override
    public String toString() {
        return "[ rollno=" + rollno + ", name=" + name + ", age=" + age + "]";
    }

}

現在我們可以正常調用Collections.sort方法了。

既然Comparable完成了我們的工作,為什么還需要Comparator呢?

使用Comparable接口我們只能根據一個屬性對ArrayList進行排序。為了讓排序可以根據多個屬性進行,需要使用Comparator。

使用Comparator對ArrayList<Object>進行排序(多個屬性)

重寫Comparatorcompare方法:

import java.util.Comparator;
public class Student  {
    private String name;
    private int rollno;
    private int age;

    /* 有參構造 */
    ...
    //Getter and setter methods
    ...
    /* 根據name進行排序 */
    public static Comparator<Student> NameComparator = new Comparator<Student>() {

    public int compare(Student s1, Student s2) {
       String name1 = s1.getName().toUpperCase();
       String name2 = s2.getName().toUpperCase();

       // 正序排列
       return StudentName1.compareTo(StudentName2);

       // 逆序排列
       //return StudentName2.compareTo(StudentName1);
    }};

    /* 根據rollno進行排序 */
    public static Comparator<Student> StuRollno = new Comparator<Student>() {

      public int compare(Student s1, Student s2) {

         int rollno1 = s1.getRollno();
         int rollno2 = s2.getRollno();

         /* 正序排列 */
         return rollno1-rollno2;

         /* 逆序排列 */
         //return rollno2-rollno1;
    }};
    @Override
    public String toString() {
        return "[ rollno=" + rollno + ", name=" + name + ", age=" + age + "]";
    }

}

這樣,我們就既可以用name進行排序,也可以用age進行排序,只需要在有不同的排序需求時,使用不同的Comparator就可以了(e.g. Collections.sort(arraylist, Student.NameComparator))。

——以上內容譯自Java ArrayList of Object Sort Example (Comparable And Comparator)


多屬性組合排序

上面對Java的ArrayList自定義排序進行了基本介紹,下面是工作中遇到的一個需求:

對於一個漏洞,有兩個排序依據,首先根據是否修復來排序,其次按照嚴重程度排序,類似於SQL中的ORDER BY field1, field2,若field1相同,則比較field2

可以看到,右邊的一列是按照未修復,已修復的順序排列的,而左邊也是按照風險程度由高到低排列,但是分別對應了是否修復的順序。這種排序可以認為也是多屬性排序,但是與上邊講到的多屬性不同,這種方式是多種屬性結合的排序方式,

    public static Comparator<Loopholes> loopholesComparator = new Comparator<Loopholes>() {
        @Override
        public int compare(Loopholes l1, Loopholes l2) {
            Integer riskLevel1 =  l1.getRiskLevel();
            Integer riskLevel2 =  l2.getRiskLevel();
            Integer fixed1 = l1.getFixed();
            Integer fixed2 = l2.getFixed();
            int fixedComp = fixed1.compareTo(fixed2);
            if (fixedComp != 0) {
                return fixedComp;
            } else {
                return riskLevel1.compareTo(riskLevel2);
            }
        }
    };

首先用fixed1與fixed2進行比較,若兩者不相等,則直接排序,若兩者相等(即compartTo返回0),繼續比較風險等級並返回風險等級的排序結果。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM