Integer as key in HashMap

I

Ike

if I have an Integer object as a key in a HashMap, and I create that Integer
from an int, use that to put() a String as value in the HashMap, can I later
create a new Integer object, from the same int value, and use this latter
Integer object to get() the value of that String I put in?

Or must I use the actual Integer object I first created? Thank you, Ike
 
I

Ingo R. Homann

Hi,

Chris said:
Try it and see.

Bad idea. Then he knows that it (accidentially?) works for the 5 Million
of Integers that he tested, but does not know that it works in general.

@Ike: It works generally! (Look at the doku: for the use as a key in a
HashMap, the class must implement hashCode() and equals(). The class
Integer does that.)

Ciao,
Ingo
 
K

KS

@Ike: It works generally!

I have written code that relies on this property. And it has always
worked. The reason probably is that the hashCode method of the Integer
class uses the int value that it currently wraps to compute the hash
code. (Otherwise it would be a meaningless implmentation of hashCode)
 
P

Patricia Shanahan

Ike said:
if I have an Integer object as a key in a HashMap, and I create that Integer
from an int, use that to put() a String as value in the HashMap, can I later
create a new Integer object, from the same int value, and use this latter
Integer object to get() the value of that String I put in?

Or must I use the actual Integer object I first created? Thank you, Ike

It will work the first way.

In general, you need to consider the equals method for the key class. An
Object, or any object inheriting the Object equals, is equal to itself
and nothing else. For an Object key, you would have to use the actual
Object instance.

The Integer equals API documentation says "The result is true if and
only if the argument is not null and is an Integer object that contains
the same int value as this object.". If you follow the procedure you
describe, the object used in get() will be equal to the key, so the
second method works.

If you don't trust the implementer of the key class, you should also
check the hashCode description. The first method is reliable if, and
only if, the hashCode implementation is consistent with equals according
to the contract described for Object. If two objects are equal, they
must have the same hashCode.

I have not yet found a Sun API class with a problem in this area, and
the Integer documentation says "a hash code value for this object, equal
to the primitive int value represented by this Integer object." which is
fine.

Patricia
 
T

Tom Hawtin

Chris said:
How does it work accidentally?

Have you been programming long? Accidents are easy.

Take this program of mine.

class Accident {
public static void main(String[] args) {
java.util.Map<Long,String> map =
new java.util.IdentityHashMap<Long,String>();
map.put(1L, "fred");
System.err.println(map.get(1L));
}
}

It works! Now try replacing 1 with 1729. Interesting...

(Technically it may or may not work, in both cases.)

Tom Hawtin
 
C

Chris Uppal

Chris said:
How does it work accidentally?

Suppose that the HashMap /might/ compare its Integer keys using identity
comparison (it doesn't, in fact, as others have said, but that is the
possibility that the OP was worried about). Now, when you run your test (which
is intended to fail if HashMaps use identity comparison for Integers), how do
you know whether it was working because somehow you (somehow) used the /same/
instance of java.lang.Integer for each index without realising it, or because
the HashMap works in the way we want it to ?

It's not an academic question. There are various ways of creating an
java.lang.Integer from an int (including the auto-boxing done implicitly by the
compiler), and some of those make use of a cache of Integer instances.

So, in order to tell whether you have created a valid test (one that doesn't
risk working "by accident"), you have to know quite a lot about the documented
behaviour of java.lang.Integer (and autoboxing). It much easier to look up the
documentation for Integer.equals() and Integer.hashCode() to see how they'll
work with HashMap[*], than trying to find the rather more esoteric infomation
about caching in java.lang.Integer to tell whether you have a useful test.

-- chris

[*] Just as you would if you wanted to know how any other kind of object would
work in a HashMap.
 
J

John W. Kennedy

Tom said:
Chris said:
How does it work accidentally?

Have you been programming long? Accidents are easy.

Take this program of mine.

class Accident {
public static void main(String[] args) {
java.util.Map<Long,String> map =
new java.util.IdentityHashMap<Long,String>();
map.put(1L, "fred");
System.err.println(map.get(1L));
}
}

It works! Now try replacing 1 with 1729. Interesting...

(Technically it may or may not work, in both cases.)

No-one has been talking about an IdentityHashMap. The question was about
ordinary HashMaps, which /do/ work with Integer (and Long and Double and
probably Byte and Short, too, but the documentation is not explicit).
 
I

Ingo R. Homann

Hi,
No-one has been talking about an IdentityHashMap. The question was about
ordinary HashMaps, which /do/ work with Integer

Yes. But the OP did not know that it /does/ work and asked for it. But
Chris' hint to "try" it was no good hint. Tom demonstrated that in
general it is not a good idea only to *try*. To repeat myself: When he
tried it, he knows that it works for the 5 Million of Integers that he
tested, but does *not* know if it works 'accidentially' (like the test
with IndentityHashMap and '1L') or if it works *in general*.
> (and Long and Double and
probably Byte and Short, too, but the documentation is not explicit).

IMHO it is: equals() and hashCode() are overridden in the classes you
mention, and somewhere in the docs, it is mentioned that this is enough
to let a HashMap work correctly.

Ciao,
Ingo
 
J

John W. Kennedy

Ingo said:
Hi,


Yes. But the OP did not know that it /does/ work and asked for it. But
Chris' hint to "try" it was no good hint. Tom demonstrated that in
general it is not a good idea only to *try*. To repeat myself: When he
tried it, he knows that it works for the 5 Million of Integers that he
tested, but does *not* know if it works 'accidentially' (like the test
with IndentityHashMap and '1L') or if it works *in general*.


IMHO it is: equals() and hashCode() are overridden in the classes you
mention, and somewhere in the docs, it is mentioned that this is enough
to let a HashMap work correctly.

Double, Float, Long and Integer specifically say that they use
value-based hashCode(), and give the exact algorithms. Char, Short and
Byte merely mention that they override hashCode(), but do not say how,
at least in the 6.0 docs. Long, Integer, Char, Short, and Byte specify
class and value equality for equals(); Double and Float specify class
and bit equality.

If Char, Short, and Byte are documented as providing hashCode() that
works for HashMap, it is not in the obvious place.
 
T

Tom Hawtin

John said:
Double, Float, Long and Integer specifically say that they use
value-based hashCode(), and give the exact algorithms. Char, Short and
Byte merely mention that they override hashCode(), but do not say how,
at least in the 6.0 docs. Long, Integer, Char, Short, and Byte specify
class and value equality for equals(); Double and Float specify class
and bit equality.

All of the classes you have mentioned extend Object(!). The spec for
Object is enough to clarify the meaning (if the intent really needs
clarification).

Tom Hawtin
 
J

John W. Kennedy

Tom said:
All of the classes you have mentioned extend Object(!). The spec for
Object is enough to clarify the meaning (if the intent really needs
clarification).

To the extent that Object requires that a.hashCode() == b.hashCode if
a.equals(b), yes, that is true.

I still wish that Char, Short, and Byte documented how they do
hashCode(), since Long, Integer, Double, and Float do.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,710
Latest member
bernietqt

Latest Threads

Top