使用散列图时的原因不明原因

时间:2013-05-19 18:22:53

标签: java reference hashmap pass-by-reference

下面的精简程序对我来说效果很好但是当我在for循环外移动hashVal声明(粗体)时,我的程序无法正常运行。我在插入hashmap时需要它在for循环中的任何原因?在我快速,草率的实现工作之后,我在考虑潜在的优化时发现了这一点。然而,现在似乎快速和草率的实现工作,但不是我认为应该是优化版本。

public class X
{
   public static void foo()
   {
      Integer x1 = 0;
      HashMap<Integer, BigInteger[]> map = new HashMap<Integer, BigInteger[]>();
      int hashKey;
      /* **BigInteger[] hashVal  = new BigInteger[2];**  <-----Does not run correctly 
      if I keep the hashVal declaration here. (1) */
      for(x1 = 0; x1 <= 1048576; x1++)
      {
        BigInteger bx1 = BigInteger.valueOf(x1.intValue());
        **BigInteger[] hashVal  = new BigInteger[2];** (2)
        BigInteger res;
        /* Do lots and lots of big integer calculations and get a final result in res */
        hashKey = res.hashCode();
        /* Store res and x1 in hashmap */
        hashVal[0] = res;
        hashVal[1] = BigInteger.valueOf(x1.intValue());
        map.put(hashKey, hashVal);
      }
      Integer x0;
      for(x0 = 0; x0 <= 1048576; x0++)
      {
        /* do lots of BigInteger calculations to generate res */ 
        hashKey = res.hashCode();
        **bigNum = map.get(hashKey); <--------------Never returns a match if (1) above is enabled instead of (2) !**
    }
}

}

3 个答案:

答案 0 :(得分:1)

...因为当hashVal在循环之外时,它只会被创建一次,因此在循环内你不断地将相同的BigInteger []推送到地图中。换句话说,地图中的每个项目最终都是对同一个BigInteger []的引用。这意味着你在最后一次循环中放入BigInteger []中的任何值都将是地图中每个引用所看到的值。

当你在循环中创建一个新的BigInteger []时,每次循环hashVal都是对不同BigInteger []的引用。

答案 1 :(得分:0)

那是因为,(2)在循环内是DECLARED和INITIALIZED。因此,无论迭代次数多少,hashVal都将包含上次迭代的值。我的建议是在循环外声明hashVal并在循环中使用它。新代码如下所示。

public class X
{
   public static void foo()
   {
      Integer x1 = 0;
      HashMap<Integer, BigInteger[]> map = new HashMap<Integer, BigInteger[]>();
      int hashKey;
      BigInteger[] hashVal  = null; //changed here
      /* if I keep the hashVal declaration here. (1) */
      for(x1 = 0; x1 <= 1048576; x1++)
      {
        BigInteger bx1 = BigInteger.valueOf(x1.intValue());
        hashVal  = new BigInteger[2]; //changed here
        BigInteger res;
        /* Do lots and lots of big integer calculations and get a final result in res */
        hashKey = res.hashCode();
        /* Store res and x1 in hashmap */
        hashVal[0] = res;
        hashVal[1] = BigInteger.valueOf(x1.intValue());
        map.put(hashKey, hashVal);
      }
      Integer x0;
      for(x0 = 0; x0 <= 1048576; x0++)
      {
        /* do lots of BigInteger calculations to generate res */ 
        hashKey = res.hashCode();
       bigNum = map.get(hashKey); 
    }
}

我的更改已在代码中注释为“此处已更改”。 如果这种方法解决了您的问题,请告诉我。

谢谢, 马杜。

答案 2 :(得分:0)

  

我的意思是在C中我能做到这一点:

int a[2]; a[0] =x; a[1] = y; 
  重复

等,并正确分配值。

在Java程序中发生的同样的事情也发生在C:

int main()
{
    int numbers[2];
    int* array_of_int_pointers[2];


    for (int i=0; i<2; ++i) {
        numbers[0] = i * 10;
        numbers[1] = i * 20;

        printf("%d : %d \n", numbers[0], numbers[1]);

        array_of_int_pointers[i] = numbers;
    }

    int* first_array = array_of_int_pointers[0];
    int* second_array = array_of_int_pointers[1];

    printf("%d \n", first_array[1] );

    return 0;
}

--output:--
0 : 0 
10 : 20 
20 

您的问题询问为什么输出的最后一行不是0。