简体   繁体   English

Hashset允许重复?

[英]Hashset allows duplicates?

This question surely isn't a new one, but I didn't find any helpful answer anywhere. 这个问题肯定不是新问题,但我在任何地方都找不到任何有用的答案。

As you can see in the code below, the equals and hashcode methods are overriden, but it still allows duplicates. 正如您在下面的代码中看到的那样,equals和hashcode方法被覆盖,但它仍然允许重复。 The Hashcode has been generated automatically by Netbeans. Hashcode由Netbeans自动生成。

@Override
public boolean equals(Object o)
{
    TaskDetails other = (TaskDetails) o;
    if ( (id_subtask == other.id_subtask)
            && ((date.compareTo(other.date)) == 0) )
    {
        System.err.println("Duplicate Entry"+id_subtask+" + "+other.id_subtask);
        return true;
    }
    else
    {
        System.out.println("Good!" +id_subtask+" + "+other.id_subtask);
        return false;
    }

} 

@Override
public int hashCode() {
    int hash = 7;
    hash = 71 * hash + this.id_subtask;
    hash = 71 * hash + this.id_team_member;
    hash = 71 * hash + Float.floatToIntBits(this.nb_hours);
    hash = 71 * hash + (this.date != null ? this.date.hashCode() : 0);
    hash = 71 * hash + (this.comment != null ? this.comment.hashCode() : 0);
    hash = 71 * hash + (this.subtask_name != null ? this.subtask_name.hashCode() : 0);
    System.out.println("Hash : "+hash + "Subtask : " + id_subtask);
    return hash;       
}

This the code used to add an entry into the hashset : 这个代码用于在hashset中添加一个条目:

TaskDetails newTaskDetails = new TaskDetails
                                (
                                    s.getId_subtask(),
                                    mus.teamMember.getId_team_member(),
                                    f,
                                    mysqlFormat.format(caldate),
                                    c.substring(0, Math.min(c.length(), 100)),
                                    s.getName_subtask()
                                );

                            allTasks.add(newTaskDetails);

(allTasks being the Hashset) (allTask​​s是Hashset)

This code is used in function A and B. 此代码用于函数A和B.

If only function A is executed, it works fine. 如果只执行功能A,它可以正常工作。 If function B is executed after function A (so the code above is executed twice), then the hashset suddenly accepts duplicates, even though system.err is triggered saying there is a duplicate entry? 如果函数B在函数A之后执行(所以上面的代码执行两次),那么即使触发了system.err说有重复的条目,hashset突然接受重复项?

Is there a flaw in the code, or am I just missing something? 代码中是否存在缺陷,或者我只是遗漏了什么?

Thanks for the help! 谢谢您的帮助!

you are using 2 fields to consider 2 objects to be "equal", but you are using more than 2 fields to construct the hashcode. 您使用2个字段将2个对象视为“相等”,但您使用的字段数超过2个来构造哈希码。 your hashCode() method cannot be more specific than your equals() method. 你的hashCode()方法不能比你的equals()方法更具体。 as a good rule of thumb, your hashCode() method should not use any fields that your equals() method does not use (it can use fewer however). 作为一个好的经验法则,你的hashCode()方法不应该使用你的equals()方法不使用的任何字段(但是它可以使用更少的字段)。 to put it more technically, if 2 objects are "equal" they must have the same hashcode (the reverse is not required). 更具技术性,如果2个对象“相等”,它们必须具有相同的哈希码(反之则不需要)。

You are violating the consistency requirement between hashCode() and equals(). 您违反了hashCode()和equals()之间的一致性要求。 If two objects are equal according to equals(), they must also have the same hash. 如果两个对象根据equals()相等,则它们也必须具有相同的散列。 Because your equals only considers two fields, and hashCode considers more, this requirement is not met. 因为您的equals只考虑两个字段,而hashCode考虑更多,所以不满足此要求。

This is a duplicate question, see my previous answer . 这是一个重复的问题,请参阅我之前的回答

The behaviour where a java.util.HashSet allows duplicates is caused when the hash code of the objects in the java.util.HashSet can change. 其中行为java.util.HashSet允许重复时当在对象的哈希码引起java.util.HashSet可以改变。

This typically happens when an object's hash code is constructed from mutable fields. 当从可变字段构造对象的哈希码时,通常会发生这种情况。

Your problem is that the implementation of hashCode() does not match equals() . 您的问题是执行hashCode()不匹配equals() Both methods must use the same attributes of your object. 两种方法都必须使用对象的相同属性。

It's likely in your implementation that the hashCode() is different even if equals() evaluates to true . 在你的实现中,即使equals()计算结果为truehashCode()也是不同的。 In this case (different hashCode s) the objects are different for the HashMap . 在这种情况下(不同的hashCode ), HashMap的对象是不同的。

Please correct your implementations to use the same attributes. 请更正您的实现以使用相同的属性。 Then the error should vanish. 然后错误应该消失。

From the javadoc of Object 来自Objectjavadoc

If two objects are equal according to the equals(Object) method, then
calling the hashCode method on each of the two objects must produce the
same integer result. 

Your hashcodes are different for two objects that are equal according to the equals(Object) method, so the other code HashSet is going to make the wrong assumptions, and return the wrong results. 对于根据equals(Object)方法相同的两个对象,您的哈希码是不同的,因此其他代码HashSet将做出错误的假设,并返回错误的结果。

Some code is written in a manner that they depend on other objects honoring "contracts". 某些代码的编写方式依赖于其他符合“合同”的对象。 Your class doesn't honor the Object contract, so nothing in collections can be assumed to work, as collections requires that the Object contracts not be broken. 您的类不遵守Object合约,因此集合中的任何内容都不能被认为是有效的,因为集合要求Object不会被破坏。

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

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