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