我将一些数组放入带有2个键的hashmap中。然后我试图提取这些值,但只能获取最后一个键的值。对于任何其他键我得到空指针异常:
“线程中的异常”main“java.lang.RuntimeException:No xyValues 对于键:'L','18 .2'at tmp.DataScan1.getSerie(DataScan1.java:49)at tmp.DataScan1.main(DataScan1.java:66)“
怎么了?
以下是我的工作示例:
import java.util.Arrays;
import java.util.HashMap;
public class DataScan1 extends HashMap<Character, DataSerie>{
public static double[] freqs;
public void putSerie(char lriv, double freq, double[][] xyValues){
char key1 = lriv;
long key2 = double2key(round(freq, 4));
DataSerie dataSerie = new DataSerie();
dataSerie.put(key2, xyValues);
this.put(key1, dataSerie);
}
private static long double2key(double value){
long result = (long) (value * 10000);
return result;
}
public DataScan1(){
freqs = new double[]{1, 16.9,4.0,18.2,17.4};
for (int idxfreq=0; idxfreq<freqs.length; idxfreq++){
double[][] array = new double[][]{{1, 2}, {3,4}};
putSerie('L', freqs[idxfreq], array);
}
}
public double[][] getSerie(char lriv, double freq){
char key1 = lriv;
long key2 = double2key(round(freq, 4));
double[][] xyValues = this.get(key1).get(key2);
if (xyValues == null){
throw new RuntimeException("No xyValues for the keys: '" + lriv + "', '" + freq + "'");
}
return xyValues;
}
public static void printArr(double[] arr){
System.out.println(Arrays.toString(arr));
}
public static double round(double d, int decimalPlace) {
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
}
public static void main(String[] args) {
DataScan1 myData = new DataScan1();
printArr(myData.freqs);
double[][] qq = myData.getSerie('L', 17.4); // that serie exist
double[][] qqq = myData.getSerie('L', 18.2); // but this -- isn't, error here
}
}
更新: 我忘记了DataSerie的定义:
public class DataSerie extends HashMap<Long, double[][]>{
}
答案 0 :(得分:7)
简单地说:糟糕主意。
您希望使用浮点值作为地图的关键字。这意味着将创建Double对象;并使用他们的equals()方法进行比较。
事情是:你不做那件事。当你比较两个浮点数时,你总是总是沿着(x1 - x2)&lt;小量。 (请参阅here以获取更多示例,说明为什么这是一个坏主意;然后here进行一些替代;最后here进行一些解释;尤其是回答Bernd的第2号)
换句话说:如果您真的想将这些数字用作关键字,那么请将它们表示为字符串!
除此之外:避免混合概念 - 你决定使用地图;所以不要通过使用数组来使事情变得更复杂。我宁愿定义一个&#34; Matrix&#34;用于保存当前在double [] []数组中的内容的类。
最后,针对您当前代码的真实问题:
this.put(key1, dataSerie);
在这里,您将新的dataSerie对象放入地图中。如果你仔细观察,你会发现你一直在使用相同的键(char&#39; L&#39;)。换句话说:是的,您的代码会创建一个新的dataSerie对象;但是你会覆盖地图上的一个和唯一的条目。
因此,有两种方法:
Map<Char, List<double[][]>>
作为示例。但老实说;我认为真实带走的是:退一步,然后逐步完成this,以便真正了解您打算使用的内容!
答案 1 :(得分:1)
在putSerie()
中,您始终会创建一个新的DataSerie
,并在密钥'L'
上替换旧的DataSerie
相反,如果密钥'L'
不存在,则只应在其中创建新的xyValues
。如果它已经存在,只需获取现有元素并将新元素({{1}})插入其中。
答案 2 :(得分:1)
public void putSerie(char lriv, double freq, double[][] xyValues){
char key1 = lriv;
long key2 = double2key(freq);
DataSerie dataSerie;
if (!this.containsKey(key1)) {
// Only create a new one, when necessary
dataSerie = new DataSerie();
this.put(key1, dataSerie);
} else {
dataSerie = this.get(key1);
}
dataSerie.put(key2, xyValues);
}