简体   繁体   中英

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. The Hashcode has been generated automatically by 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 :

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)

This code is used in function A and B.

If only function A is executed, it works fine. 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?

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. your hashCode() method cannot be more specific than your equals() method. 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). to put it more technically, if 2 objects are "equal" they must have the same hashcode (the reverse is not required).

You are violating the consistency requirement between hashCode() and equals(). If two objects are equal according to equals(), they must also have the same hash. Because your equals only considers two fields, and hashCode considers more, this requirement is not met.

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.

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() . 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 . In this case (different hashCode s) the objects are different for the HashMap .

Please correct your implementations to use the same attributes. Then the error should vanish.

From the 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. 

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.

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.

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.

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