2012-01-09 173 views
4

我使用这个类作为我的钥匙与哈希映射对象键

public class Design { 
private double[] factors = null; 

public double[] getFactors() { 
    return factors; 
} 

public void setFactors(double[] factors) { 
    this.factors = factors; 
} 

public Design(double[] factors) { 
    this.factors = factors; 
} 

@Override 
public int hashCode() { 
    final int prime = 31; 
    int result = 1; 
    result = prime * result + Arrays.hashCode(factors); 
    return result; 
} 

@Override 
public boolean equals(Object obj) { 
    if (this == obj) 
     return true; 
    if (obj == null) 
     return false; 
    if (!(obj instanceof Design)) 
     return false; 
    Design other = (Design) obj; 
    if (!Arrays.equals(factors, other.factors)) 
     return false; 
    return true; 
} 

我使用一个循环

public static void main(String[] args) { 

    Map<Design, Double> map = new HashMap<Design, Double>(); 

    double[] dbl = new double[2]; 

    for(int i=0; i<5; i++){ 
     for(int j=0; j<2; j++){ 
      System.out.println(j+i); 
      dbl[j] = j+i; 
     } 
     Design des = new Design(dbl); 
     map.put(des, Double.valueOf(i)); 
    } 

    for(Design d: map.keySet()){ 
     System.out.println(d.getFactors()[0] + "\t" + d.getFactors()[1]); 
    } 

    for(double d: map.values()){ 
     System.out.println(d); 
    } 
} 

增加的值映射被覆盖的hasCode()和equals()方法的HashMap问题在关键价值中。它显示添加的最后一个键。

4.0 5.0 
4.0 5.0 
4.0 5.0 
4.0 5.0 
4.0 5.0 

我在哪里出错?

+0

感谢...的解决方法是添加DBL =新的双[2];在将新值分配给数组之前... – 2012-01-09 22:59:15

回答

2

如果您要将数组的声明移至for循环,则所有操作都将按预期进行。现在的问题是你所有的Design实例都有相同的数组。

for(int i=0; i<5; i++){ 
    double[] dbl = new double[2]; 
    for(int j=0; j<2; j++){ 
     System.out.println(j+i); 
     dbl[j] = j+i; 
    } 
    Design des = new Design(dbl); 
    map.put(des, Double.valueOf(i)); 
} 

此外,您equals方法会产生不正确的结果,当你有Design一个子类。而不是使用instanceof,比较类。因此,改变

if (!(obj instanceof Design)) 
     return false; 

if (!(obj.getClass() == getClass())) 
    return false; 

然而,这无关你的问题

3

您不会复制setFactors和构造函数中的double[] factors数组。这就是为什么键类的所有实例最终会共享您在循环中修改的相同阵列。

你应该改变setFactors如下:

public void setFactors(double[] factors) { 
    this.factors = new double[factors]; 
    System.arrayCopy(factors, 0, this.factors, 0, factors.length); 
} 

public Design(double[] factors) { 
    setFactors(factors); 
} 
3

的问题是你用双打的同一阵列为您创建设计的所有实例。在初始化主循环中的下一个数字时,您将再次修改第一个对象。试试这个:

public double[] getFactors() { 
    return factors.clone(); 
} 

public void setFactors(double[] factors) { 
    this.factors = factors.clone(); 
} 

public Design(double[] factors) { 
    setFactors(factors); 
} 

或者,如果这将有一个性能开销,这不是在你的应用程序可以接受,只是必须非常小心你如何使用传递给setFactors阵列和getFactors的返回值。

2

您只制作了一个数组对象。 Java使用数组的引用语义,因此每次通过循环时,都会更改数组中的值,并且所有更改都会反映在所有对象中。

换句话说,你确实有五个不同的对象,并且它们全都打印出来,但它们都引用相同的数组。

要解决此问题,请为循环的每次迭代创建一个新数组。