Java 向树映射添加条目时引发的NullPointerException

Java 向树映射添加条目时引发的NullPointerException,java,Java,以下代码在tm.put(“dd”,7)上抛出NPE。为什么会这样?我添加了调试,看起来我的比较函数是错误的,但我将委托给String.compare如何修复它,以便我可以将新条目添加到树状图中,并自动按值对新条目进行排序?谢谢 编辑我遇到的问题是,据我所知,树形图应该是连续排序的-您应该能够向已填充的TM添加条目,并使地图保持排序顺序。目前给出的解决方案不允许我这样做。当我添加(“cc”,7)时,我希望根据我提供给构造函数的比较器将该条目添加到“slotin”。 这应该是可能的,不是吗 EDIT

以下代码在
tm.put(“dd”,7)上抛出NPE。为什么会这样?我添加了调试,看起来我的比较函数是错误的,但我将委托给String.compare如何修复它,以便我可以将新条目添加到树状图中,并自动按值对新条目进行排序?谢谢

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

EDIT2我现在明白了这可能是不可能的,因为comparator对象用于查找值的映射是在构造时提供的。也许有办法解决这个问题,但我看不到

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);  
}

显然,比较器内部的
哈希映射
没有
的“dd”
条目:只有
的“xx”
的“xz”
的“cx”
的“ax”
被映射。这就是为什么
this.map.get(k1)
k1
等于
“dd”
时产生
null

然后调用
compare以查看
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);
}

这里出现的问题
返回this.map.get(k1.compareTo(this.map.get(k2))


您已经预定义了map
this.map=mapthis.map.get(k1)
返回
null
。这就是为什么您会得到
null.compareTo(…)
,这会导致异常。

this.map.get()在键不存在时返回null。但是如果我这样做,则树映射在添加新项后不再正确排序。@JL\u因此,当哈希映射没有提供用作排序键的数字时,就不再有“正确”的顺序。您可以修改代码,将所有“未知”排序到顶部或底部(请参见编辑),但仅此而已。是的,谢谢。这是一个有趣的问题,因为要求树映射连续按值排序比按键排序困难得多。但这种方法行不通,因为正如我在编辑中所说,用于比较中的值查找的映射在构建时是固定的。我想知道这是否可能。我很感激这一点,但我需要了解如何更改代码,以便在添加新条目后对TM进行排序。看,您添加了key-value-param,并比较值,而不是key
map.get(k1.compareTo()
。这很奇怪。因为map要求具有唯一的、可比较的键。这就是为什么您必须比较键:
k1.compareTo(k2)
。或者,如果确实需要比较值,请考虑使用不同的键。
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);
}