Comparator and equals()

后端 未结 11 1932
终归单人心
终归单人心 2020-12-16 17:27

Suppose I need TreeSet with elements sorted with some domain logic. By this logic it doesn\'t matter order of some elements that doesn\'t equal so compare metho

相关标签:
11条回答
  • 2020-12-16 17:59

    hashcode() method doesn't guarantee any less than or greater than. compare() and equals() should yield the same meaning, but its not necessary, though.

    As far as I can understand from your confusing code (no offence intended :)), you want to add duplicates to the TreeSet. For that reason you came up with this implementation. Here is the reason, you can't put them in the TreeSet, quoting from the docs,

    The behavior of a set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.

    So, you need to do something with yor equals() method, so it can never return true whats so ever. The best implementation would be,

    public boolean equals(Object o) {
        return false;
    }
    

    By the way, if I am right in my understanding, why not you use List instead and sort that.

    0 讨论(0)
  • 2020-12-16 17:59

    You have a Foo class wich is comparable but want to use a different sorting in a TreeSet<Foo> structure. Then your idea is the correct way to do it. Use that constructor to "overrule" the natural sorting of Foo.

    0 讨论(0)
  • 2020-12-16 18:00

    There is no rule in Java which says that the hash codes of two objects must be different just because they aren't equal (so o1.hashCode() - o2.hashCode() could return 0 in your case).

    Also the behavior of equals() should be consistent with the results from compareTo(). This is not a must but if you can't maintain this, it suggests that your design has a big flaw.

    I strongly suggest to look at the other fields of the objects and use some of those to extend your comparison so you get a value != 0 for objects were equals() == false.

    0 讨论(0)
  • 2020-12-16 18:06

    Very interesting question. As far as I understand your problem is duplicate elements.

    I think that if o1.equals(o2) their hash codes might be equal too. It depends on the implementation of hashCode() in your Foo class. So, I'd suggest you to use System.identityHashCode(x) instead.

    0 讨论(0)
  • 2020-12-16 18:11

    There are a couple of problems here:

    • Hash codes are not generally unique, and in particular System.identityHashCode will not be unique on vaguely modern JVMs.

    • This is not a question of stability. We are sorting an array, but creating a tree structure. The hash code collisions will cause compare to return zero, which for TreeSet means one object wins and the other is discarded - it does not degrade to a linked-list (the clue is having "Set" in the name).

    • There is generally an integer overflow issue with subtracting one hash code from another. This means the comparison wont be transitive (i.e. it is broken). As luck would have it, on the Sun/Oracle implementation, System.identityHashCode always returns positive values. This means that extensive testing will probably not find this particular sort of bug.

    I don't believe there is a good way to achieve this using TreeSet.

    0 讨论(0)
提交回复
热议问题