3

I have a List which will be changed overtime and I want to store it with a time value and check if the same List appears again.

ex:

[1, 2, 3] is same as [1, 2, 3]

I thought that since List<Integer> is passed by the reference value, so I think the key should be stringified to be used.

E.g.:

Map<String, Integer> = new HashMap<>()
(key:"stringified key", value: .....)

But I find that Map<List<Integer>, Integer> map = new HashMap<>() also works but I don't know why it works, since the key should be reference to the same list no matter what the values in list changed.

E.g.:

(key:[reference to key], value: .....)
List<Integer> testList = new ArrayList<>();
testList.add(0);
map.put(testList, 0);
testList.set(0, 1);
if(map.containsKey(testList))System.out.println("duplicate");
else System.out.println("unique");

The above result will print "unique" but I think it should print "duplicate". Why does the above result show this?

senseiwu
  • 5,001
  • 5
  • 26
  • 47
Jason
  • 1,573
  • 3
  • 18
  • 46
  • 5
    Never modify a key object in a map. Unpredictable behaviour is for certain. Instead remove the mapping, modify the key and reinsert. The reason you get *unique* in this case is that the hashcode of the list has changed, so the hash map cannot find it even though it is in there, only now stored under the wrong hash value. Or instead you *might* perhaps wrap your list in an object the hashcode of whoch doesn’t depend in the list, but this would be ugly and hard to maintain. so I recommend you don’t. – Ole V.V. Mar 14 '19 at 15:57
  • ... the last line of the code block `else System.out.println("unique);` is missing quotation marks – FailingCoder Mar 14 '19 at 16:00

1 Answers1

5

Since yoy changed the content of the ArrayList the value of the ArrayList hashCode also changed.

List<Integer> l = new ArrayList<>();
l.add(0); 
System.out.println(l.hashCode()); // 31
l.set(0, 1);
System.out.println(l.hashCode()); // 32

This goes against the principle of HashMap where the hashCode is used to find the element's location. Objects used for the HashMap keys should have constant hashCode, otherwise the HashMap lookup logic won't work.

Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
  • is this kind of bug? since hashcode in updated for `ArrayList` but not in the hash bucket – Ryuzaki L Mar 14 '19 at 16:55
  • @Deadpool `HashMap` uses `hashCode` value to select the bucket on insertion. If different `hashCode` is used during lookup it will look into different bucket and won't find the value. – Karol Dowbecki Mar 14 '19 at 17:20