好吧,我有这段代码,它应该从加权列表中获得一个随机条目。然而,当我尝试调用TreeMap.higherEntry时,即使有更高的条目可用,它也会返回null。lowerEntry有效,ceilingEntry返回相同的null。这是我的代码:
import java.util.*;
public class Randomizer<E> extends ArrayList<E> {
private Random rng;
private double defaultWeight;
public Randomizer(List<E> list) {
super(list);
rng = new Random();
defaultWeight = 1.0d;
}
/*Stripped some uninteresting constructor variations for clarity*/
public void setSeed(long seed) {
rng.setSeed(seed);
}
public E getRandom() {
TreeMap<Double,E> map = new TreeMap<>();
double total = 0;
for(E e : this) {
if(e instanceof Weighted) {
map.put(((Weighted) e).getWeight(),e);
total += ((Weighted) e).getWeight();
} else {
map.put(defaultWeight,e);
total += defaultWeight;
}
System.out.println(total);
}
double value = rng.nextDouble() * total;
System.out.println(value + ", " + map.higherKey(value));
return map.higherEntry(value).getValue();
}
}
下面是一个小数据集的控制台输出:
5.0
9.0
11.0
14.0
15.0
15.5
19.5
22.5
24.0
26.5
27.5
28.0
9.987466924354226, null
Exception in thread "main" java.lang.NullPointerException
at me.datafox.utils.Randomizer.getRandom(Randomizer.java:52)
at me.datafox.grick.SwordTest.main(SwordTest.java:39)
我做错什么了吗?数据集的格式非常奇怪,所以我将其排除在外,但很明显,从权重列表中计算总数不是我面临的问题。
javadoc说:
返回与严格大于给定键的最小键关联的键值映射,如果没有这样的键,则返回null。
您的代码会:
double value = rng.nextDouble() * total;
长话短说:唯一的解释是,没有符合这一标准的价值观。换句话说:你的逻辑从根本上被打破了。
关键是:您要乘以一个随机值。所有的赌注都在这里。有时您的代码可能会导致非null结果,有时则不然。
回答我自己的问题以关闭此线程。我的问题就在这里:
map.put(((Weighted) e).getWeight(),e);
total += ((Weighted) e).getWeight();
该地图本应是一个每个关键点都比前一个大的地图,但由于睡眠不足,我只是将原始权重添加到地图中。这里有一段固定的代码:
total += ((Weighted) e).getWeight();
map.put(total,e);
这不是错误
public static void main(String[] args) {
// creating tree map
TreeMap<Integer, String> treemap = new TreeMap<Integer, String>();
// populating tree map
treemap.put(2, "two");
treemap.put(1, "one");
treemap.put(3, "three");
treemap.put(6, "six");
treemap.put(5, "five");
// getting higher key for key 4
System.out.println("Checking values of the map");
System.out.println("Value is: "+ treemap.higherKey(3));
}
输出为5
你的代码是这样做的:
11->getHigherKey=5
9->getHigherKey=null
映射的关键应该是total
的值,而不是单个权重。
double total = 0;
for (E e : this) {
if (e instanceof Weighted) {
total += ((Weighted) e).getWeight();
} else {
total += defaultWeight;
}
map.put(total, e);
System.out.println(total);
}
double value = rng.nextDouble() * total;
double result = map.higherKey(value);
System.out.println(value + ", " + result);
return result.getValue();
例如,如果条目A、B、C的权重分别为4、2、5,则需要关键字4、6、11。这样,A覆盖0-4,B覆盖5-6,C覆盖7-11。我希望这能充分解释这一点。