2011-12-14 31 views
1

JavaDoc的定义设定为:Java的设置得到重复条目

不包含重复元素的集合。更正式地,设置 不含对E1和e2元素,使得e1.equals(E2)

要验证相同的,我创建了一个非常简单的程序:

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; 
     } 
    } 
} 

的输出程序是

2 
true 

这意味着new Employee(10).equals(new Employee(10))返回true,而set.add(new Employee(10)); set.add(new Employee(10));将对象添加两次。

我的代码有什么问题?

+0

阅读:http://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683 – Tom 2011-12-14 12:58:28

回答

7

您的Employee类不覆盖hashCode - 它需要这样做才能使任何基于散列的收集工作。

例如:

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

您是否确实输入了答案并在21秒内格式化?我放弃了:-) – crnlx 2011-12-14 13:00:17

+0

@crnlx:我的第一个版本没有包含代码示例。 – 2011-12-14 13:01:11

+0

这使事情变得更好一点。 – crnlx 2011-12-14 13:05:29

4

你的类voilates上equals()hashCode()合资合同:

注意,一般需要覆盖hashCode方法每当equals方法被重写,从而维护hashCode方法的一般合约,其中规定相等的对象必须具有相同的散列码。

在你的情况,相等的对象不一定相等的散列码。这是令人困惑的HashSet,因为Employees与相同的id可能最终在不同的桶中,因此得到对待,如果他们不相等。

要修复,请覆盖hashCode() [例如,仅返回this.id]。

0

也许这是您的问题return this.id - o.id;而您检查return this.equals(o)返回true或false。

1

HashSet基于Hash Table数据结构,所以你必须覆盖Employee类都equalshashCode方法,以使其正常工作。

但是,您可以使用不基于散列表的其他Set实现,如TreeSet