2016-11-12 36 views
0

我試圖使用接口比較器來訂購一個優先隊列,這樣如果乘客的訂單有殘疾,他們的訂單就取決於第一個訂單,然後取決於他們有的票的類型以及最後的到達時間。如何將Comparator與多個字段對象一起使用?

import java.util.*; 

public static void main(String[] args){ 
    Random rand = new Random(System.nanoTime()); 
    Comparator<Passenger> comparator; 
    PriorityQueue<Passenger> queue = new PriorityQueue<Passenger>(10, comparator); 
    Passenger pass[] = new Passenger [10]; 


    for (int i=0; i<10;i++){ 
     int time1 = 0; 
     pass[i] = new Passenger(rand.nextInt(100000000), rand.nextInt(3) , rand.nextBoolean(), time1); 
     time1 = time1 + 15; 
    } 

} 

有我初始化乘客的陣列,這裏是頭等艙乘客和比較方法:

public class Passenger implements Comparator<Passenger>{ 

private int ID; 
private int clase; 
private boolean disability; 
private int arrivalTime; 

public Passenger(int ID, int clase, boolean disability, int arrivalTime) { 

    this.ID = ID; 
    this.clase = clase; // 0-vip 1-economy 2-economy 
    this.disability = disability; 
    this.arrivalTime = arrivalTime; 
} 
public int getID() { 
    return ID; 
} 
public void setID(int iD) { 
    ID = iD; 
} 
public int getClase() { 
    return clase; 
} 
public void setClase(int clase) { 
    this.clase = clase; 
} 
public boolean isDisability() { 
    return disability; 
} 
public void setDisability(boolean disability) { 
    this.disability = disability; 
} 
public int getArrivalTime() { 
    return arrivalTime; 
} 
public void setArrivalTime(int arrivalTime) { 
    this.arrivalTime = arrivalTime; 
} 

public int compare(Passenger pas1, Passenger pas2) { 
    if((pas1.isDisability()) && (!pas2.isDisability())){ 
     return 1;      //passenger 1 has disability 
    }else if((!pas1.isDisability()) && (pas2.isDisability())){ 
     return -1;       //passenger 2 has disability 
    } 
    else{         //both have disability or no one has disability 
     if(pas1.getClase() < pas2.getClase()){ 
      return 1;     // passenger 1 has better class 
     }else if(pas1.getClase() > pas2.getClase()){ 
      return -1;      // passenger 2 has better class 
     } 
     else{        //both have disability and same class 
      if(pas1.getArrivalTime() < pas2.getArrivalTime()){ 
       return 1;    //passenger 1 arrived before passenger 2 
      } 
      else return -1;     //passenger 2 arrived before passenger 1 
     } 
    } 
} 

我該如何處理以更好的方式,這些多層次的比較?

+1

所以具體是什麼問題呢?代碼是否會拋出錯誤?它排序不正確嗎? – Keiwan

+0

你比較,你通過一個構造函數的參數爲​​空 – Rogue

回答

0

看來你的問題是關於簡化您的比較,但我認爲你寧願實現Comparable<Passenger>而不是Comparator,並使用#compareTo方法。至於清理,這是一個有點一件容易的事,如果你只是抽象的實際布爾邏輯:

public int compareTo(Passenger other) { 
    if (this.isDisability()^other.isDisability()) { //use an XOR 
     return this.isDisability() ? 1 : -1; //1 for us, -1 for other 
    } 
    //compare #getClase 
    int clase = -Integer.compare(this.getClase(), other.getClase()); //invert 
    if (clase == 0) { 
     //compare arrival times if clase is equal 
     //normalize to -1, 1 (0 excluded in OP) 
     return this.getArrivalTime() < other.getArrivalTime() ? 1 : -1; 
    } 
    return clase > 0 ? 1 : -1; //normalize to -1, 0, 1 
} 

這允許你定義一個自然排序爲Passenger,和封裝/內部類實現(不需要儘可能多的曝光)。

這也使得像分揀更容易操作:

List<Passenger> passengers = /* some list */; 
Collections.sort(passengers); 

如果你想提供一個比較器,可以完成替代排序,你也可以做你的類中:

public class Passenger { 

