Java Set gets duplicate entry

房东的猫 提交于 2020-01-30 09:13:33

问题


JavaDoc defines set as :

A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2)

To verify the same, i created a very simple program:

import java.util.HashSet;

public class CheckHashSet {
    public static void main(String[] args) {
        HashSet<Employee> set = new HashSet<Employee>();
        set.add(new Employee(10));
        set.add(new Employee(10));
        System.out.println(set.size());
        System.out.println(new Employee(10).equals(new Employee(10)));
    }

    private static class Employee implements Comparable<Employee> {
        private final int id;
        public Employee(int id) {
            this.id = id;
        }
        @Override
        public int compareTo(Employee o) {
            return this.id - o.id; 
        }

        @Override
        public boolean equals(Object obj) {
            if(obj instanceof Employee) {
                return compareTo((Employee)obj)==0;
            }
            return false;
        }
    }
}

The output of the program is

2
true

This means new Employee(10).equals(new Employee(10)) returns true whereas set.add(new Employee(10)); set.add(new Employee(10)); adds the object twice.

What is wrong with my code?


回答1:


Your Employee class doesn't override hashCode - it needs to do so in order for any hash-based collection to work.

For example:

@Override
public int hashCode() {
    return id;
}



回答2:


Your class voilates the joint contract on equals() and hashCode():

Note that it is generally necessary to override the hashCode method whenever equals method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

In your case, equal objects do not necessarily have equal hash codes. This is what's confusing the HashSet, since Employees with the same id could end up in different buckets and consequently get treated as if they weren't equal.

To fix, override hashCode() [for example, to simply return this.id].




回答3:


HashSet is based on Hash Table data structure so you have to override both equals and hashCode methods in class Employee to make it work properly.

However you can use another Set implementation not based on hash table such as TreeSet.




回答4:


Maybe here is your problem return this.id - o.id; rather you check return this.equals(o) that return true or false.



来源:https://stackoverflow.com/questions/8504851/java-set-gets-duplicate-entry

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!