Java中PriorityQueue调用equals()返回意外结果的技术咨询
PriorityQueue equals()返回false的原因及解决办法
原因
Java的PriorityQueue没有重写Object类的equals()和hashCode()方法,所以它的equals判断逻辑就是默认的引用相等校验:只有当两个队列是同一个对象实例时(即==返回true),equals才会返回true,和队列里的元素内容、顺序完全无关。
你测试里的两个空队列是不同的对象实例,所以window.equals(base)返回false;同一个对象调用equals自然返回true。哪怕两个队列的元素完全一致,只要是不同的实例,equals就会返回false,这就是你看到的结果。
补充:虽然PriorityQueue是按优先级排序的队列,但它内部用堆结构存储,迭代器不保证顺序,但这不是equals返回false的核心原因——核心就是没重写equals方法。
解决办法
如果需要比较两个PriorityQueue的内容是否一致,有几种实用方案:
1. 自定义内容比较方法
直接遍历两个队列的元素,但要注意PriorityQueue的迭代器不保证优先级顺序,所以得用poll()依次取出(为了不修改原队列,要先复制):
public static <T> boolean arePriorityQueuesEqual(PriorityQueue<T> q1, PriorityQueue<T> q2) { if (q1.size() != q2.size()) { return false; } // 复制队列避免破坏原数据 PriorityQueue<T> tempQ1 = new PriorityQueue<>(q1); PriorityQueue<T> tempQ2 = new PriorityQueue<>(q2); while (!tempQ1.isEmpty()) { T elem1 = tempQ1.poll(); T elem2 = tempQ2.poll(); if (elem1 == null ? elem2 != null : !elem1.equals(elem2)) { return false; } } return true; }
2. 转数组排序后比较
如果能接受少量额外空间,可以把队列转成数组,排序后用Arrays.equals()比较,这种方法适合元素可排序的场景:
import java.util.Arrays; public static <T extends Comparable<T>> boolean comparePriorityQueues(PriorityQueue<T> q1, PriorityQueue<T> q2) { if (q1.size() != q2.size()) { return false; } Object[] arr1 = q1.toArray(); Object[] arr2 = q2.toArray(); Arrays.sort(arr1); Arrays.sort(arr2); return Arrays.equals(arr1, arr2); }
3. 封装自定义PriorityQueue并重写equals
如果业务中频繁需要比较队列内容,可以自己封装一个子类,重写equals和hashCode:
public class ComparablePriorityQueue<T> extends PriorityQueue<T> { @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PriorityQueue<?> that = (PriorityQueue<?>) o; if (size() != that.size()) return false; PriorityQueue<T> tempThis = new PriorityQueue<>(this); PriorityQueue<?> tempThat = new PriorityQueue<>(that); while (!tempThis.isEmpty()) { T elemThis = tempThis.poll(); Object elemThat = tempThat.poll(); if (elemThis == null ? elemThat != null : !elemThis.equals(elemThat)) { return false; } } return true; } @Override public int hashCode() { int hash = 0; PriorityQueue<T> temp = new PriorityQueue<>(this); while (!temp.isEmpty()) { T elem = temp.poll(); hash = 31 * hash + (elem == null ? 0 : elem.hashCode()); } return hash; } }
内容的提问来源于stack exchange,提问作者Contone
相关产品推荐
相关产品推荐

