假设我有一个简单的POJO类Class1,它有两个int类型的字段。我已经实现了它的hashCode()和equals()方法来处理这两个字段,以便将类的实例放入集合中。到目前为止还不错。现在,我想要一个不同的集合,如果第一个字段相等,则将Class1的实例视为相等,使相等条件变弱。 我甚至可能希望有另一个集合,只考虑第二个字段作为检查相等的字段。这是可能的吗? 如果是,怎么做?
你可以通过使用TreeSet和提供一个只检查你感兴趣的字段的自定义Comparator来获得该效果。但需要注意的是,严格来说这样的TreeSet不再是一个“正确”的Set,因为它有效地忽略了你的对象的equal()方法。请注意,一个集合维护的顺序(无论是否提供了显式比较器)必须与相等性一致,如果要正确实现Set接口。(有关“与equals一致”的精确定义,请参见Comparable或Comparator。)这是因为Set接口是基于equals操作定义的,但TreeSet实例使用它的compareTo(或compare)方法执行所有元素比较,因此,通过该方法判断相等的两个元素在集合的角度上相等。即使集合的排序与equals不一致,其行为也是明确定义的;它只是未遵守Set接口的一般契约。
标准Java库不支持此功能。而且(令人惊讶的是),Apache Commons Collections或Guava库中似乎没有支持这种功能的Map或Set类。如果你努力寻找,可能会找到其他支持此功能的库。或者,你可以编写自己的代码……从标准HashMap代码开始。 一种便宜而高效的替代方案是为你的元素类型创建一个轻量级包装类,该类将大部分方法委托给包装类并提供与原始类不同的equals / hashcode对。这样做会有一些小的运行时开销……但值得考虑。Joachim的建议也很好,除非你的集合很大。(TreeSet具有O(logN)查找时间复杂度,而正确实现的哈希表具有O(1)查找时间复杂度。)