具有自定义相等标准的Java HashSet?
我正在寻找类似于Java TreeSet在实例化时接收自定义比较器的能力,所以我不需要使用对象的默认相等(和哈希码)标准。
我能想到的最接近的是将我的对象包装在一个私有的自定义类中,但这看起来很糟糕:(这在编程时最终会成为一种反复出现的主题,所以我想知道是否已有可供我们使用的东西。也许在公共图书馆?
谢谢
不,你已经找到了你应该使用的解决方案。
即使对于TreeSet
,也不赞成使用与equals
不兼容的比较标准:
请注意,如果有序集合要正确实现Set接口,则由有序集合维护的排序(无论是否提供显式比较器)必须与equals一致。
(我不知道Apache Commons,但是Guava 明确 拒绝了对此类事情的请求。)
你是对的,当你想使用任何Trees
( TreeMap
, TreeSet
)时,你添加的对象必须实现Comparable
。
对于原始类型,Java已经为您解决了这个问题。
对于自定义对象,您有3种可能性:
-
您的一个对象已经具有基本类型的唯一ID或已实现
compareTo()
的类型(如String
)然后将此字段用于compareTo,如果其他值的值对于相等并不重要。 (但是equals()
也必须只使用这一个字段) -
使用Apache的
EqualsBuilder
:这适用于reflection,并不是最快的解决方案 -
自己编写,阅读一些教程如何做到这一点:例如:
Josh Bloch:有效的第2版
但是不要忘记equals()
和compareTo()
必须兼容(和hashCode()
),这样你就不会违反equals契约。 (合同本身不太容易理解,但如果你把其中一个等同于教程,它就会变得清晰。)
或者忘掉所有,并使用HashSet
, HashMap
。
有几个第三方集合框架允许自定义相等逻辑。 这非常适合覆盖无法更改源的对象的相等性。
- 特罗韦
Trove的地图/集支持使用自定义散列策略,允许您根据输入数据的特征调整集合。 此function还允许您在无法覆盖Object.hashCode()时定义散列函数。
- HE-collections
要实现这一点,任何需要标准修正的类型都必须实现HE-Collection接口EqualsAndHashCorrection。 此接口定义方法hashCodeInHeCollection()和equalsInHeCollection(Object),用于更正不正确的已实现方法hashCode()和equals(Object)。