1

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.

asked Sep 17, 2012 at 12:10
3
  • 2
    You will need to override hashCode() method in TRpair, no? Commented Sep 17, 2012 at 12:12
  • Why? Is it not sufficient that equals() is overridden? Commented Sep 17, 2012 at 12:14
  • 1
    hashCode() needs to be overridden to maintain equality if more objects have equal values (and state). More Hashable tables check consistency and equality by hashes. Commented Sep 17, 2012 at 12:25

2 Answers 2

3

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.

answered Sep 17, 2012 at 12:13
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks! Is 31 chosen simply because it is an arbitrary prime, or is there another reason?
It a somewhat arbitrary but commonly used prime number. e.g. String.hashCode() uses it.
@Froskoy, you can use any prime number of your choice.
Thanks again! Also, what should I put in t.hashCode() and r.hashCode() - just something that will be unique to that t/r?
@Froskoy you can use any non-trivial prime number. I wouldn't use 2. ;)
|
1

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.

Buhake Sindi
89.4k30 gold badges176 silver badges234 bronze badges
answered Sep 17, 2012 at 12:16

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.