Java HashMap with Int Array

55,265

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 the containsKey(Object key) method says: "returns true if and only if this map contains a mapping for a key k 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 uses java.util.Arrays equals/deepEquals method.
    • And don't forget that when you @Override equals(Object), you must also @Override hashCode
  • Use something like List<Integer> that does define equals 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 print true, 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:

API

  • Object.equals and Object.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.

Share:
55,265
Sunil
Author by

Sunil

Nothing special.............

Updated on July 09, 2022

Comments

  • Sunil
    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 the HashMap?

  • Joachim Sauer
    Joachim Sauer about 14 years
    Implementing only equals() is not enough, you need to implement hashCode() as well. See Chapter 3 of Effective Java (available online: java.sun.com/developer/Books/effectivejava/Chapter3.pdf)
  • Ashwin Jayaprakash
    Ashwin Jayaprakash over 10 years
    This is explained here - stackoverflow.com/questions/8777257/…
  • ArpitA
    ArpitA over 2 years
    new 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