Bloch's wonderful book "Effective Java" points out that if equals
is not symmetric then the behavior of Collections contains
is indeterminate.
In the example he gives (reproduced with small modifications below), Bloch says that he sees a "false", but could just as well have seen a true or an Exception.
You could see a "true" if the standard does not specify whether contains(Object o)
checks e.equals(o)
or o.equals(e)
for each item in the collection, and the former is implemented. However, the Collections Javadoc clearly states that it has to be the latter (and it's what I observed).
So the only possibilities I see are "false" or possibly an exception (but the String Javadoc seems to preclude the latter).
I understand the broader point, it's likely that an asymmetric equals
is will lead to problems in code outside of Collections, but I don't see it for the example he quotes.
Am I missing something?
import java.util.List;
import java.util.ArrayList;
class CIString {
private final String s;
public CIString(String s) {
this.s = s;
}
@Override public boolean equals( Object o ) {
System.out.println("Calling CIString.equals from " + this.s );
if ( o instanceof CIString)
return s.equalsIgnoreCase( ( (CIString) o).s);
if ( o instanceof String)
return s.equalsIgnoreCase( (String) o );
return false;
}
// Always override hashCode when you override equals
// This is an awful hash function (everything collides -> performance is terrible!)
// but it is semantically sound. See Item 10 from Effective Java for more details.
@Override public int hashCode() { return 42; }
}
public class CIS {
public static void main(String[] args) {
CIString a = new CIString("Polish");
String s = "polish";
List<CIString> list = new ArrayList<CIString>();
list.add(a);
System.out.println("list contains s:" + list.contains(s));
}
}