Java HashSet with a custom equality criteria? [duplicate]

女生的网名这么多〃 提交于 2019-12-17 18:45:15

问题


I was looking for something akin to the Java TreeSet's ability to receive a custom comparator at instantiation time, so I needed not to use the object's default equality (and hash code) criteria.

The closest I could come up with was to wrap my objects in a private custom class, but that seems hacky :( This ends up being a kind of recurring theme when programming, so I was wondering if there's something already available for us to use. Maybe in the commons libraries?

Thanks


回答1:


Nope, you've found exactly the solution you're supposed to use.

Even for TreeSet, it's frowned upon to use comparison criteria that aren't compatible with equals:

Note that the ordering maintained by a sorted set (whether or not an explicit comparator is provided) must be consistent with equals if the sorted set is to correctly implement the Set interface.

(I don't know about Apache Commons, but Guava specifically rejected requests for this sort of thing.)




回答2:


There are a couple of third-party collections frameworks that allows custom equality logic. This is perfect for overriding equality for objects that you can't alter the source.

  • Trove

Trove's maps/sets support the use of custom hashing strategies, allowing you to tune collections based on characteristics of the input data. This feature also allows you to define hash functions when it is not feasible to override Object.hashCode().

  • HE-Collection

To achive this, any type that needs a standard correction, must implement the HE-Collection interface EqualsAndHashCorrection. This interface defines the methods hashCodeInHeCollection() and equalsInHeCollection(Object), that serve as correction for the incorrect implemented methods hashCode() and equals(Object).




回答3:


You are correct, when you want to use any of the Trees (TreeMap, TreeSet) the objects you add must implement Comparable.

For primitive types, Java has solved this for you.
For custom objects you have 3 possibilities:

  1. One of your object already has an unique id of a primitive type or an Type that already implements compareTo() (like String) Then use this field for compareTo, if the values of the others are not important for equality. (But then equals() must also only use this one field)

  2. Use EqualsBuilder from Apache: This works with reflection, and is not the fastest solution

  3. Write it your own, read some tutorial how to do that: e.g:

Josh Bloch: Effective java 2nd Edition

But don't forget that equals(), and compareTo() must be compatible (and hashCode(), too), such that you do not violate the equals contract. (The contract itself is less understandable, but it gets clear if you foillow one of that equals tutorials.)

Or forget that all, and use a HashSet , HashMap.



来源:https://stackoverflow.com/questions/14880450/java-hashset-with-a-custom-equality-criteria

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!