I am trying to use an ArrayList
as a key in a HashMap
, but if I add values to the list after setting the list as a key, the map won't recognize the list anymore. I have already found a solution for my problem, but it is an ugly way of doing it, here is some example code for the problem:
HashMap<Object,String> hm = new HashMap<Object,String>();
List<String> l = new ArrayList<String>();
hm.put(l, "stuff");
l.add("test");//add item after adding the list to the hashmap
System.out.println(hm.get(l));
this will return the text "null" while
HashMap<Object,String> hm = new HashMap<Object,String>();
List<String> l = new ArrayList<String>();
l.add("test"); //add item before adding the list to the hashmap
hm.put(l, "stuff");
System.out.println(hm.get(l));
works fine and returns "stuff"
Does anyone know why this happens?
Short: because keys must be immutable for hashmaps to work (at least their identity must be immutable) and lists aren't.
Long: when you add a key to a map its hashCode()
method is used to determine the bucket the entry is put into. Inside that bucket equals()
is used to check whether that key already exists in there. The same is true for lookups.
Now ArrayList
does a deep equals()
and hashCode()
so if you alter the list after using it as key you'll end up in a different bucket or with a different outcome for equals()
and the map most likely won't find it.
Edit
hashCode()
implementation for AbstractList
(which ArrayList
extends):
public int hashCode() {
int hashCode = 1;
for (E e : this)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
return hashCode;
}
As you can see: if the list is empty the hash code will be 1 otherwise the hash code will be something else (in your case 31 * "test".hashCode()
). Thus you're likely to end up looking in a different bucket which will fail.
Edit 2
Clarification on "different outcome for equals()
": of course equals()
should return true if the list used as a key and the list used for the lookup only contain equal elements in the same order. But if you change that list after using it as a key you might end up in different situations:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.