Java PriorityQueue相同优先级保持FIFO且不修改原元素类的实现方案
解决方案
核心实现思路是通过包装类嵌入自增序列号,无需修改原有TestTimedItemChange类即可实现同优先级元素的FIFO出队规则。
具体改动步骤
- 新增自增序列生成器和包装类
在TestPriorityQueue类中新增自增序列生成器,同时定义包装类包裹原业务对象与序列号:
static class TestPriorityQueue { // 新增:自增序列号生成器 private final AtomicInteger sequenceGen = new AtomicInteger(0); // 新增:包装类,嵌入序列号 private static class TimedItemChangeWrapper { private final TestTimedItemChange item; private final int sequence; public TimedItemChangeWrapper(TestTimedItemChange item, int sequence) { this.item = item; this.sequence = sequence; } public TestTimedItemChange getItem() { return item; } } // 原有其他代码不变 }
- 修改PriorityQueue的存储类型与比较器
队列改为存储包装类对象,比较逻辑先按原有规则排序,优先级平局时按序列号升序排序(更早插入的元素序列号更小,优先出队):
private Comparator<TimedItemChangeWrapper> getWrapperComparator(final Map<String, String> eventIdToTypeMap) { // 复用原有比较逻辑 Comparator<TestTimedItemChange> baseComparator = getTimedItemChangeComparator(eventIdToTypeMap); return (o1, o2) -> { int baseCompare = baseComparator.compare(o1.getItem(), o2.getItem()); if (baseCompare != 0) { return baseCompare; } // 优先级相同时,序列号小的先出队,保证FIFO return o1.sequence - o2.sequence; }; }
- 适配队列的增删操作
public void build(){ // 原有其他初始化代码不变 // 队列改为存储包装类 final Queue<TimedItemChangeWrapper> pinnedItemsInQuickView = new PriorityQueue<>(getWrapperComparator(eventIdToTypeMap)); for (final TestEvent event : eventList) { final TestTimedItemChange newItemToAdd = buildTimedItemChange(event.getItemId(), event.getStartTime(),"add"); if (changesCollection.size() >= 4) { // 出队后取原业务对象 final TestTimedItemChange oldItemToRemove = pinnedItemsInQuickView.peek().getItem(); changesCollection.add(buildTimedItemChange(oldItemToRemove.getItemId(), Math.max(newItemToAdd.getTimePosition(), oldItemToRemove.getTimePosition()), "remove")); changesCollection.add(newItemToAdd); pinnedItemsInQuickView.poll(); // 入队时生成新序列号 pinnedItemsInQuickView.add(new TimedItemChangeWrapper(newItemToAdd, sequenceGen.getAndIncrement())); } else { changesCollection.add(newItemToAdd); // 入队时生成新序列号 pinnedItemsInQuickView.add(new TimedItemChangeWrapper(newItemToAdd, sequenceGen.getAndIncrement())); } } // 原有输出逻辑不变 }
效果说明
修改后同优先级的元素会严格按插入顺序出队,原有错误输出中先移除212、216的问题会被修复,实际出队顺序为210 → 211 → 212 → 216,完全符合FIFO要求。
内容的提问来源于stack exchange,提问作者user2621826
相关产品推荐
相关产品推荐

