TreeMap put没有按预期工作

时间:2017-08-01 12:40:42

标签: java object treemap

class Point{
    int x, y, l;

    Point(int x, int y, int l){
        this.x =x;
        this.y =y;
        this.l=l;
    }
    @Override
    public int hashCode() {
        return y;
    }

    @Override
    public boolean equals(final Object obj) {
        if(this == obj) return true;
        if(!(obj instanceof Point)) return false;
        Point p = (Point) obj;
        return this.x == p.x && this.y == p.y;
    }
}

    TreeMap<Point,Integer>  sortedMap = new TreeMap<>((p1, p2)-> p1.l-p2.l);
    sortedMap.put(new Point(4,5,0),0);
    sortedMap.put(new Point(5,5,0),6);
    System.out.println(sortedMap.size()); -> Output:  1
    System.out.println((new Point(4,5,0)).equals(new Point(5,5,0))); -> Output -> False.

我在类中重载了hashcode,equals方法。我认为put方法应该使用equals方法来确定是否退出相同的对象。但它没有按预期工作。

我不确定为什么我的hashMap大小为1。如果我理解hashmap工作错误,请告诉我。帮我识别一下这段代码中的错误?

3 个答案:

答案 0 :(得分:11)

您的TreeMap正在将Point值与l部分进行比较(不管是什么意思)。这就是代码的这一部分:

new TreeMap<>((p1, p2)-> p1.l-p2.l);

您创建的两个点具有相同的l值(0),因此它们被视为相等...因此第二次调用put会替换现有条目。 TreeMap根本不使用equalshashCode

来自documentation

  

请注意,如果此有序映射要正确实现Map接口,则树映射维护的顺序(如任何有序映射)以及是否提供显式比较器必须与equals一致。 (有关与equals一致的精确定义,请参阅Comparable或Comparator。)这是因为Map接口是根据equals操作定义的,但是有序映射使用compareTo(或compare)方法执行所有键比较,因此从排序映射的角度来看,通过此方法被视为相等的键是相等的。即使排序与equals不一致,也可以很好地定义有序映射的行为。它只是没有遵守Map接口的一般合同。

您的比较与<{1}}一致,这就是您查看违反equals合同的结果的原因。

答案 1 :(得分:6)

TreeMap仅使用提供的Comparator(或可用的自然顺序)来确定相等性,因此equalshashCode没有区别。

在您的情况下,两个Point都具有相同的l值,因此根据您的Comparator认为它们相同。

在确定密钥的顺序(和相等性)时,您可以修改Comparator以考虑所有属性(lxy

答案 2 :(得分:2)

sortedSet.put(new Point(4,5,0),0);
sortedSet.put(new Point(5,5,0),6);

这些看涨期权使用提供的比较器((p1, p2)-> p1.l-p2.l)检查两个点是否为equal

(new Point(4,5,0)).equals(new Point(5,5,0))

这使用Point类中重写的等号。

因此差异..