Java HashMap put()奇怪的行为

时间:2013-08-21 09:19:21

标签: java hashmap put

我创建了一个包含十个字段的HashMapkey类型为Stringvalue类型为double[]

当我尝试使用put(String id, double[] newVal)更新地图时,不仅会更新与“id”键关联的值,还会更新地图中的所有值。

如何解决此问题?

      for (int j = 0;j<attrIndex.length;j ++){

        String name = train.attribute(attrIndex [j]).name();
        double g = eval.evaluateAttribute(attrIndex[j]);

        double[] newVal = {0.0, 0.0};
        double w = 1;
        if (g == 0.0) 
            w = 0.5;

        newVal = table.get(name);
        newVal[0] += g;
        newVal[1] += w;
        table.put(name, newVal);

    }

3 个答案:

答案 0 :(得分:2)

我很确定真正的错误不在你向我们展示的代码中。考虑一下:

    double[] newVal = {0.0, 0.0};
    // ...
    newVal = table.get(name);   // LOOK HERE
    newVal[0] += g;
    newVal[1] += w;
    table.put(name, newVal);

乍一看,您似乎正在创建新的double[],然后更新它。但事实上,正在更新的double[]是您从哈希表中提取的那个。 (您正在初始化的double[]被丢弃,代码中的put操作是多余的。)

那怎么会有问题?好吧,本身它不是。但它确实意味着别的东西必须使用一组初始条目填充table。并且症状表明填充表的代码看起来像这样:

   double[] val = {0.0, 0.0};
   for (String name : ...) {
       table.put(name, val);
   }

...正在创建多个共享相同double[] 的哈希表条目。很自然地,当您更新与一个名称关联的值时,实际上是在更新与所有名称关联的值。


JB Nizet(现已删除)代码解决问题的原因是它每次更新条目时都会替换double[]对象。

但解决此问题的更好方法是将初始化代码更改为:

   for (String name : ...) {
       double[] val = {0.0, 0.0};
       table.put(name, val);
   }

您可以将更新代码简化为:

for (int j = 0;j<attrIndex.length;j ++){
    String name = train.attribute(attrIndex [j]).name();
    double g = eval.evaluateAttribute(attrIndex[j]);
    double w = 1;
    if (g == 0.0) 
        w = 0.5;
    double[] val = table.get(name);
    val[0] += g;
    val[1] += w;
}

答案 1 :(得分:1)

您在循环的每次迭代中使用相同的数组。 变化

double[] newVal = {0.0, 0.0};

double[] newVal = new double[]{0.0, 0.0};

答案 2 :(得分:1)

您只创建一个double [],因此所有键/值对共享相同的值。

尝试创建新阵列:

table.put(name, new double[]{newVal[0], newVal[1]);

快速破解,肯定有更优雅的解决方案。