迭代Hash密钥集时的空值

时间:2011-06-24 01:04:51

标签: java hashmap

令我困惑的是,以下段如何导致Boolean必需的null值,尽管它在实际哈希表中的相应键处不为null:

for (List<List<A>> a : hashMap.keySet()) {  
    Boolean mandatory = hashMap.get(a);
}

3 个答案:

答案 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<>>密钥,如果你搞砸了equalsA方法,那么你的列表'equals方法也会搞砸,再次搞砸了你的地图。

如果您需要进一步证明您尝试做的事情是个坏主意,请查看alphazero的优秀代码示例。