views:

90

answers:

2

Consider the sample code given below:

Abstract Name

public abstract class Name {
    private String name;
 public Name(String name)
 {
  this.name=name;
 }
 public String toString()
 {
  return name;

 }
 public String getName() {
  return name;
 }
}

FirstName

public class FirstName extends Name {

 FirstName(String name) {
  super(name);
 }
 public String toString()
 {
  return getName();
 }
}

LastName

public class LastName extends Name{
LastName(String name) {
super(name);
}
public String toString()
{
 return getName();
}
}

TestName

public class TestName {
public static void main(String[] args) {
 Set<Name> names=new HashSet<Name>();
 names.add(new FirstName("George"));
 names.add(new LastName("Bush"));
 names.add(new FirstName("Bush"));
    System.out.println(names);
}
}

Output

[Bush, Bush, George]

Now the question is how to override hashcode and equal's method such that I have only one name "Bush" either as the first name or the last name ?

+3  A: 

You probably want something like this:

 public boolean equals(Object obj)
 {
   if (obj == null)
     return false;
   if (!(obj instanceof Name))
     return false;
   Name name = (Name) obj;
   return this.name.equals(name.name);
 }

 public int hashCode()
 {
   return name.hashCode();
 }
Joshua
This should work: A `HashSet` will not `add()` an object if it already `contains()` an object that `equals()` it.
Jorn
thnx it works.just edit "!obj instanceof Name" to "!(obj instanceof Name)"
Emil
a hashset will only add an element if there isn't an object with the same hashcode in the collection, equals doesn't take part in this
Salandur
@Salandur: you're wrong. `equals()` **does** play an important role here. You can have two objects with the same `hashCode()` in a `HashSet` as long as `a.equals(b)` returns `false`! If that weren't the case, then a hash code collision would be very, very bad, when in fact it is only a slight disadvantage.
Joachim Sauer
true! i was not thinking when writing...
Salandur
+2  A: 

you should provide a custom equals method, not the default one. by contract a FirstName and a LastName can never be equal, because they are 2 different classes (with the same content in this case).

edit: generated equals method from eclipse:

public boolean equals( Object obj )
{
    if ( this == obj )
        return true;
    if ( obj == null )
        return false;
    if ( getClass() != obj.getClass() )
        return false;
    Name other = (Name) obj;
    if ( name == null )
    {
        if ( other.name != null )
            return false;
    }
    else if ( !name.equals( other.name ) )
        return false;
    return true;
}
Salandur
You can't do a getClass() != obj.getClass() check because he wants the LastName to be equated to a First Name. Also, don't forget to always make the hashCode() work the same as the equals()
Joshua
the hashcodes must be the same, when equals returns true. my hashcode calulates its value based on name, so that works. there is no contract so that if the hascodes are the same, equals must return true. so he has to provide a custom equals method with does checks if the other object is an name and has the same content. FirstName en LastName don't provide additional information, so are redundant.
Salandur