    //... 

    public static class ArrivalComparator implements Comparator<Passenger> { 

     public int compare(Passenger one, Passenger two) { 
      return Integer.compare(one.getArrivalTime(), two.getArrivalTime()); 
     } 
    } 

    //... 

} 

使用我們前面的例子,這會讓你根據到達時間對所有乘客進行分類:

Collections.sort(passengers, new Passenger.ArrivalComparator()); 

此外,這剛好可以使用Java 8聯:

//Sort by arrival time 
Collections.sort(passengers, (one, two) -> Integer.compare(one.getArrivalTime(), two.getArrivalTime()); 

但總體而言,記住一個比較主要是定義一個特定的排序,而Comparable定義了通用/自然排序。

+0

你compareTo方法過於複雜,易於維護和其他選項將在一個時間只能做一個比較,如果你提到,他們需要一起使用才能達到預期這將是很好結果 – developer

+0

這並不太複雜,實際上我認爲它比OP中最初的'#比較'更清晰。其他選項一次只能執行一項,但您可以根據自己的喜好對它們進行嚴格比較。它們並不一定需要一起使用,'#compareTo'可以用於大多數事物(包括'Collections#sort'和'PriorityQueue'的構造函數)的'Comparator'的就地,而我的要點是「比較器」應該是針對特定順序而不是OP發佈的自然順序。 – Rogue

+0

嘿,非常感謝你使用你的代碼並做了一些改變,只是看看我自己的回答,真的非常感謝你。 –

1

我想你在找什麼是重構你的代碼,我會建議分離compare邏輯到一個單獨的PassengerComparator類(SRP)爲更好地維護如下圖所示可讀性

public class PassengerComparator implements Comparator<Passenger> { 

     public int compare(Passenger pas1, Passenger pas2) {  
     //check the comparison of all 
     if(disabilityComparator(Passenger pas1, Passenger pas2) 
       && arrivalTimeComparator(Passenger pas1, Passenger pas2) 
       && claseComparator(Passenger pas1, Passenger pas2)) { 
      return 1; 
     } else { 
      return -1; 
     } 
     } 

    //compares only disability 
    private int disabilityComparator(Passenger pas1, Passenger pas2) { 
      return pas1.isDisability() - pas2.isDisability(); 
    } 

    //compares only arrivalTime 
    private int arrivalTimeComparator(Passenger pas1, Passenger pas2) { 
      return pas1.getArrivalTime() - pas2.getArrivalTime(); 
    } 

    //compares only clase 
    private int claseComparator(Passenger pas1, Passenger pas2) { 
      return pas1.getClase() - pas2.getClase(); 
    } 
} 

用法:

PriorityQueue<Book> queue = new PriorityQueue<Book>(10, new PassengerComparator()); 
+0

豈不是'PassengerComparator實現比較'你會初始化爲'PassengerComparator補償=新PassengerComparator();'? – Rogue

+0

你是正確的,更新的使用 – developer

0

如何以更好的方式處理這些多級別的比較?

  1. 爲每個屬性創建單獨的比較器。
  2. 將各個比較器組合成多級比較。有關此方法的示例,請查看Group Comparator

因此,知道你有可重複使用的代碼,它允許你按照你希望的任何順序進行排序,而無需編寫複雜的多級比較器。

您可能還需要檢查出的Bean Comparator這使得它很容易在一個單一的代碼行創建單獨的比較。

0

嘿,我剛剛得到正確的答案,只是通過增加這類客運它的作品了確切的方式,我想這樣的優先順序是:殘疾,階級和arrivalTime,太謝謝你了。 :)

public int compareTo(Passenger other) { 
    if (this.isDisability()^other.isDisability()) { // use an XOR so it only enters if one of them is true 
     return this.isDisability() ? -1 : 1; 
    } 
    int clase = -Integer.compare(this.getClase(), other.getClase()); 
    if (clase == 0) { 
     return this.getArrivalTime() < other.getArrivalTime() ? -1 : 1; 
    } 
    return clase > 0 ? -1 : 1; 
} 
相關問題