0

下面的精简程序对我来说效果很好,但是当我将 hashVal 声明(粗体)移到 for 循环之外时,我的程序无法正确运行。在插入哈希映射时,为什么我需要它在 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) !**
    }
}

}

4

3 回答 3

1

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

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

于 2013-05-19T18:30:10.353 回答
0

我的意思是在 CI 中可以做到这一点:

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。

于 2013-05-20T16:35:34.103 回答
0

那是因为, (2) 在循环内被声明和初始化。因此,无论经过多少次迭代,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); 
    }
}

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

谢谢,马杜。

于 2013-05-19T19:04:18.933 回答