codinguser
codinguser

Reputation: 5572

Why does this String.equals() method always return false?

I have a class for which I have implemented a custom hashCode() and equals(Object) method using the Eclipse method generator. Each object of the class has a String field called mUid which should be unique and is enough to determine equality. The overridden methods look like this:

    @Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((mUid == null) ? 0 : mUid.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    DataSource other = (DataSource) obj;
    if (mUid == null) {
        if (other.mUid != null)
            return false;
    } else if (!mUid.equals(other.mUid))
        return false;
    return true;
}

But for some reason, when I compare two objects of my class, it always returns false. I've stepped through the code with a debugger and can determine that the mUid strings are the same. But my equals(Object) method always returns false at the line

if (!mUid.equals(other.mUid)) {return false;}.

This means the String equals() method is saying the strings are not equal. But, in the debugger I can see that even their hashcodes are equal.

Here is a debugging screenshot: Debugging screenshot Can anyone please explain what is happening? Thanks.

Update: It works!

I should point out that I am not calling the equals(...) method directly, but rather from List<DataSource> list.contains(DataSource). It turns out that if I step through the equals(Object) code, it shows me that it returns false for comparing every object in the list (even if there is a match). But it seems the List.contains() method returns the right value (true or false) anyway. Don't know why this is, but it works. I had an extra semicolon after the if(list.contains(dataSource)); so I could not rightly see that contains() was working fine. Thanks for your help everyone.

Upvotes: 0

Views: 10299

Answers (5)

Nicolas Bousquet
Nicolas Bousquet

Reputation: 4000

Ok so I taken a look at a decompiled version of String.equals:

public boolean equals(Object obj)
{
    if(this == obj)
        return true;
    if(obj instanceof String)
    {
        String s = (String)obj;
        int i = count;
        if(i == s.count)
        {
            char ac[] = value;
            char ac1[] = s.value;
            int j = offset;
            int k = s.offset;
            while(i-- != 0) 
                if(ac[j++] != ac1[k++])
                    return false;
            return true;
        }
    }
    return false;
}

So in the debbuger, I would try to compare and print the 2 char Arrays. You can use the toCharArray method for this. If the char indeed differs, it is likely to be an encoding problem and I'd try to check the encoding used by Yahoo and ensure you decode using it.

Upvotes: 0

pajevic
pajevic

Reputation: 4657

Your method should work. I just tested with this code and it worked fine:

public class DataSource {

    private String mUid;

    public DataSource(String m) {
        mUid = m;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((mUid == null) ? 0 : mUid.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        DataSource other = (DataSource) obj;
        if (mUid == null) {
            if (other.mUid != null)
                return false;
        } else if (!mUid.equals(other.mUid))
            return false;
        return true;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        DataSource ds1 = new DataSource("test");
        DataSource ds2 = new DataSource("test");
        System.out.println(ds1.equals(ds2));
    }

}

The console output was "true"; When I changed the code to DataSource ds2 = new DataSource("test1"); it returned "false";

Upvotes: 2

If you used the Eclipse generator this is very strange, and hand editing the generated code should not be necessary. Can you post the whole class source code? Do you extend another objects?

Upvotes: 0

Niranj Patel
Niranj Patel

Reputation: 33248

try this

 if (mUid == null)
{
    if (other.mUid != null)
        return false;
} 
else if (!mUid.equalsIgnoreCase(other.mUid))
    return false;
return true;

Upvotes: 0

Thomas
Thomas

Reputation: 88707

This means the String equals() method is saying the strings are not equal. But, in the debugger I can see that even their hashcodes are equal.

Equal hashcodes do not necessarily represent equal strings. Are their contents really equal?

Upvotes: 0

Related Questions