ipo*_*oga 1 java contains equals arraylist
[下面的固定问题]
我有这门课:
Class Doc() {
private String D;
Doc(String d) {
D = d;
}
@Override
public boolean equals(Object o) {
if (o instanceOf String) {
if (o.equals(D)) return true;
else return false;
} else return false;
}
@Override
public int hashCode() {
...
}
}
Run Code Online (Sandbox Code Playgroud)
如果我运行测试,使用例如"abc"作为参数启动Doc()然后使用Doc().equals("abc")它返回true - 正如我所料.如果我使用:
ArrayList docs = new ArrayList<Doc>();
Doc d = new Doc("123");
Docs.add(d);
System.out.println(docs.contains("123"));
Run Code Online (Sandbox Code Playgroud)
它返回false,我不确定为什么.我已经尝试将输出添加到.equals()方法以检查它是否被使用,它是.这个代码hashCode()只是一些虚假(我知道我应该做一些正确的事,我只是不确定如何) - 但我只会使用equals().
不过,我读到的地方equals()也会检查hashCode(); 如果我在其中添加System.out.println(".")第一行hashCode()并不输出任何内容,那么它似乎不会被调用.我最好的猜测是我无法比较不同类的两个对象 - 这是正确的吗?还是我忽略了别的什么?
为了将来参考,使用@JonSkeet的建议解决了这个问题 - 代码现在是:
Class Doc() {
private String D;
Doc(String d) {
D = d;
}
public String getD() {
return D;
}
@Override
public boolean equals(Object o) {
if (o instanceOf Doc) {
Doc tmp = (Doc) o;
if (tmp.getD().equals(D)) return true;
else return false;
} else return false;
}
@Override
public int hashCode() {
...
}
}
Run Code Online (Sandbox Code Playgroud)
你假设contains()会打电话memberInCollection.equals(candidate)而不是打电话candidate.equals(memberInCollection).该文件违背认为:
更正式地说,当且仅当此列表包含至少一个元素e时才返回true
(o==null ? e==null : o.equals(e)).
从根本上说,你的equals方法打破了正常的契约,因为它不是对称的 - 对于任何非空值的x和y,x.equals(y) == y.equals(x)应该是真的.这是不是你的代码的情况下:
new Doc("123").equals("123") // True
"123".equals(new Doc("123")) // False
Run Code Online (Sandbox Code Playgroud)
(此外,您的equals方法甚至不是自反的 - x.equals(x)如果x是对实例的引用,则永远不会为真Doc.)
基本上,您不应该尝试使一个类型的实例等于不相关类型的实例.它总会很糟糕.在类型层次结构中使得平等很好地工作是很困难的 - 但对于不相关的类型,这是一个非常糟糕的主意.