I was surprised to see that equals() is apparently overridden for ArrayList<String>. Because contains() in Collection<> apparently compares values, not references. Of course, for Collection<Object>, references would be compared. In the program below, shouldn’t I get false on the second line?
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();
al.add("Obama");
al.add("Reagan");
al.add("Bush");
al.add("Nyquist");
StringBuffer sb = new StringBuffer();
sb.append("Bush");
System.out.println("compares values? using constants " + al.contains("Bush"));
System.out.println("compares values? using local variable " + al.contains(sb.toString()));
}
run:
compares values? using constants true
compares values? using local variable true
This is exactly the output you should expect, and
Collection<Object>would be no different. AllCollectiontypes, unless specified otherwise, use.equals(Object), and differing implementations violate theCollectioncontract. (And to be clear, upcasting aStringto anObjectdoes not change the behavior of itsequalsmethod.)There is some precedent — see e.g. the
TreeSetimplementations, which use comparison-based equality, andIdentityHashSet, which uses reference equality — but these should usually be used only when the two notions of equality match, or for significant and unusual need.