Java-對象排序


在業務邏輯中,我們經常需要對list進行排序,就像下面這樣:

Collections.sort(l);

如果l中的元素是String類型,你會發現sort方法將使用字母順序排序。如果l中的元素是Date類型,sort方法將使用日歷順序排序。這是因為String和Date都實現了Comparable接口,也就是說,如果你想對某種對象進行排序,那么它必須實現Comparable接口。在Java語言中,實現該接口的類羅列如下:

Classes Implementing Comparable
Class Natural Ordering
Byte Signed numerical
Character Unsigned numerical
Long Signed numerical
Integer Signed numerical
Short Signed numerical
Double Signed numerical
Float Signed numerical
BigInteger Signed numerical
BigDecimal Signed numerical
Boolean Boolean.FALSE < Boolean.TRUE
File System-dependent lexicographic on path name
String Lexicographic
Date Chronological
CollationKey Locale-specific lexicographic

如果某個類是別人寫的,它確實沒有實現該接口,那就對排序問題無能為力了么?不是的,sort還有另一種形式:

Collections.sort(list, comparator)
只有這兩種方法。如果以上兩種方法你都沒有做,那么sort方法將拋出異常。 
Comparable接口
Comparable接口形式如下:
public interface Comparable<T> {
    public int compareTo(T o);
}
是的,它只有一個方法。你必須在該方法中定義對象是如何比較的。下面是一個demo:
SortDemo.java
package Colloections;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class SortDemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new SortDemo().sort();
    }   private void sort(){
        Person p1 = new Person("bob", 5);
        Person p2 = new Person("albert", 8);
        Person p3 = new Person("bob", 13);
        
        List<Person> list = new ArrayList<Person>();
        list.add(p1);
        list.add(p2);
        list.add(p3);
        System.out.printf("排序前:%n");
        for (Person person : list) {
            System.out.printf(person.toString());
        }
        
        Collections.sort(list);
        System.out.printf("排序后:%n");
        for (Person person : list) {
            System.out.printf(person.toString());
        }
    }
}


class Person implements Comparable<Person>{

    public String name;
    public int age;
    
    public Person(String n, int a){
        name = n;
        age = a;
    }
    
    public  String toString() {
        return String.format("Name is %s, Age is %d%n", name, age);
    }
    
    @Override
    public int compareTo(Person o) {
        // TODO Auto-generated method stub
        //排序優先級為:姓名/年齡
        int nameComp = this.name.compareTo(o.name);
        return (nameComp != 0 ? nameComp : (this.age - o.age));
    }
}

 

程序輸出如下:

排序前:
Name is bob, Age is 5
Name is albert, Age is 8
Name is bob, Age is 13
排序后:
Name is albert, Age is 8
Name is bob, Age is 5
Name is bob, Age is 13

 

Comparator

Comparator接口提供一個獨立的排序功能,這有兩個用處:1.你不想使用某個類自帶的compareTo邏輯進行排序;2.某個類並沒有繼承Comparable接口。可見,Comparator接口使得排序更加靈活。它的形式如下所示:
public interface Comparator<T> {
    int compare(T o1, T o2);
}

是的,一個方法就夠了。當o1比o2小於,等於,大於時,compare方法將返回一個負數,零或者正數。使用demo如下:

 

SortDemo.java

package Colloections;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class SortDemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //new SortDemo().sort();
        new SortDemo().sortByComparatpr();
    }
    
    private void sortByComparatpr(){
        Person p1 = new Person("bob", 5);
        Person p2 = new Person("albert", 8);
        Person p3 = new Person("bob", 13);
        
        List<Person> list = new ArrayList<Person>();
        list.add(p1);
        list.add(p2);
        list.add(p3);
        System.out.printf("排序前:%n");
        for (Person person : list) {
            System.out.printf(person.toString());
        }
        
        PersonComparator comparator = new PersonComparator();
        Collections.sort(list, comparator);
        System.out.printf("排序后:%n");
        for (Person person : list) {
            System.out.printf(person.toString());
        }
    }
    
    private void sort(){
        Person p1 = new Person("bob", 5);
        Person p2 = new Person("albert", 8);
        Person p3 = new Person("bob", 13);
        
        List<Person> list = new ArrayList<Person>();
        list.add(p1);
        list.add(p2);
        list.add(p3);
        System.out.printf("排序前:%n");
        for (Person person : list) {
            System.out.printf(person.toString());
        }
        
        Collections.sort(list);
        System.out.printf("排序后:%n");
        for (Person person : list) {
            System.out.printf(person.toString());
        }
    }
}


class Person implements Comparable<Person>{

    public String name;
    public int age;
    
    public Person(String n, int a){
        name = n;
        age = a;
    }
    
    public  String toString() {
        return String.format("Name is %s, Age is %d%n", name, age);
    }
    
    @Override
    public int compareTo(Person o) {
        // TODO Auto-generated method stub
        //排序優先級為:姓名/年齡
        int nameComp = this.name.compareTo(o.name);
        return (nameComp != 0 ? nameComp : (this.age - o.age));
    }
}



class PersonComparator implements Comparator<Person>{

    @Override
    public int compare(Person o1, Person o2) {
        // TODO Auto-generated method stub
        
        return o2.compareTo(o1);
    }
}

程序輸出如下:

排序前:
Name is bob, Age is 5
Name is albert, Age is 8
Name is bob, Age is 13
排序后:
Name is bob, Age is 13
Name is bob, Age is 5
Name is albert, Age is 8

注意,這里的輸出是降序排列的,因為在compare方法中使用o2與o1進行了比較。如果需要升序排列,則如下修改即可:

return o1.compareTo(o2);

注意,不要這樣修改:

return -o2.compareTo(o1);

這是因為compareTo返回的負數值是不確定的,而有一個特殊的負整數,取負時結果仍為負數:

-Integer.MIN_VALUE == Integer.MIN_VALUE

 

 


免責聲明!

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



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