我能够在TreeSet中插入重复的条目。 如何克服这一点

我有一个名为Employee的类,它有employeeNameemployeeId作为其成员变量。我正在创建新的Employee对象,然后将其添加到TreeSet ,我想根据employeeId对其进行排序。 但我认为如果两个Employee对象具有相同的employeeName则它们是相等的。 设置不允许重复。 但在这里我可以观察到一种奇怪的行为。 这是我的代码。(我这里不使用getter和setter。我直接访问成员变量。)

 package secondOne; import java.util.Set; import java.util.TreeSet; class Employee implements Comparable { String employeeName; int employeeId; public Employee(String name, int id) { this.employeeName = name; this.employeeId = id; } public int compareTo(Employee emp) { //return this.employeeName.compareTo(emp.employeeName); return (this.employeeId - emp.employeeId); } @Override public String toString() { return ("Name is: " + employeeName + " Emp id is: " + employeeId); } @Override public boolean equals(Object emp) { if (emp instanceof Employee && ((Employee) emp).employeeName == this.employeeName) { return true; } return false; } } public class TestingSetsWithComparable { /** * @param args */ public static void main(String[] args) { Employee e1 = new Employee("A", 1); Employee e2 = new Employee("A", 2); Employee e3 = new Employee("B", 3); Set set = new TreeSet(); set.add(e1); set.add(e2); set.add(e3); System.out.println(set); } } 

这里上面代码的输出是,
[Name is: A Emp id is: 1, Name is: A Emp id is: 2, Name is: B Emp id is: 3]

我的第一个问题是,在equals()方法中,如果他们有相同的employeeName,我认为2个Employee objests是相等的但是在compareTo方法中,我使用employeeId进行排序。 在这种情况下,输出显示employeeName’A’的2个条目。 当我认为2个对象具有相同的employeeName时,TreeSet如何允许重复条目。 这怎么可能..? 第二个问题是,在compareTo方法中,如果我使用employeeName进行排序,那么我不会得到同名的第二个重复条目。 第二种情况的输出是
[Name is: A Emp id is: 1, Name is: B Emp id is: 3]

为什么会这样..?

问题出在这里:

 ((Employee)emp).employeeName== this.employeeName 

您必须使用equals方法比较String

 ((Employee)emp).employeeName.equals(this.employeeName) 

请参阅如何比较Java中的字符串?

此外,由于你要覆盖equals方法,如果你也覆盖hashCode方法会很好,如Object#equals contract中所述:

请注意,通常需要在重写此方法时覆盖hashCode方法,以便维护hashCode方法的常规协定,该方法声明相等的对象必须具有相等的哈希代码。

附加:由于您使用的是TreeSet ,因此它将使用compareTo方法而不是equalshashCode方法。 这是因为TreeSet实现了SortedSet接口。 请参阅SortedSet javadoc(强调我的):

一个集合,进一步提供其元素的总排序。 元素按照其自然顺序 (即实现Comparable进行排序,或者通过在排序集创建时通常提供的Comparator进行排序。

您应该根据您的需要实现此方法:

 public int compareTo(Employee emp) { if (this.employeeName.equals(emp.employeeName)) { return 0; } //removed the comparison by subtraction since it will behave wrongly on int overflow return new Integer(this.employeeId).compareTo(emp.employeeId); } 

由于您正在比较Strings,我建议使用Apache Commons Lang中的StringUtils类,它提供帮助方法以避免null检查和其他方法。

你应该 string== 进行比较 ,但是使用equals()方法,并且你应该覆盖compareTo方法以与employeeName进行比较而不是与employeeId进行比较,如果你想以这种方式进行比较。

 (Employee)emp).employeeName.equals(this.employeeName) 

 public int compareTo(Employee emp) { return (this.employeeName-emp.employeeName); } 

你比较字符串的方式是错误的。 请参见如何比较Java中的2个字符串

 (Employee)emp).employeeName== this.employeeName 

应该

 (Employee)emp).employeeName.equals(this.employeeName)