Froskoy
Froskoy

Reputation: 3027

Java - Retrieving objects from HashMap

I have a problem when retrieving values from a hashmap. The hashmap is declared as follows:

HashMap<TRpair,A> aTable = new HashMap<TRpair,A>();

I then put 112 values into the map as follows:

aTable.put(new TRpair(new T(<value>),new Integer(<value>)),new Ai());

where Ai is any one of 4 subclasses that extend A.

I then proceed to check what values are in the map, as follows:

int i = 0;
for (Map.Entry<TRpair,A> entry : aTable.entrySet()) {
    System.out.println(entry.getKey().toString() + " " + entry.getValue().toString());
    System.out.println(entry.getKey().equals(new TRpair(new T("!"),new Integer(10))));
    i++;
}

i holds the value 112 at the end, as one would expect and the equality test prints true for exactly one entry, as expected.

However, when I do

System.out.println(aTable.get(new TRpair(new T("!"), new Integer(10))));

null is output, despite the above code snippet confirming that there is indeed one entry in the map with exactly this key.

If it helps, the class TRpair is declared as follows:

public class TRpair {
    private final T t;
    private final Integer r;

    protected TRpair(Integer r1, T t1) {
        terminal = t1;
        row = r1;
    }

    protected TRpair(T t1, Integer r1) {
        t = t1;
        r = r1;
    }

    @Override
    public boolean equals(Object o) {
        TRpair p = (TRpair)o;
        return (p.t.equals(t)) && (p.r.equals(r));
    }

    @Override
    public String toString() {
        StringBuilder sbldr = new StringBuilder();
        sbldr.append("(");
        sbldr.append(t.toString());
        sbldr.append(",");
        sbldr.append(r.toString());
        sbldr.append(")");
        return sbldr.toString();
    }
}

the equals() and toString() methods in each of the Ai (extending A) and in the T class are overridden similarly and appear to behave as expected.

Why is the value output from the hashmap aTable null, when previously it has been confirmed that the value for the corresponding key is indeed in the map?

With many thanks,

Froskoy.

Upvotes: 1

Views: 467

Answers (2)

Konstantin Pribluda
Konstantin Pribluda

Reputation: 12367

IIRC hashmap looks up by hashCode() and not by equality, and since you did not implemented hashcode you use default implementation which is consistent with object pointer equality - you need to implement proper hashcode function which takes into account "T" parameter as well as integer (or not)

It is good practice that hashCode() and equals() are consistent, but not structly necessary if you know what you are doing.

Upvotes: 1

Peter Lawrey
Peter Lawrey

Reputation: 533930

The keys/elements for a Hash collection but override hashCode() if euqals is overridden.

You could use.

public int hashCode() {
    return t.hashCode() * 31 ^ r.hashCode();
}

BTW: It appears from your code that Integer r cannot be null in which case using int r makes more sense.

From Object.equals()

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

Upvotes: 3

Related Questions