Question

Here is my code:

import java.util.HashMap;

class MyString
{
  String string;

  MyString(String string)
  {
    this.string = new String(string);
  }
}

public class test
{

  public void test3()
  {
    HashMap<MyString, Byte> byteHashMap = new HashMap<MyString, Byte>();
    char c = 'A';
    byte b = (byte)c;

    String string = new String("The Letter A");
    MyString myString = new MyString(string);

    byteHashMap.put(myString, b);

    if (byteHashMap.containsKey(myString))
    //if (byteHashMap.containsKey(new MyString(string)))
    {
      System.out.println("true");
    }
    else
    {
      System.out.println("false");
    }
  }

  public static void main(String[] args)
  {
    test testObject = new test();
    testObject.test3();
  }
}

I would like to know why the code, as is, returns true. However, when I switch the if statements (see the commented line), it returns false.

I believe it has something to do with overriding the equals method in the MyString class but I am unsure how to approach this.

Regards.

Was it helpful?

Solution

Your belief is correct. Map structures rely on .equals to determine if a key already exists in the map or not. By default, object types have instance equality (meaning a.equals(b) is true if and only if a and b point to the same object).

In your case, you probably want two MyString instances to be equal if the string field is equal. In this case, you would override equals with something like:

@Override
public boolean equals(Object other) {
    if (other == null) { return false; }
    if (!(other instanceof MyString)) { return false; }
    MyString m = (MyString)other;
    return this.string.equals(m.string);
}

With this, either of the two if statements would return true.

You should also override hashCode. If you use Eclipse, it can generate these two methods for you quite easily via the Source menu.

OTHER TIPS

Yes, override hashCode and equals. Right now you will compare a string against the memory reference (standard implementation) of your MyString object.

example

@Override
public bool equals(Object args0) {
   if(args0 == this) { return true; }
   if(!(args0 instanceof MyString)) { return false; }
   MyString obj = (MyString) args0;

   return obj.getString().equals(this.string); // Create getter
}

@Override
public int hashCode(){
   return this.string.hashCode() * 37;
}

You need to implement hashCode and equals. HashMaps put objects in buckets based on the hashCode. Different objects can have the same hashCode, but the rule is that two equal objects must have the same hashCode. Once the HashMap finds all of the entries with the same hashCode, it then checks for equality using the equals method.

The default implementation checks for object instance equality - that is, are the two objects the same instance. In your case, you're checking two different instances.

Override the equals and hashCode methods to pass through the values returned by hashCode() and equals() for the private String member variable, assuming that's all that determines if two instances of your class are equal.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top