java對象比較排序


參考:改善java代碼的151個建議-73建議:使用Compatator排序

  在項目開發中,我們經常要對一組數據排序,或者升序或者降序,在java中排序有多種方式,最土的方法就是自己寫排序算法,比如冒泡排序,快速排序,二叉樹排序等,但一般不要自己寫,jdk已經為我們提供了很多的 排序算法,我們采用拿來主義就成了。

 

在java中,要給數據排序,有兩種實現方式,分別實現兩個接口:

  1. 一種是實現Comparable接口
  2. 另一種是實現Comparator接口

  在JDK類庫中,有一部分類實現了Comparable接口,如Integer Double和String等。 
 Comparable接口有一個comparTo(Object o)方法,它返回整數類型。對於表達式x.compareTo(y),如果返回值為0,則表示x和y相等,如果返回值大於0,則表示x大於y,如果返回值小於0,則表示x小於y.

 

 

    查看Comparable接口源碼

public interface Comparable<T> {
    public int compareTo(T o);
}

 舉個例子:

      給公司職員排序,按照工號排序,先定義一個職員類

編寫Employee類實現Comparable接口

package hello;

import org.apache.commons.lang3.builder.CompareToBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;


public class Employee implements Comparable<Employee>{
    //id是根據進入公司的先后順序編碼的
    private int id;
    //姓名
    private String name;
    //職位
    private Position position;
    public Employee(int id, String name, Position position) {
        super();
        this.id = id;
        this.name = name;
        this.position = position;
    }
    //按照id號排序,也就是資歷的深淺排序
    @Override
    public int compareTo(Employee o) {
        // TODO Auto-generated method stub
        return new CompareToBuilder().append(id, o.id).toComparison();
    }
    @Override
    public String toString(){
         return ToStringBuilder.reflectionToString(this);
    }
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Position getPosition() {
        return position;
    }

    public void setPosition(Position position) {
        this.position = position;
    }

}

     這是一個簡單的javabean,描述的是一個員工的基本信息,其中id是員工編號,按照進入公司的先后順序編碼,position是崗位描述,表示是經理還是普通職員,這是一個枚舉類型:

public enum Position {
  Boss, Manager,staff
}

   職位有三個級別:

  Boss(老板), Manager(經理), Staff(職員)

  • 按id排序

Employee類的compareTo()方法,是Comparable接口必須要實現的方法,使用apach的工具類來實現,表明是按照id的自然序列排序的(升序)。一切准備完畢,我們看看如何排序:

package hello;

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

public class HelloWord {

    public static void main(String[] args) {
        List<Employee> list = new ArrayList<Employee>(5);
        // 一個老板
        list.add(new Employee(1001, "張三", Position.Boss));
        // 兩個經理
        list.add(new Employee(1006, "趙四", Position.Manager));
        list.add(new Employee(1003, "王五", Position.Manager));
        // 兩個職員
        list.add(new Employee(10002, "李六", Position.staff));
        list.add(new Employee(1005, "馬牛", Position.staff));
        // 按照id排序,也就是按照資歷深淺排序
        Collections.sort(list);
        for (Employee e : list) {
            System.out.println(e);
        }
    }
}

【運行結果】:

hello.Employee@46244bb9[id=1001,name=張三,position=Boss]
hello.Employee@4b5d7792[id=1003,name=王五,position=Manager]
hello.Employee@3e0a765c[id=1005,name=馬牛,position=staff]
hello.Employee@7fbb6976[id=1006,name=趙四,position=Manager]
hello.Employee@6909037d[id=10002,name=李六,position=staff]

是按照id升序排列的,結果正確。

  • 按職位排序

本着“領導為先”的理念,按職位從高到低排序,先是老板,然后是經理,最后是普通職員,Employee已經是一個穩定類,為了一個排序功能修改它,影響按照id排序,不是一個好辦法。

Collections.sort()方法有一個重載方法sort(List<T> list, Comparator<? super T> c),有一個Comparator接口參數,我們實現這個接口:

//職位排序器
class PositionComparator implements Comparator<Employee>{
    @Override
    public int compare(Employee o1, Employee o2) {
        //按照職位降序排列
        return o1.getPosition().compareTo(o2.getPosition());
    }

創建了一個職位排序法,按職位高低排序,測試一下:

        Collections.sort(list, new PositionComparator());
        for (Employee e : list) {
            System.out.println(e);
        }

【運行結果】:

hello.Employee@46244bb9[id=1001,name=張三,position=Boss]
hello.Employee@4b5d7792[id=1003,name=王五,position=Manager]
hello.Employee@7fbb6976[id=1006,name=趙四,position=Manager]
hello.Employee@3e0a765c[id=1005,name=馬牛,position=staff]
hello.Employee@6909037d[id=10002,name=李六,position=staff]

 按照職位排序,結果正確。

 

  • 按照職位從低到高排序

 為了照顧員工,需要按職位由低到高排序

兩個辦法:

  1. Collections.reverse(List<?> list)方法實現倒序排列
  2. Collections.sort(List<?> list,Collections.reverseOrder(new PositionComparator())也可以

用這兩個方法來測試:

        Collections.reverse(list);
        for (Employee e : list) {
            System.out.println(e);
        }

        System.out.println("----");
        Collections.sort(list,
                Collections.reverseOrder(new PositionComparator()));
        for (Employee e : list) {
            System.out.println(e);
        }

【運行結果】:

hello.Employee@6909037d[id=10002,name=李六,position=staff]
hello.Employee@3e0a765c[id=1005,name=馬牛,position=staff]
hello.Employee@7fbb6976[id=1006,name=趙四,position=Manager]
hello.Employee@4b5d7792[id=1003,name=王五,position=Manager]
hello.Employee@46244bb9[id=1001,name=張三,position=Boss]
----
hello.Employee@6909037d[id=10002,name=李六,position=staff]
hello.Employee@3e0a765c[id=1005,name=馬牛,position=staff]
hello.Employee@7fbb6976[id=1006,name=趙四,position=Manager]
hello.Employee@4b5d7792[id=1003,name=王五,position=Manager]
hello.Employee@46244bb9[id=1001,name=張三,position=Boss]

按照職位由地到高排序,結果正確

 

  •  先按職位排序,職位 相同按id排序

在compareTo或compare方法中先判斷職位是否相等,職位相等再根據工號排序

修改Employee類的compareTo()方法為

    @Override
    public int compareTo(Employee o) {
        return new CompareToBuilder()
            .append(position, o.position)    //按照職位排序
            .append(o.id,id).toComparison(); //工號排序
    }

排序代碼:

        Collections.sort(list);
        for (Employee e : list) {
            System.out.println(e);
        }

【運行結果】:

hello.Employee@4d871a69[id=1001,name=張三,position=Boss]
hello.Employee@631803fb[id=1006,name=趙四,position=Manager]
hello.Employee@4b5d7792[id=1003,name=王五,position=Manager]
hello.Employee@655538e5[id=1005,name=馬牛,position=staff]
hello.Employee@20e0b1d6[id=1002,name=李六,position=staff]

總結:

  1.  實現了Comparable接口類表明自身可比較,有了比較才能進行排序;
  2. Comparator接口是一個工具類接口,用作比較,與原類的邏輯沒有關系;

 


免責聲明!

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



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