java ArrayList未使用重写的equals
我在获取ArrayList以正确使用重写的equals时遇到问题。问题是,我试图对单个键字段使用equals to only测试,并使用ArrayList。contains()测试是否存在具有正确字段的对象。这里有一个例子
public class TestClass {
private static class InnerClass{
private final String testKey;
//data and such
InnerClass(String testKey, int dataStuff) {
this.testKey =testKey;
//etc
}
@Override
public boolean equals (Object in) {
System.out.println("reached here");
if(in == null) {
return false;
}else if( in instanceof String) {
String inString = (String) in;
return testKey == null ? false : testKey.equals(inString);
}else {
return false;
}
}
}
public static void main(String[] args) {
ArrayList<InnerClass> objectList = new ArrayList<InnerClass>();
//add some entries
objectList.add(new InnerClass("UNIQUE ID1", 42));
System.out.println( objectList.contains("UNIQUE ID1"));
}
}
让我担心的是,我不仅在输出上出错,而且没有得到“到达此处”的输出
有人知道为什么这个覆盖被完全忽略了吗?覆盖和内部类是否有一些我不知道的微妙之处
编辑: 有问题的网站,所以我似乎无法标记答案。 谢谢你的快速回复:是的,这是我的疏忽,那就是绳子。等于调用了thta,而不是我的自定义thta。我想现在是老式支票了
# 1 楼答案
通常,您还需要重写
hashCode()
,但这不是这里的主要问题。你有一个不对称的equals(..)
方法。文件明确指出,它应该是对称的:你观察到的是由于合同破裂而导致的意外行为
创建一个实用程序方法,该方法迭代所有项,并在字符串上使用
equals(..)
进行验证:你可以用番石榴的
Iterables.any(..)
方法做类似的事情:# 2 楼答案
根据the JavaDoc of ^{} ,它被定义为返回
true
请注意,此定义在中的元素
o
上调用equals
,这是参数,而不是^{因此
String.equals()
将被调用,而不是InnerClass.equals()
还请注意the contract for ^{} 指出
但是您违反了这个约束,因为
new TestClass("foo", 1).equals("foo")
返回true
,但是"foo".equals(new TestClass("foo", 1))
将始终返回false
不幸的是,这意味着您的用例(可以等同于另一个标准类的自定义类)不能以完全一致的方式实现
如果您仍然想做这样的事情,您必须仔细阅读所有集合类的规范(有时是实现),并检查是否存在这样的缺陷
# 3 楼答案
您正在用一个
String
而不是InnerClass
的参数调用contains
:在我的JDK中:
注意
indexOf
如何调用o.equals()
。在你的例子中,o
是一个String
,所以你的objectList.contains
将使用String.equals
而不是InnerClass.equals
# 4 楼答案
虽然没有回答您的问题,但许多收藏使用
hashcode()
。你也应该覆盖它,以“同意”equals()
实际上,您应该始终同时实现
equals
和hashcode
,并且它们应该始终保持一致。正如Object.equals()
的javadoc所述:具体地说,许多藏品都依赖于这一契约的维持——否则行为就没有定义
# 5 楼答案
如果您检查
ArrayList
的来源,您将看到它调用其他对象的equals
。在您的例子中,它将调用equals
ofString "UNIQUE ID1"
,这将检查其他对象是否为String
类型,并仅返回false
:对于您的案例,使用只包含
id
的InnerClass
调用contains
:不要忘记为
InnerClass
实现equals
,它只比较id
# 6 楼答案
你的实施是错误的。in参数不应该是
String
。它应该是一个InnerClass
(注意
instanceof null
返回false,所以不需要先检查null)然后,您可以使用以下方法测试列表中是否存在等效的对象:
但是,如果您真的想通过字符串键检查InnerClass,为什么不使用
Map<String,InnerClass>