以下代码在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)
答案 0 :(得分:2)
很显然,比较器中的HashMap
没有"dd"
的条目:仅映射了"xx"
,"xz"
,"cx"
和"ax"
。这就是为什么this.map.get(k1)
等于null
时k1
会产生"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(...)
导致异常的原因。