Hash Card Object Key

I use this class as my key to the Hashmap with overriden hasCode () and 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; } 

I added values ​​to display with a loop

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

The problem is the key values. He displayed the last key added.

 4.0 5.0 4.0 5.0 4.0 5.0 4.0 5.0 4.0 5.0 

Where am I mistaken?

+4
source share
4 answers

If you move your array declaration into a for loop, everything will go as expected. The problem is that all of your Design instances have the same array.

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

In addition, your equals method will produce incorrect results if you have a subclass of Design . Instead of using instanceof compare the classes. Therefore change

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

to

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

However, this is not related to your problem.

+2
source

You are not copying the double[] factors array in setFactors and the constructor. This is why all instances of the key class end up using the same array that you modify in a loop.

You should modify setFactors as follows:

 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
source

The problem is that you are using the same double array for all the instances you create in Design. When you initialize the following numbers in the main loop, you change the first object again. Try the following:

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

Or, if it has performance overheads that are not acceptable in your application, just be very careful about how you use the arrays passed to setFactors and the return value of getFactors.

+3
source

You have created only one array object. Java uses reference semantics for arrays, so every time you go through a loop, you change the values ​​in the array, and the changes are reflected in all Design objects.

In other words, you have five different Design objects, and they print them all, but they all refer to the same array.

To fix this, create a new array for each iteration of the loop.

+2
source

Source: https://habr.com/ru/post/1390133/


All Articles