Tired up with trying to resolve the problem with this code:
public class MapTest {
static class T{
static class K{}
}
static Map<List<T.K>, List<String>> map = new HashMap<>();
static List<String> test(List<T.K> list, String s){
List<String> l = map.get(list);
if (l == null){
l = new ArrayList<String>();
System.out.println("New value()");
map.put(list, l);
}
l.add(s);
return l;
}
public static void main(String s[]){
ArrayList<T.K> list = new ArrayList<T.K>();
test(list, "TEST");
list.add(new T.K());
List<String> l = test(list, "TEST1");
System.out.println(l.size());
}
}
It should create a new list-value for the map only once, but output is as follows:
New value
New value
1
it is something wrong happen with hashcode of the list after I insert value in it. I expect "new value" show up only once, and size will be 2, not 1. is it just JVM problem or something more general? mine one is Oracle JVM 1.8.0_65
The hashcode of the list object changes when you put an item in it. You can see how the hashcode is calculated in the ArrayList.hashCode documentation.
In general, using a mutable object as the key for a map isn't going to work well. Per the Map documentation:
Note: great care must be exercised if mutable objects are used as map keys. The behavior of a map is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is a key in the map.
Thus, when you add the list to the map a second time, the map doesn't see it as being "equal" to the first list (since it isn't according to .equals), so it adds it again.
If you want a map where keys are looked up by identity rather than by value, you can use the IdentityHashMap class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With