Anshul
Anshul

Reputation: 199

Java Collections query

public class Person {
    private String name;
    public Person(String name) { this.name = name; }
    public boolean equals(Person p) {
        return p.name.equals(this.name);
    }
}

    Which statement is true?
    A. The equals method does NOT properly override the Object.equals method.
    B. Compilation fails because the private attribute p.name cannot be accessed in line 5.
    C. To work correctly with hash-based data structures, this class must also implement the
    hashCode method.
    D. When adding Person objects to a java.util.Set collection, the equals method in line 4 will
    prevent duplicates.
    Answer: A

This is a question from a mock exam, I am preparing for ocjp 6 and I have doubts as to the option C. It says "to work correctly", so doesn't that imply needing to overwrite the hashcode? Although not overwriting hashcode() would work, I am focusing on the word CORRECTLY!!!

Upvotes: 2

Views: 673

Answers (3)

Edwin Buck
Edwin Buck

Reputation: 70909

Equals is not correctly implemented, it takes an Object, not a Person as a parameter.

Compilation does not fail due to the private modifier. Private access members are accessible from within the entire surrounding class.

This will not work correctly with hash based data structures, because hashCode() for two instances A and B must be equal when A.equals(B) or B.equals(A). Currently the default implementation of hashCode is based on the instance, and not the equality of name.

Yes, the equals(Object) method will be used to determine if entries are indeed equal in a java.util.Set; however, if it is a hash based Set then hashCode() may be used as a short cut to determining equality. If hashSet() is incorrectly implemented, then the Set may decide to not call equals(Object) afterwards, as the hashCode()s indicate that the two objects cannot be equals.

Note that a proper implementation of hashCode() can definitively determine if an object is not equals but it cannot definitively determine if an object is equals; that is solely reserved for equals(Object). HashCode() is typically very fast to call, so often it is used to discard needed equality checks before the actual call to equals(Object) to determine true equality.

Note that this class lacks an equals(Object) method (but it has a similarly named equals(Person) method that will not be used in equality checks due to the wrong method signature). As such, this class will not work properly in a Set if the intent was to have one entry in the set per name. However, the default implementation of equals(Object) is in effect, as is the default implementation of hashCode() which is tailored to match, so it will work correctly within a Set; but, only if the intent was to not store the same instance twice within the Set.

Upvotes: 4

James Dunn
James Dunn

Reputation: 8264

Yes, answer C is correct.

You are right to focus on the word CORRECTLY. In order for this class to work correctly with hash-based structures, it MUST implement `hashCode()` in a way consistent with its implementation of `equals()`, according to the equals-hashcode contract.

From the javadoc for hashcode():

The general contract of hashCode is:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

Upvotes: 2

Seelenvirtuose
Seelenvirtuose

Reputation: 20608

Answer C is correct! You must also implement the hashCode method in a qay, that two equal persons also have the same hash code.

If you do not, you can put a person into a hash-based data structure, but cannot find it with another instance (that is equal to the first one).

Example:

Person p1 = new Person("me");
Person p2 = new Person("me");
System.out.println(p1.equals(p2)); // prints true
Set<Person> persons = new HashSet<>();
persons.add(p1);
System.out.println(persons.contains(p2)); // prints false (which should be wrong)

Upvotes: 1

Related Questions