Hashset允许重复?

时间:2012-12-10 15:18:08

标签: java duplicates hashset

这个问题肯定不是新问题,但我在任何地方都找不到任何有用的答案。

正如您在下面的代码中看到的那样,equals和hashcode方法被覆盖,但它仍然允许重复。 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;       
}

这个代码用于在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);

(allTask​​s是Hashset)

此代码用于功能A和B.

如果只执行功能A,它可以正常工作。如果函数B在函数A之后执行(所以上面的代码执行了两次),那么即使触发了system.err说有重复的条目,hashset也会突然接受重复项?

代码中是否存在缺陷,或者我只是遗漏了什么?

感谢您的帮助!

5 个答案:

答案 0 :(得分:8)

您正在使用2个字段来将2个对象视为“相等”,但您使用的字段数超过2个来构造哈希码。您的hashCode()方法不能比您的equals()方法更具体。作为一个好的经验法则,您的hashCode()方法不应使用equals()方法不使用的任何字段(但它可以使用更少的字段)。从技术角度来说,如果2个对象“相等”,则必须具有相同的哈希码(反之则不需要)。

答案 1 :(得分:3)

您违反了hashCode()和equals()之间的一致性要求。如果两个对象根据equals()相等,则它们也必须具有相同的散列。因为你的equals只考虑两个字段,而hashCode考虑更多,所以不满足这个要求。

答案 2 :(得分:0)

这是一个重复的问题,请参阅我的previous answer

java.util.HashSet中对象的哈希码可以更改时,会导致java.util.HashSet允许重复的行为。

当从可变字段构造对象的哈希码时,通常会发生这种情况。

答案 3 :(得分:0)

您的问题是hashCode()的实施与equals()不符。两种方法必须使用对象的相同属性。

即使hashCode()评估为equals(),您的实施中也可能true不同。在这种情况下(不同hashCode s),HashMap的对象不同。

请更正您的实施以使用相同的属性。然后错误应该消失。

答案 4 :(得分:0)

来自javadoc of Object

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. 

对于根据equals(Object)方法相同的两个对象,您的哈希码是不同的,因此其他代码HashSet将做出错误的假设,并返回错误的结果。

某些代码的编写方式依赖于其他尊重“合同”的对象。您的班级不遵守Object合同,因此集合中的任何内容都不能被认为是有效的,因为集合要求Object合同不被破坏。

相关问题