我正在检查TreeMap的headMap方法,该方法返回Map的一部分,其键严格小于toKey。因此,我期望输出为B,C,但它仅返回B。这是我做的一件很奇怪的事情,我更改了return this.priority > o.priority ? 1 : -1;
这样的compareTo方法,然后开始返回我期望的C,B。我确定这是不正确的,但是我如何才能得到优先级低于A的B,C。我在哪里弄错了。谢谢。
NavigableMap<PolicyTypePriorityWrapper, String> treeMap = new TreeMap();
PolicyTypePriorityWrapper a = new PolicyTypePriorityWrapper("A", 2);
PolicyTypePriorityWrapper b = new PolicyTypePriorityWrapper("B", 1);
PolicyTypePriorityWrapper c = new PolicyTypePriorityWrapper("C", 1);
treeMap.put(a, "A");
treeMap.put(b, "B");
treeMap.put(c, "C");
NavigableMap<PolicyTypePriorityWrapper, String> map = treeMap.headMap(a, false);
Set<PolicyTypePriorityWrapper> policyTypePriorityWrappers = map.keySet();
for (PolicyTypePriorityWrapper pol: policyTypePriorityWrappers) {
System.out.println(pol.getPolicyType());
}
PolicyTypePriorityWrapper.java
class PolicyTypePriorityWrapper implements Comparable<PolicyTypePriorityWrapper> {
private String policyType;
private int priority;
public PolicyTypePriorityWrapper(final String policyType, final int priority) {
this.policyType = policyType;
this.priority = priority;
}
public String getPolicyType() {
return this.policyType;
}
public int getPriority() {
return this.priority;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PolicyTypePriorityWrapper that = (PolicyTypePriorityWrapper) o;
if (priority != that.priority) return false;
return policyType.equals(that.policyType);
}
@Override
public int hashCode() {
int result = policyType.hashCode();
result = 31 * result + priority;
return result;
}
@Override
public int compareTo(final PolicyTypePriorityWrapper o) {
return Integer.compare(this.priority, o.priority);
}
}
答案 0 :(得分:1)
那是因为您没有遵循Comprarable
中的JDK文档指南:
强烈建议(尽管不是必需的)自然顺序应与等号保持一致。之所以如此,是因为没有显式比较器的排序集(和排序映射)与自然排序与等式不一致的元素(或键)一起使用时,其行为“奇怪”。特别是,这样的排序集(或排序图)违反了根据equals方法定义的集合(或图)的一般约定。
如您所见,您遇到的情况是a.compareTo(b) == 0
但!a.equals(b)
。 "B", 1
和"C", 1
对于TreeMap
都是相等的:
请注意,如果树排序图要正确实现
Map
接口,则树映射所维护的排序(与任何排序的映射一样)以及是否提供显式比较器必须与equals一致。 (有关与equals一致的精确定义,请参见Comparable或Comparator。)之所以这样,是因为Map
接口是根据equals操作定义的,因此但是排序后的映射使用其{{ 1}}(或比较)方法,因此从排序后的映射的角度来看,此方法认为相等的两个键是相等的。排序后的映射的行为是明确定义的,即使其排序与equals不一致也是如此;只是不遵守Map界面的一般约定。例如,如果一个人将两个键a和b相加,使得
compareTo
到不使用显式比较器的排序集中,则第二个add操作返回false(以及排序后的集合的大小不会增加),因为从排序集的角度来看,a和b是等效的。。
因此,发生的情况是您(!a.equals(b) && a.compareTo(b) == 0)
不能区分具有相同优先级但类型不同的两个元素,但是由于TreeMap使用的是 ONLY (仅)相等,那么您首先不会将它们都添加到地图中。
您是否尝试过compareTo
?我的猜测是它排在第二位。
答案 1 :(得分:1)
new PolicyTypePriorityWrapper("B", 1)
是不合格的,因为它甚至没有进入treeMap
。
为什么?因为键是PolicyTypePriorityWrapper
对象,它们根据其整数优先级值进行比较。由于b
和c
具有相同的优先级,因此仅将最后一个保存到treeMap
。与a
相比,b
和c
的优先级比a
低,并且等于b
。保留键并替换值。因此,在地图中将出现一个条目PolicyTypePriorityWrapper b
,其中包含新替换的值C
。
这是Map::put(K key, V value)
方法的行为。
如果该映射先前包含该键的映射,则旧值将替换为指定值。
现在NavigableMap::headMap(K toKey, boolean inclusive)
返回此映射的一部分视图,该视图的键小于(或等于,如果包含在内,则为true)toKey(取自文档)。结果很明显。 a
和b
仅留在treeMap
中,因此a
被滤除,因为它的优先级比b
小,只有b
有资格退货。