令我困惑的是,以下段如何导致Boolean必需的null值,尽管它在实际哈希表中的相应键处不为null:
for (List<List<A>> a : hashMap.keySet()) {
Boolean mandatory = hashMap.get(a);
}
答案 0 :(得分:2)
HashMap将返回null
if the key specified is not bound to a value。
问题几乎可以肯定,a
上的比较操作 - 列表 - 反对键失败。
让我猜一下:你在调用put之后修改这些列表(关键对象)了吗?您是否删除了其中一个键中的所有条目?请记住,所有空ArrayList的空列表都是equal
。进一步记住,List.equals()将列表内容(逐个)与测试相等性进行比较。
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 */ }
}
结果:
[](ArrayList@1) => true
[sof_6462281.ListAsKey$A@4b71bbc9](ArrayList@1265744872) => null
[](ArrayList@1) => true
编辑:在上面添加了更多操作并添加了控制台。
答案 1 :(得分:0)
Boolean可以为null,因为它包装了value-type primitive boolean。我不确定你的意思是它在实际哈希表中的相应键上不为空。您正在遍历键,然后获取这些键的值。键的值被插入为null,因此当您检索它时,您将获得null。
答案 2 :(得分:0)
将可变对象用于Map键始终是一件危险的事情。如果在插入地图后保留对任何这些键的任何引用,则很可能在将来的某个时刻修改其中一个键,这将使地图内容无效。
不太可能,但可能的情况,即使假设你以某种方式搞砸了List<List<>>
密钥,如果你搞砸了equals
类A
方法,那么你的列表'equals
方法也会搞砸,再次搞砸了你的地图。
如果您需要进一步证明您尝试做的事情是个坏主意,请查看alphazero的优秀代码示例。