簡體   English   中英

Java PriorityQueue自定義Comparator

[英]Java PriorityQueue custom Comparator

在我的PriorityQueue中,我有兩種類型的客戶,VIP和常客。 我想首先服務VIP,然后定期服務。

如果CustomerID <100,則認為是VIP。

如果客戶是VIP,他會在隊列的VIP部分結束時進入

如果客戶是常規的,他會在整個隊列的末尾進行。

換句話說,我想按布爾VIP值排序,同時保留客戶進入的順序。

這是我的Order課程

public class Order implements Comparable<Order> {
    private final int customerID;
    private final int amount;
    private final boolean vip_status;

    public Order(int customerID, int amount) { 
        this.customerID = customerID;
        this.amount = amount;
        this.vip_status = customerID < 100 ? true : false;

    }

    @Override
    public int compareTo(Order o) {
        if (vip_status && !o.vip_status) {
            return -1;
        }
        if (!vip_status && o.vip_status)
            return 1;
        return 0;
    }

    public int getCustomerID() {
        return customerID;
    }

    public int getAmount() {
        return amount;
    }

    public boolean isVip_status() {
        return vip_status;
    }
}

這是我填寫隊列的嘗試:

import java.util.PriorityQueue;

public class MyPriorityQueue {
    public static void main(String[] args) {
        PriorityQueue<Order> queue = new PriorityQueue<>();
        Order o1 = new Order(1, 50);
        Order o2 = new Order(5, 30);
        Order o3 = new Order(4, 10);
        Order o4 = new Order(150, 5);
        Order o5 = new Order(2, 5);
        Order o6 = new Order(200, 5);

        queue.add(o1);
        queue.add(o2);
        queue.add(o3);
        queue.add(o4);
        queue.add(o5);
        queue.add(o6);

        while(!queue.isEmpty()){
            Order s = queue.poll();
            System.out.printf("VIP Status: %s CustomerID: %s Amount: %s%n", 
                        s.isVip_status(), s.getCustomerID(), s.getAmount());
        }
    }
}

結果我得到了(這是錯誤的):

VIP Status: true CustomerID: 1 Amount: 50
VIP Status: true CustomerID: 5 Amount: 30
VIP Status: true CustomerID: 2 Amount: 5
VIP Status: true CustomerID: 4 Amount: 10
VIP Status: false CustomerID: 150 Amount: 5
VIP Status: false CustomerID: 200 Amount: 5

這是我期望看到的(CustomerID 2和4應該按照它們的相同順序):

VIP Status: true CustomerID: 1 Amount: 50
VIP Status: true CustomerID: 5 Amount: 30
VIP Status: true CustomerID: 4 Amount: 10
VIP Status: true CustomerID: 2 Amount: 5
VIP Status: false CustomerID: 150 Amount: 5
VIP Status: false CustomerID: 200 Amount: 5

更新:除了VIP之外,我不想排序任何其他列。 我不想添加“日期”,因為它感覺像是一個黑客,而不是理解Java的工作原理。

看起來Java開箱即用的PriorityQueue類可以自由地重新排序項目,如果它們相互比較相等

(這不是“java如何工作”,它只是代表Java Runtime附帶的某個類的一點變態。)

所以,這里可能有用:

  1. 引入一個新的OrderPlacement類,包含a) Order和b) int priority

  2. PriorityQueue添加OrderPlacement對象而不是Order對象。

  3. 創建新的OrderPlacement對象時,通過遞增計數器為其發出新的priority

然后, OrderPlacement對象可以有一個compareTo()方法,如下所示:

@Override
public int compareTo( OrderPlacement o ) 
{
    int d = -Boolean.compare( order.vip_status, o.order.vip_status );
    if( d != 0 )
        return d;
    return Integer.compare( priority, o.priority );
}

如果必須使用優先級隊列,下面的代碼將解決您的問題。 請注意,我使用靜態計數器來維護具有相同VIP狀態的元素的正確順序,因為相等元素在優先級隊列中以隨機順序維護。 這是因為優先級隊列使用最小/最大堆數據結構,它只關心將min / max元素放在堆頂部並且不關心相同元素的排序。

import java.util.PriorityQueue;

public class Order implements Comparable<Order> {
  private final int customerID;
  private final int amount;
  private final int vip_status;
  private final int score;
  private static int counter = 0;

  public Order(int customerID, int amount) {
    this.customerID = customerID;
    this.amount = amount;
    this.vip_status = customerID < 100 ? 0 : 1;
    this.score = counter++;
  }

  @Override
  public String toString() {
    return customerID + " : " + amount + " : " + vip_status;
  }

  @Override
  public int compareTo(Order o) {
    int status = ((Integer) this.vip_status).compareTo(o.vip_status);
    status = status == 0 ? ((Integer) this.score).compareTo(o.score) : status;
    return status;
  }

  public static void main(String[] args) {
    Order o1 = new Order(1000, 100);
    Order o2 = new Order(500, 100);
    Order o3 = new Order(99, 100);
    Order o4 = new Order(10, 100);
    Order o5 = new Order(200, 100);
    Order o6 = new Order(1, 100);

    PriorityQueue<Order> orderQueue = new PriorityQueue<>();
    orderQueue.offer(o1);
    orderQueue.offer(o2);
    orderQueue.offer(o3);
    orderQueue.offer(o4);
    orderQueue.offer(o5);
    orderQueue.offer(o6);

    System.out.println(orderQueue.poll());
    System.out.println(orderQueue.poll());
    System.out.println(orderQueue.poll());
    System.out.println(orderQueue.poll());
    System.out.println(orderQueue.poll());
    System.out.println(orderQueue.poll());
  }
}

`

樣本輸出:

99 : 100 : 0
10 : 100 : 0
1 : 100 : 0
1000 : 100 : 1
500 : 100 : 1
200 : 100 : 1

注意:您需要知道得分最終可能會達到Integer.MAX_VALUE

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM