Java PriorityQueue未按预期顺序出队问题求助
嗨,我发现你代码里的问题啦!导致输出顺序不符合预期的根源是包装类的引用比较错误,咱们一步步来拆解:
首先,你在Comparator的compare方法里用了a.getValue() != b.getValue()来判断两个值是否相等,这是个容易踩的坑!因为Integer是包装类,当值不在-128~127的默认缓存范围内时(比如你用的200),每次调用getValue()返回的都是新的Integer对象,!=比较的是对象引用而非实际数值。所以哪怕两个值都是200,a.getValue() != b.getValue()也会返回true,导致代码进入第一个分支:return Integer.compare(b.getValue(), a.getValue())。
而Integer.compare(200, 200)的结果是0,这会让PriorityQueue认为这两个元素的优先级完全相同。对于优先级相同的元素,PriorityQueue不会保证它们的顺序,最终出队顺序就会依赖元素的插入顺序——而HashMap的entrySet()遍历顺序是无序的(不保证和插入顺序一致),所以你才会得到[accountB(200), accountC(200), accountA(200)]这样的结果。
那怎么修复呢?把判断条件改成基于数值的比较就好啦:
- 方法一:用
!a.getValue().equals(b.getValue()),这是包装类比较值的正确方式 - 方法二:用
Integer.compare(a.getValue(), b.getValue()) != 0,直接比较数值大小
修改后的Comparator示例:
PriorityQueue<Map.Entry<String, Integer>> maxHeap = new PriorityQueue<>(new Comparator<Map.Entry<String, Integer>>() { @Override public int compare(Map.Entry<String, Integer> a, Map.Entry<String, Integer> b) { int valueCompare = Integer.compare(b.getValue(), a.getValue()); if (valueCompare != 0) { return valueCompare; } return a.getKey().compareTo(b.getKey()); } });
这样修改后,当值相等时,代码会进入key的比较分支,按照key的字典序升序排列,poll出来的顺序就会是accountA(200), accountB(200), accountC(200),完全符合你的预期啦!
另外补充一点:HashMap本身是无序集合,它的entrySet遍历顺序和插入顺序无关,但PriorityQueue会严格按照你定义的Comparator对元素排序,只要Comparator逻辑正确,最终出队顺序就会符合预期。
备注:内容来源于stack exchange,提问作者laserman999

