哈希映射对象键

时间:2012-01-09 22:51:57

标签: java hashmap

我正在使用这个类作为Hashmap的键,重写了hasCode()和equals()

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

问题在于关键值。它显示了添加的最后一个键。

4.0 5.0
4.0 5.0
4.0 5.0
4.0 5.0
4.0 5.0

我哪里出错?

4 个答案:

答案 0 :(得分:3)

您没有在double[] factors和构造函数中复制setFactors数组。这就是为什么密钥类的所有实例最终共享您在循环中修改的相同数组的原因。

您应该按如下方式更改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);
}

答案 1 :(得分: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 :(得分:2)

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

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

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

答案 3 :(得分: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;

然而,这与您的问题无关