views:

533

answers:

7

Say i create one object and add it to my ArrayList. If I then create another object with exactly the same constructor input, will the contain() method evaluate the two objects to be the same? Assume the constructor doesn't do anything funny with the input, and the variables stored in both objects are identical.

ArrayList<Thing> basket = new ArrayList<Thing>();
Thing thing = new Thing(100);
basket.add(thing);
Thing another = new Thing(100);
basket.contains(another); // true or false?


class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    equals (Thing x) {
        if (x.value == value) return true;
        return false;
    }
}

Is this how the class should be implemented to have contains() return true?

+3  A: 

The ArrayList uses the equals method implemented in the class (your case Thing class) to do the equals comparison.

Bhushan
A: 

Implement the equals() method in your class.

Shadow
An object does not need to implement `Comparable` for the `contains` method to work.
danben
If you want it to compare correctly it does.
Shadow
Shadow, did you look implementation of 'conatains'?
Adi
where exactly is this 'conatains'? Do you mean 'Contains'?
Shadow
@Shadow - this is **so wrong**. Firstly, Comparable (only) defines a `compareTo` method, and the List contract says that `contains` uses `equals` ... not `compareTo`. So any `compareTo` method you define will be ignored by a properly code `List` implementation. Second, `contains` **will** work if you don't define `equals` in your class. It will use the inheritted implementation of `equals`. If there are no overrides in super classes, `equals` will be equivalent to the `==` operator. That works just fine!
Stephen C
Well sorry about the oversight, I shouldn't have let this wrong answer slip all night. Answer has been changed.
Shadow
+2  A: 

It uses the equals method on the objects. So unless Thing overrides equals and uses the variables stored in the objects for comparison, it will not return true on the contains() method.

Yishai
+5  A: 

ArrayList implements the List Interface.

If you look at the Javadoc for List at the contains method you will see that it uses the equals() method to evaluate if two objects are the same.

Binary Nerd
Just in case you plan to override equals(), make sure you override hashcode() method as well. If you wont, things may not work as expected while using Collections?
Mohd Farid
+1  A: 

Yes, your implementation is correct for contains().

If you didn't override the equals() method, you would still have the default implementation, which would compare the objects by reference.

You've apparently decided to compare the objects by value.

The contains() function will iterate through the collection and return true if equals() returns true for any of the elements, otherwise it will return false.

Your call to contains will return true.

Marcus Adams
+1  A: 

Other posters have addressed the question about how contains() works.

An equally important aspect of your question is how to properly implement equals(). And the answer to this is really dependent on what constitutes object equality for this particular class. In the example you provided, if you have two different objects that both have x=5, are they equal? It really depends on what you are trying to do.

If you are only interested in object equality, then the default implementation of .equals() (the one provided by Object) uses identity only (i.e. this == other). If that's what you want, then just don't implement equals() on your class (let it inherit from Object). The code you wrote, while kind of correct if you are going for identity, would never appear in a real class b/c it provides no benefit over using the default Object.equals() implementation.

If you are just getting started with this stuff, I strongly recommend the Effective Java book by Joshua Bloch. It's a great read, and covers this sort of thing (plus how to correctly implement equals() when you are trying to do more than identity based comparisons)

Kevin Day
For my purpose I was trying to see if an object of equal value was in the ArrayList. I suppose it is a sort of hack. Thank you for the book recommendation
mvid
+1  A: 

Generally you should also override hashCode() each time you override equals(), even if just for the performance boost. HashCode() decides which 'bucket' your object gets sorted into when doing a comparison, so any two objects which equal() evaluates to true should return the same hashCode value(). I cannot remember the default behavior of hashCode() (if it returns 0 then your code should work but slowly, but if it returns the address then your code will fail). I do remember a bunch of times when my code failed because I forgot to override hashCode() though. :)

alexloh