Java HashMap with Int Array
Solution 1
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
Solution 2
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.
Solution 3
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.
Solution 4
The hashCode()
implementation for arrays is derived from Object.hashCode()
, so it depends on the memory location of the array. Since the two arrays are instantiated separately, they have different memory locations and thus different hashcodes. If you made one array it would work:
int[] arr = {1, 2};
map.put(arr, "sun");
System.out.println(map.containsKey(arr));
Solution 5
You've got two different objects that happen to contain the same values, because you've called new twice.
One approach you might use is to create a "holder" class of your own, and define that class's equals and hash methods.
Comments
-
Sunil almost 2 years
I am using this code to check that array is present in the
HashMap
:public class Test { public static void main(String[] arg) { HashMap<int[], String> map = new HashMap<int[], String>(); map.put(new int[]{1, 2}, "sun"); System.out.println(map.containsKey((new int[]{1, 2}))); } }
But this prints
False
. How can I check that array is present in theHashMap
? -
Joachim Sauer about 14 yearsImplementing only
equals()
is not enough, you need to implementhashCode()
as well. See Chapter 3 of Effective Java (available online: java.sun.com/developer/Books/effectivejava/Chapter3.pdf) -
Ashwin Jayaprakash over 10 yearsThis is explained here - stackoverflow.com/questions/8777257/…
-
ArpitA over 2 yearsnew int[]{12} will also return the sun which would be false . So, instead of just converting it to string we can put some kind of identifier like # So, int[]{1,2} will be #1#2 AND int[]{12} will be #12