Java PriorityQueue自定义Comparator

Vla*_* S. 8 java priority-queue

在我的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我填写队列的尝试:

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());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

结果我得到了(这是错误的):

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
Run Code Online (Sandbox Code Playgroud)

这是我期望看到的(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
Run Code Online (Sandbox Code Playgroud)

更新:除了VIP之外,我不想排序任何其他列.我不想添加"日期",因为它感觉像是一个黑客,而不是理解Java的工作原理.

Mik*_*kis 4

看来,PriorityQueuejava 自带的开箱即用的类可以自由地对项目进行重新排序(如果它们比较彼此相等)

(这不是“java 的工作原理”,它只是代表 Java 运行时附带的某个类的一点歪曲。)

所以,这可能会起作用:

  1. 引入一个新OrderPlacement类,包含 a) anOrder和 b) an 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 );
}
Run Code Online (Sandbox Code Playgroud)

  • 事实上,JavaDocs 中甚至有一个示例建议采用这种方法(不是针对“PriorityQueue”,而是针对相关的 [“PriorityBlockingQueue”](https://docs.oracle.com/javase/8/docs/api/java/ util/concurrent/PriorityBlockingQueue.html)(使用“static final AtomicLong”作为计数器) (2认同)