Java HashMap with Int Array
You are comparing two different references. Something like this will work:
public class Test {
public static void main(String[] arg)
{
HashMap<int[],String> map= new HashMap<int[],String>();
int[] a = new int[]{1,2};
map.put(a, "sun");
System.out.println(map.containsKey(a));
}
}
Since a
is the same reference, you will receive true
as expected. If your application has no option of passing references to do the comparison, I would make a new object type which contains the int[]
and override the equals()
method (don't forget to override hashCode()
at the same time), so that will reflect in the containsKey()
call.
I would use a different approach. As mentioned before, the problem is with arrays equality, which is based on reference equality and makes your map useless for your needs. Another potential problem, assuming that you use ArrayList instead, is the problem of consistency: if you change a list after is has been added to the map, you will have a hashmap corruption since the position of the list will not reflect its hashcode anymore.
In order to solve these two problems, I would use some kind of immutable list. You may want to make an immutable wrapper on int array for example, and implement equals() and hashCode() yourself.
The problem is because the two int[]
aren't equal.
System.out.println(
(new int[] { 1, 2 }).equals(new int[] { 1, 2 })
); // prints "false"
Map
and other Java Collections Framework classes defines its interface in terms of equals
. From Map API
:
Many methods in Collections Framework interfaces are defined in terms of the
equals
method. For example, the specification for thecontainsKey(Object key)
method says: "returnstrue
if and only if this map contains a mapping for a keyk
such that(key==null ? k==null : key.equals(k))
."
Note that they don't have to be the same object; they just have to be equals
. Arrays in Java extends from Object
, whose default implementation of equals
returns true only on object identity; hence why it prints false
in above snippet.
You can solve your problem in one of many ways:
- Define your own wrapper class for arrays whose
equals
usesjava.util.Arrays
equals/deepEquals
method.- And don't forget that when you
@Override equals(Object)
, you must also@Override hashCode
- And don't forget that when you
- Use something like
List<Integer>
that does defineequals
in terms of the values they contain - Or, if you can work with reference equality for
equals
, you can just stick with what you have. Just as you shouldn't expect the above snippet to ever printtrue
, you shouldn't ever expect to be able to find your arrays by its values alone; you must hang-on to and use the original references every time.
See also:
- Overriding equals and hashCode in Java
- How to ensure hashCode() is consistent with equals()?
- Understanding the workings of equals and hashCode in a HashMap
API
Object.equals
andObject.hashCode
- It's essential for a Java programmer to be aware of these contracts and how to make them work with/for the rest of the system
I think the problem is your array is doing an '==' comparison, i.e. it's checking the reference. When you do containsKey(new int[] { ... }), it's creating a new object and thus the reference is not the same.
If you change the array type to something like ArrayList<Integer>
that should work, however I would tend to avoid using Lists as map keys as this is not going to be very efficient.