I have a problem with Hashtable; it contains redundant keys. I have redefined the equal and the hashcode, but the same problem. below is an example of my problem. I'm really need help. Thank you in advance.
public class Payoff {
public ArrayList<Cluster> coalitions = new ArrayList<Cluster>();
@Override
public boolean equals(Object t) {
// Vérification de la référence
if (t==this)
return true;
//Vérification du type du paramètre puis de ses attributs.
if (t instanceof Payoff) {
Payoff tbis = (Payoff)t;
return this.coalitions.equals(tbis.coalitions);
} else
return false;
}
@Override
public int hashCode() {
return this.coalitions.hashCode();
}
}
public class Cluster implements Cloneable {
public ArrayList<Integer> dataArray = new ArrayList<Integer>();
public double[] ch;
public double coalitionPayoff;
public Cluster() {
}
public Cluster(Cluster obj) {
this.ch = obj.ch;
this.dataArray = (ArrayList<Integer>)obj.dataArray.clone();
this.coalitionPayoff = obj.coalitionPayoff;
}
public boolean equals(Object T)
{ // Vérification de la référence
if (T==this)
return true;
//Vérification du type du paramètre puis de ses attributs.
if (T instanceof Cluster)
{
Cluster Tbis = (Cluster) T;
return this.DataArray.equals(Tbis. DataArray) && Arrays.equals(this.Ch,Tbis.Ch)
&& (this.CoalitionPayoff ==Tbis.CoalitionPayoff);
} else
return false;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dataArray == null) ? 0 : dataArray.hashCode());
//result = prime * result + (int) (coalitionPayoff ^ (coalitionPayoff >>> 32));
result = prime * result + ((ch == null) ? 0 : ch.hashCode());
return result;
}
public Cluster clone() {
return new Cluster ();
}
}
public static void main(String[] args) throws Exception {
Hashtable<Payoff,Double> HashTab = new Hashtable<Payoff,Double>();
Payoff Pay1 = new Payoff();
Cluster Cluster1 = new Cluster();
Cluster1.DataArray.addAll(java.util.Arrays.asList(1,2,3));
double[] ary = {1.5};
Cluster1.Ch= ary;
Pay1.Coalitions.add(Cluster1);
Cluster1 = new Cluster();
Cluster1.DataArray.addAll(java.util.Arrays.asList(4,5));
double[] ary2 = {4.5};
Cluster1.Ch= ary2;
Pay1.Coalitions.add(Cluster1);
HashTab.put(Pay1, 0.5);
Payoff Pay2 = new Payoff();
Cluster Cluster2 = new Cluster();
Cluster2.DataArray.addAll(java.util.Arrays.asList(1,2,3));
double[] ary3 = {1.5}; Cluster2.Ch= ary3;
Pay2.Coalitions.add(Cluster2);
Cluster2 = new Cluster();
Cluster2.DataArray.addAll(java.util.Arrays.asList(4,5));
double[] ary4 = {4.5};
Cluster2.Ch= ary4;
Pay2.Coalitions.add(Cluster2);
if(!HashTab.containsKey(Pay2)){
HashTab.put(Pay2, 0.5);
}
System.out.println(HashTab.size());
}
This line is the problem:
result = prime * result + ((ch == null) ? 0 : ch.hashCode()
This is the hashcode of the array not the hashcode of the content of the array, hence when you say:
double[] ary = {1.5};
double[] ary3 = {1.5};
it is different besides having the same data in it. Make sure you use the content, not the object reference as hashcode.
And of course Java has a solution for that:
result = prime * result + ((ch == null) ? 0 : Arrays.hashCode(ch)
And this is my test code I used for approaching the problem. JUnit rulez!
public class TestHashTable
{
@Test
public void testEmpty()
{
final Cluster c1 = new Cluster();
final Cluster c2 = new Cluster();
Assert.assertEquals(c1, c2);
Assert.assertEquals(c1.hashCode(), c2.hashCode());
}
@Test
public void testSame()
{
final Payoff pay1 = new Payoff();
final Cluster cluster1 = new Cluster();
cluster1.dataArray.addAll(java.util.Arrays.asList(1,2,3));
pay1.coalitions.add(cluster1);
Assert.assertEquals(pay1, pay1);
Assert.assertEquals(pay1.hashCode(), pay1.hashCode());
}
@Test
public void testEquals()
{
final Payoff pay1 = new Payoff();
final Cluster cluster1 = new Cluster();
cluster1.dataArray.addAll(java.util.Arrays.asList(1,2,3));
pay1.coalitions.add(cluster1);
final Payoff pay2 = new Payoff();
final Cluster cluster2 = new Cluster();
cluster2.dataArray.addAll(java.util.Arrays.asList(1,2,3));
pay2.coalitions.add(cluster2);
Assert.assertEquals(cluster1, cluster2);
Assert.assertEquals(pay1, pay2);
Assert.assertEquals(cluster1.hashCode(), cluster2.hashCode());
Assert.assertEquals(pay1.hashCode(), pay1.hashCode());
}
@Test
public void testUseInMap()
{
final Payoff pay1 = new Payoff();
final Cluster cluster1 = new Cluster();
cluster1.dataArray.addAll(java.util.Arrays.asList(1,2,3));
final double[] a1 = {1.5};
cluster1.ch = a1;
pay1.coalitions.add(cluster1);
final Payoff pay2 = new Payoff();
final Cluster cluster2 = new Cluster();
final double[] a2 = {1.5};
cluster2.ch = a2;
cluster2.dataArray.addAll(java.util.Arrays.asList(1,2,3));
pay2.coalitions.add(cluster2);
final Map<Payoff, Double> map = new HashMap<Payoff, Double>();
map.put(pay1, 1.0);
map.put(pay2, 2.0);
Assert.assertEquals(1, map.size());
Assert.assertTrue(2.0 == map.get(pay1));
}
}
The equals
method of Cluster
returns false because this.ch.equals(tbis.ch)
returns false.
array1.equals(array2)
is equal to array1 == array2
, so if the content is the same but the actual array instance is different, the method will return false. To check the content of the arrays rather than the array instance, use Arrays.equals(array1,array2)
(or in your case: Arrays.equals(this.ch,tbis.ch)
).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.