向TreeMap添加条目时抛出NullPointerException

时间:2018-10-26 10:03:58

标签: java

以下代码在tm.put("dd",7);上引发NPE。为什么是这样?我已经添加了调试功能,并且看来我的比较功能是错误的,但是我委托给了String.compare。 如何解决该问题,以便我可以向TreeMap中添加新条目,并且它将自动按VALUE对新条目进行排序?谢谢。

编辑我所遇到的问题是,就我所知,TreeMap应该进行连续排序-您应该能够将条目添加到已填充的TM中,并保留地图以排序的顺序。到目前为止给出的解决方案不允许我这样做。当我添加(“ cc”,7)时,我希望根据我提供给构造函数的比较器将该条目“插入”。 这应该可行,不是吗?

EDIT2 我现在可以看到自己,这可能是不可能的,因为在构造时会提供比较器对象用于查找值的映射。可能有解决方法,但我看不到。

static void f16(){
        Map<String,Integer> hm = new HashMap<>();
        hm.put("xx",5);        hm.put("xz",6);        hm.put("cx",9);        hm.put("ax",2);

        class ValueComparator implements Comparator<String> { //satisfies Comparator<K> req of TreeMap const
            Map<String,Integer> map;
            ValueComparator(Map<String,Integer> map){
                this.map=map;
            }
            public int compare(String k1, String k2){
                System.out.printf("k1:%s k2:%s\n",k1,k2);//for debugging
                return this.map.get(k1).compareTo(this.map.get(k2));
            }
        }
        ValueComparator valueComp = new ValueComparator(hm);
        NavigableMap<String,Integer> tm = new TreeMap<>(valueComp);
        tm.putAll(hm);
        System.out.println(tm);        
        tm.put("dd",7); //throws NPE
        System.out.println(tm);  
}

控制台输出:

k1:xx k2:xx
k1:xz k2:xx
k1:cx k2:xx
k1:cx k2:xz
k1:ax k2:xz
k1:ax k2:xx
{ax=2, xx=5, xz=6, cx=9}
k1:dd k2:xz
Exception in thread "main" java.lang.NullPointerException
        at T1$1ValueComparator.compare(T1.java:28)
        at T1$1ValueComparator.compare(T1.java:21)
        at java.util.TreeMap.put(TreeMap.java:552)
        at T1.f16(T1.java:35)
        at T1.main(T1.java:10)

2 个答案:

答案 0 :(得分:2)

很显然,比较器中的HashMap没有"dd"的条目:仅映射了"xx""xz""cx""ax" 。这就是为什么this.map.get(k1)等于nullk1会产生"dd"的原因。

之后,您根据compareTo的结果调用get

this.map.get(k1).compareTo(this.map.get(k2));
//               ---------

会产生NPE。

要解决此问题,请添加一些替代方法来比较地图中没有键的对象-例如,通过比较键本身:

public int compare(String k1, String k2){
    System.out.printf("k1:%s k2:%s\n",k1,k2);//for debugging
    Integer v1 = this.map.get(k1);
    Integer v2 = this.map.get(k2);
    if (v1 != null && v2 == null) {
        return -1;
    }
    if (v1 == null && v2 != null) {
        return 1;
    }
    return (v1 != null && v2 != null) ? v1.compareTo(v2) : k1.compareTo(k2);
}

答案 1 :(得分:1)

问题出现在return this.map.get(k1).compareTo(this.map.get(k2));

您具有预定义的映射this.map=map;,但是如果添加元素,则会调用比较器。但是由于元素尚未在地图上,因此this.map.get(k1)返回null。这就是为什么您得到null.compareTo(...)导致异常的原因。