Java 提供了使用Comparator
.
现在我的问题是为什么 java 不允许对 equals() 和 hashcode() 做同样的事情。
现在每个集合contains()
方法都可以轻松地使用这个外部相等提供程序来检查对象是否相等。
Guava有Equivalence
课程,它几乎可以满足您的要求。
您甚至可以将对象包装在 anEquivalence
中以使用更好的 hashCode() equals() 实现来装饰对象(例如,如果您想使用带有错误 equals() hashCode() 的对象作为 Map 键但没有访问权限到消息来源)
这是一个示例:数组没有正确实现 equals() 和 hashCode(),但这里是 char 数组的等价:
private static final Equivalence<char[]> CHAR_ARRAY_EQUIV = new Equivalence<char[]>(){
@Override
protected boolean doEquivalent(char[] a, char[] b) {
return Arrays.equals(a, b);
}
@Override
protected int doHash(char[] chars) {
return Arrays.hashCode(chars);
}
};
示例代码:
final char[] first ={'a','b'};
final char[] second ={'a','b'};
Assert.assertFalse(first.equals(second));
Assert.assertFalse(first.hashCode() == second.hashCode());
final Wrapper<char[]> firstWrapped = CHAR_ARRAY_EQUIV.wrap(first);
final Wrapper<char[]> secondWrapped = CHAR_ARRAY_EQUIV.wrap(second);
Assert.assertTrue(firstWrapped.equals(secondWrapped));
Assert.assertTrue(firstWrapped.hashCode() == secondWrapped.hashCode());
equals
并且hashCode
是对于给定的不会改变的概念Object
。只有实现者知道根据这些方法的规则应该使用哪些值。一旦他决定了那些,他们就定义了对象的身份,因此永远不应该改变。
另一方面,比较可能高度依赖于上下文。您可以通过实现来定义“自然”顺序Comparable
。但这不能针对不同的上下文而改变。假设您有一个可以按姓氏、名字、邮政编码、城市排序的联系人列表……您可以通过提供单独Comparator
的 s (或参数化的 s Comparator
)轻松地做到这一点。但它不是对象本身固有的,因此它应该是它自己的一个类(它可以实现为静态内部类,具体取决于您的代码约定)。
Comparator 接口用于在对集合进行排序时比较对象,它的 compare() 方法返回一个“int”,意思是,比较以一个 int 值结束,可以用来指示对象在排序集合中的位置。
contains() 为集合中的每个实例调用 equals() 方法,以便根据 equals-contract 找出两个实例是否相等。