Reputation: 4275
It puzzles me how the following segment can lead to a null value of the Boolean mandatory, although it is not null at the corresponding key in the actual hashtable:
for (List<List<A>> a : hashMap.keySet()) {
Boolean mandatory = hashMap.get(a);
}
Upvotes: 2
Views: 4173
Reputation: 5930
Using a mutable object for a Map key is always a dangerous thing. If you maintain any reference to any of those keys after inserting into the map, then it is very likely that one of those keys will be modified at some point in the future which will invalidate the contents of your map.
A less likely, but possible scenario, even assuming you somehow don't screw up your List<List<>>
key is if you have messed up the equals
method of class A
, then your Lists' equals
method will also be messed up, again screwing up your map.
Look at alphazero's nice code example if you need further proof that what you are attempting to do is a bad idea.
Upvotes: 0
Reputation: 27234
A HashMap will return null
if the key specified is not bound to a value.
Issue is almost certainly that comparison op on a
-- a List -- against keys is failing.
Let me guess: are you modifying these lists (the key object) after you have called a put? Did you remove all entries in one of the keys? Remember an empty list is equal
to all empty ArrayLists. Further remember that List.equals() compares list content (one by one) to test equality.
package sof_6462281;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Demonstrate the fact that the Map uses key.equals(k) to
* test for key equality. Further demonstrate that it is a
* very bad idea to use mutable collections are keys to maps.
*/
public class ListAsKey {
public static void main(String[] args) {
Map<List<A>, Boolean> map = new HashMap<List<A>, Boolean>();
List<A> alist = new ArrayList<A>();
map.put(alist, true);
for (List<A> a : map.keySet()) {
Boolean b = map.get(a);
System.out.format("\t%s(ArrayList@%d) => %s\n",a, a.hashCode(), map.get(a));
}
// you changed your list after the put, didn't you?
alist.add(new A());
for (List<A> a : map.keySet()) {
Boolean b = map.get(a);
System.out.format("\t%s(ArrayList@%d) => %s\n",a, a.hashCode(), map.get(a));
}
alist.clear();
for (List<A> a : map.keySet()) {
Boolean b = map.get(a);
System.out.format("\t%s(ArrayList@%d) => %s\n",a, a.hashCode(), map.get(a));
}
}
public static final class A { /* foo */ }
}
Results:
[](ArrayList@1) => true
[sof_6462281.ListAsKey$A@4b71bbc9](ArrayList@1265744872) => null
[](ArrayList@1) => true
edit: added more ops to above and added console out.
Upvotes: 2
Reputation: 10824
Boolean can be null because it wraps the value-type primitive boolean. I am unsure what you mean its not null at the corresponding key in the actual hashtable. You are iterating over the keys then getting the values at those keys. The value at a key was inserted as null so when you are retrieving it you are getting the null.
Upvotes: 0