问题
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 wheneverequals
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