likejudo
likejudo

Reputation: 3736

contains() compares by value, not reference?

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

Upvotes: 3

Views: 6797

Answers (3)

Tuhin Ghosh
Tuhin Ghosh

Reputation: 21

you can try System.out.println(sb.toString().equals("Bush")); in your class and see what it returns. It will return true. So in the second case it is returning/printing true.

Upvotes: 0

Brian Roach
Brian Roach

Reputation: 76908

Javdaocs for List are you friend. List.contains() relies on .equals():

boolean contains(Object o)
Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that (o==null ? e==null : o.equals(e)).

String.equals() compares the Strings contents (characters):

public boolean equals(Object anObject)
Compares this string to the specified object. The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.

Upvotes: 5

Louis Wasserman
Louis Wasserman

Reputation: 198211

This is exactly the output you should expect, and Collection<Object> would be no different. All Collection types, unless specified otherwise, use .equals(Object), and differing implementations violate the Collection contract. (And to be clear, upcasting a String to an Object does not change the behavior of its equals method.)

There is some precedent -- see e.g. the TreeSet implementations, which use comparison-based equality, and IdentityHashSet, which uses reference equality -- but these should usually be used only when the two notions of equality match, or for significant and unusual need.

Upvotes: 4

Related Questions