Java中的Treemap的headmap方法

时间:2018-07-17 17:59:40

标签: java dictionary treemap

我正在检查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);
    }
}

2 个答案:

答案 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对象,它们根据其整数优先级值进行比较。由于bc具有相同的优先级,因此仅将最后一个保存到treeMap。与a相比,bc的优先级比a低,并且等于b。保留键并替换值。因此,在地图中将出现一个条目PolicyTypePriorityWrapper b,其中包含新替换的值C

这是Map::put(K key, V value)方法的行为。

  

如果该映射先前包含该键的映射,则旧值将替换为指定值。

现在NavigableMap::headMap(K toKey, boolean inclusive)返回此映射的一部分视图,该视图的键小于(或等于,如果包含在内,则为true)toKey(取自文档)。结果很明显。 ab仅留在treeMap中,因此a被滤除,因为它的优先级比b小,只有b有资格退货。