Hashmap:只能得到最后一个值

时间:2017-01-30 11:15:48

标签: java

我将一些数组放入带有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[][]>{

}

3 个答案:

答案 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对象;但是你会覆盖地图上的一个和唯一的条目。

因此,有两种方法:

  1. 如果此地图密钥始终 相同字符;好吧,那么你不需要在这里使用地图。然后你将使用List并只添加你的值!
  2. 如果您的程序实际上必须处理不同的密钥,那么您最好使用Map<Char, List<double[][]>>作为示例。
  3. 但老实说;我认为真实带走的是:退一步,然后逐步完成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);
}