为PriorityBlockingQueue编写比较器

时间:2015-03-30 13:41:13

标签: java comparator

我的PriorityBlockingQueue拥有具有组ID的Message对象。根据组ID,队列中的元素将被排序。将从队列中获取此消息,同时添加新消息。如果已经处理了组ID,则必须首先发送该组ID的消息。

我已经编写了一个比较器来执行此操作但是,未处理组ID的消息未正确排序。

这是我的比较器

List<Integer> grpProcessed = Gateway.getGrpAlreadyProcessed();

    if (grpProcessed.contains(arg0.getGroupID()) && grpProcessed.contains(arg1.getGroupID())) {
        return 1;
    } else if (grpProcessed.contains(arg0.getGroupID())) {
        return -1;
    }       
    return 1;

我做错了什么?

2 个答案:

答案 0 :(得分:0)

您需要更准确地定义订单。当(未)处理两条消息时,如何将两条消息相互比较? (你应该只返回0 if the two objects equal each other)。 Comparable接口还定义了更多要求(结果需要传递,......)。您可以从这段代码开始(当然未经测试):

// Check if arg0 is processed
if (grpProcessed.contains(arg0.getGroupID())) {
    if (grpProcessed.contains(arg1.getGroupID())) {
        // Both arg0 and arg1 are processed
        return Objects.equals(arg0, arg1) ? 0 : Integer.compare(System.identityHashCode(arg0), System.identityHashCode(arg1));
    }
    // Only arg0 is processed
    return 1;
}
// Check if arg1 is processed
if (grpProcessed.contains(arg1.getGroupID())) {
    // Only arg1 is processed
    return -1;
}
// Neither arg0 nor arg1 are processed
return Objects.equals(arg0, arg1) ? 0 : Integer.compare(System.identityHashCode(arg0), System.identityHashCode(arg1));

答案 1 :(得分:0)

简单解决方案:只需将常数大数字添加到尚未处理的项目中,因此任何已处理项目的ID将大于任何未处理项目的ID:

int bigId = Integer.MAX_VALUE / 2;
int id0 = grpProcessed.contains(arg0.getGroupID()) ? arg0.getGroupID() : (arg0.getGroupID() + bigId);
int id1 = grpProcessed.contains(arg1.getGroupID()) ? arg1.getGroupID() : (arg1.getGroupID() + bigId); 
return id0 - id1;

如果您对ID使用全范围int,请使用long进行比较。

如果您需要将元素分成2组保持其顺序,只需使用:

return (grpProcessed.contains(arg0.getGroupID()) ? 0 : 1) - (grpProcessed.contains(arg1.getGroupID()) ? 0 : 1);