ArrayList
オブジェクトのTest
があり、等価チェックとして文字列を使用します。 List.contains()
を使用して、リストに特定の文字列を使用するオブジェクトが含まれているかどうかを確認できるようにします。
単に:
Test a = new Test("a");
a.equals("a"); // True
List<Test> test = new ArrayList<Test>();
test.add(a);
test.contains("a"); // False!
等しいおよびハッシュ関数:
@Override
public boolean equals(Object o) {
if (o == null) return false;
if (o == this) return true;
if (!(o instanceof Test)) {
return (o instanceof String) && (name.equals(o));
}
Test t = (Test)o;
return name.equals(t.GetName());
}
@Override
public int hashCode() {
return name.hashCode();
}
contains
がカスタムクラスで機能することを確認するために、equals
をオーバーライドする必要があることを読みました。したがって、equals
がtrueを返す一方で、contains
がfalseを返すのは非常に奇妙です。
この作業を行うにはどうすればよいですか?
Test
のequals
は、Stringを渡したときにtrueを返す可能性があるからといって、String
インスタンスを渡したときにequals
のTest
がtrueを返すとは限りません。実際、String
のequals
は、渡されたインスタンスが別のtrue
である場合にのみString
を返すことができます。
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) { // the passed instance must be a String
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
ArrayList
のcontains
は、検索されたインスタンスのindexOf
メソッド(この例ではequals
"a")を使用するString
を呼び出し、List
の要素タイプ(これはTest
です)を使用します。
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i])) // o in your case is a String while
// elementData[i] is a Test
// so String's equals returns false
return i;
}
return -1;
}
問題は、List<E>.contains(object o)
がtrueを返すように文書化されていることです。
このリストに(o == null?e == null:o.equals(e))などの要素eが少なくとも1つ含まれている場合に限ります。
( https://docs.Oracle.com/javase/8/docs/api/Java/util/List.html#contains-Java.lang.Object- から)
テストが機能するために必要なe.equals(o)
としてテストを実行しないことに注意してください。 equalsメソッドは可換に機能しません(Java docs)の用語を使用して「対称的に」)。
Javaドキュメントでは、クラスのequals()
メソッドは次のルールに従う必要があります。
Equalsメソッドは、null以外のオブジェクト参照に等価関係を実装します。
- 再帰的です。null以外の参照値
x
の場合、x.equals(x)
はtrueを返す必要があります。- それは対称です:null以外の参照値
x
およびy
に対して、x.equals(y)
はy.equals(x)
はtrueを返します。- 推移的です。非ヌルの参照値
x
、y
、およびz
について、x.equals(y)
がtrueを返し、y.equals(z)
が返される場合trueの場合、x.equals(z)
はtrueを返します。- 一貫性があります。null以外の参照値
x
およびy
の場合、x.equals(y)
の複数の呼び出しは一貫してtrueを返すか、一貫してfalseを返します。オブジェクトが変更されます。- Null以外の参照値
x
の場合、x.equals(null)
はfalseを返す必要があります。
書くなら
test.contains(new Test("a"));
その後、必ずtrueを返します。テストのリストで文字列オブジェクトを確認しています。