简体   繁体   English

Java HashMap put()奇怪的行为

[英]Java HashMap put() strange behaviour

I have created a HashMap with ten fields: the key type is String and the value type is an double[] . 我创建了一个具有十个字段的HashMapkey类型为Stringvalue类型为double[]

When I try to update the map using put(String id, double[] newVal) , not only the value associated to the "id" key is updated, but all values in the map. 当我尝试使用put(String id, double[] newVal)更新地图时,不仅会更新与“ id”键关联的值, put(String id, double[] newVal)更新地图中的所有值。

How to resolve this issue? 如何解决这个问题?

      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);

    }

I'm pretty sure that the real bug is not in the code you have shown us. 我很确定真正的错误不在您显示给我们的代码中。 Consider this: 考虑一下:

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

At first glance, it looks like you are creating a new double[] and then updating it. 乍一看,您似乎正在创建一个新的double[] ,然后对其进行更新。 But in fact, the double[] that is getting updated is the one that you are pulling from the hash table. 但是实际上,正在更新的double[]是从哈希表中提取的double[] (The double[] you are initializing is getting thrown away, and the put operation in your code is redundant.) (您正在初始化的double[]被丢弃,并且代码中的put操作是多余的。)

So how can this be a problem? 那么这怎么可能是个问题呢? Well, by itself it isn't. 好吧, 本身而言不是。 But it does mean that something else must be populating table with an initial set of entries. 但这确实意味着必须用初始条目集填充table 其他内容。 And the symptoms would suggest that the code that populates the table looks something like this: 这些症状表明,填充表的代码看起来像这样:

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

... which is creating multiple hash table entries that all share the same double[] . ...这将创建多个共享相同double[]哈希表条目。 So naturally, when you update the values associated with one name, you are actually updating the values associated with all of the names. 因此,自然而然地,当您更新与一个名称关联的值时,实际上是在更新与所有名称关联的值。


The reason that JB Nizet's (now deleted) code fixed the problem is that it was replacing the double[] object each time it updated an entry. JB Nizet(现已删除)的代码解决了该问题的原因是,每次更新条目时,它都替换了double[]对象。

But a better way to fix this is to change the initialization code to this: 但是解决此问题的更好方法是将初始化代码更改为此:

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

And you can simplify your update code to this: 您可以将更新代码简化为:

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;
}

You are using the same array in each iteration of the loop. 您在循环的每个迭代中使用相同的数组。 Change 更改

double[] newVal = {0.0, 0.0};

to

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

You only create a single double[], so all key/value pair share the same values. 您仅创建一个double [],因此所有键/值对共享相同的值。

Try creating a new array: 尝试创建一个新数组:

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

Just a quick hack, there are certainly more elegant solutions. 只是快速的破解,当然还有更优雅的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM