equalsだけをオーバーライド
何と比べても同じって言うクラスAがあって。
class A { @Override public boolean equals(Object obj) { return true; } }
こうすると?
Collection set = new HashSet(); Collection list = new ArrayList(); set.add(new A()); set.add(new A()); list.add(new A()); list.add(new A()); System.out.println(set.contains(new A())); System.out.println(list.contains(new A())); System.out.println(set.size()); System.out.println(list.size());
こうなった。
false
true
2
2
実際に動かしてもこの通り動作するとおもいます。ですけど、newした時にhashCodeが違う値になる保証は無い*1ので問題としては成立してなかったり…。
少なくともこの問題はEffectiveJavaの「項目9 equalsをオーバーライドする時は、常にhashCodeをオーバーライドする」に真っ向から違反すると、色々まともに動かなくなります。
例で挙げている Collection#contains には以下のように書かれています。
コレクションに指定された要素がある場合に true を返します。すなわち、このコレクションに (o==null ? e==null : o.equals(e)) である要素 e が 1 つ以上ある場合にだけ true を返します。
この場合は条件を満たすのに false になってしまってるわけです。前のも合わせて equals/hashCodeはちゃんと実装しましょうって事になるんですけどね。
おまけ
class A { public boolean equals(Object obj) {return true;} public int hashCode() {return 1;} } class B { public boolean equals(Object obj) {return true;} public int hashCode() {return 1;} } Set set = new HashSet(); set.add(new B()); set.add(new A()); for (Object o : set) { System.out.println(o.getClass()); }
答えはー……わからなかったら動かしてください。あ、ちょっと動かす時にはGroovyConsoleって言うのが便利ですよ!