简体   繁体   English

TreeMap put没有按预期工作

[英]TreeMap put is not working as expected

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.

I have overloaded both hashcode, equals method in class. 我在类中重载了hashcode,equals方法。 I think put method should use equals method to determine whether the same object exits or not. 我认为put方法应该使用equals方法来确定是否退出相同的对象。 But it is not working as expected. 但它没有按预期工作。

I am not sure why my hashMap size is 1. Please let me know if I understood hashmap working wrongly. 我不知道为什么我的hashMap大小为1.如果我理解hashmap错误地工作,请告诉我。 Help me to identify bug in this code ? 帮我识别一下这段代码中的错误?

Your TreeMap is comparing Point values by the l part (whatever that's meant to be). 你的TreeMap正在通过l部分比较Point值(不管是什么意思)。 That's what this part of your code does: 这就是你的代码的这一部分:

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

The two points you've created have the same l value (0) so they're considered equal... so the second call to put replaces the existing entry. 您创建的两个点具有相同的l值(0),因此它们被视为相等...因此第二次调用put将替换现有条目。 TreeMap doesn't use equals and hashCode at all. TreeMap根本不使用equalshashCode

From the documentation : 文档

Note that the ordering maintained by a tree map, like any sorted map, and whether or not an explicit comparator is provided, must be consistent with equals if this sorted map is to correctly implement the Map interface. 请注意,如果此有序映射要正确实现Map接口,则树映射维护的顺序(如任何有序映射)以及是否提供显式比较器必须与equals一致。 (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Map interface is defined in terms of the equals operation, but a sorted map performs all key comparisons using its compareTo (or compare) method, so two keys that are deemed equal by this method are, from the standpoint of the sorted map, equal. (有关与equals一致的精确定义,请参见Comparable或Comparator。)这是因为Map接口是根据equals操作定义的,但是有序映射使用compareTo(或compare)方法执行所有键比较,因此从排序映射的角度来看,通过此方法被视为相等的键是相等的。 The behavior of a sorted map is well-defined even if its ordering is inconsistent with equals; 即使排序与equals不一致,也可以很好地定义有序映射的行为。 it just fails to obey the general contract of the Map interface. 它只是不遵守Map接口的一般合同。

Your comparison isn't consistent with equals , which is why you're seeing results which violate the Map contract. 您的比较并非一致equals ,这就是为什么你看到违反结果Map的合同。

TreeMap only uses the supplied Comparator (or the natural ordering when available) to determine equality, so equals and hashCode make no difference. TreeMap仅使用提供的Comparator (或可用​​时的自然顺序)来确定相等性,因此equalshashCode没有区别。

In your case, both Point s have the same l value, so they are considered identical according to your Comparator . 在您的情况下,两个Point都具有相同的l值,因此根据您的Comparator ,它们被认为是相同的。

You can modify your Comparator to take all the properties ( l , x and y ) into account when determining the order (and the equality) of your keys. 在确定键的顺序(和相等)时,可以修改Comparator以将所有属性( lxy )考虑在内。

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

These put call's use the supplied comparator ((p1, p2)-> p1.l-p2.l) to check if two Points are equal . 这些put调用使用提供的比较器((p1, p2)-> p1.l-p2.l)来检查两个Point是否equal

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

This uses the equals overridden in Point class. 这使用了Point类中的equals重写。

Hence the difference.. 因此差异..

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM