简体   繁体   English

为什么hashTable包含冗余键

[英]Why hashTable contains redundant Keys

I have a problem with Hashtable; 我对Hashtable有问题; it contains redundant keys. 它包含冗余密钥。 I have redefined the equal and the hashcode, but the same problem. 我已经重新定义了equal和hashcode,但是同样的问题。 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: 当然,Java有一个解决方案:

result = prime * result + ((ch == null) ? 0 : Arrays.hashCode(ch)

Update 更新

And this is my test code I used for approaching the problem. 这是我用来解决该问题的测试代码。 JUnit rulez! 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. Clusterequals方法返回false,因为this.ch.equals(tbis.ch)返回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. array1.equals(array2)等于array1 == array2 ,因此,如果内容相同但实际数组实例不同,则该方法将返回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) ). 要检查数组而不是数组实例的内容,请使用Arrays.equals(array1,array2) (或者在您的情况下: Arrays.equals(this.ch,tbis.ch) )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM