我有一个名为Employee的类,它有employeeName
和employeeId
作为其成员变量。我正在创建新的Employee对象,然后将其添加到TreeSet
我要对其进行排序基于employeeId
。但是如果它们具有相同的employeeName
,我认为2个Employee对象是相同的。设置不允许重复。但在这里我可以观察到一种奇怪的行为。这是我的代码。(我这里没有使用getter和setter。我直接访问成员变量。)
package secondOne;
import java.util.Set;
import java.util.TreeSet;
class Employee implements Comparable<Employee> {
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<Employee> set = new TreeSet<Employee>();
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]
为什么会这样..?
答案 0 :(得分:8)
问题在于:
((Employee)emp).employeeName== this.employeeName
您必须使用String
方法比较equals
:
((Employee)emp).employeeName.equals(this.employeeName)
请参阅How do I compare strings in Java?
此外,由于您要覆盖equals
方法,因此如果您覆盖hashCode
方法也是一件好事,如Object#equals
合同中所述:
请注意,通常需要在重写此方法时覆盖hashCode方法,以便维护hashCode方法的常规协定,该方法声明相等的对象必须具有相同的哈希代码。
其他:由于您使用的是TreeSet
,因此它将使用compareTo
方法,而不是equals
和hashCode
方法。这是因为TreeSet
实现了SortedSet
接口。请参阅SortedSet
javadoc(强调我的):
进一步提供其元素的总排序的集合。元素按使用natural ordering(即实施
Comparable<T>
)或通常在排序集创建时提供的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);
}
由于您正在比较字符串,我建议使用StringUtils
中的Apache Commons Lang类来提供帮助方法以避免null
检查和其他方法。
答案 1 :(得分:1)
你应该比较 string
而不是 == ,但使用equals()
方法,你也应该覆盖compareTo
1}}与employeeName
进行比较的方法,如果您希望以这种方式进行比较。
employeeId
和
(Employee)emp).employeeName.equals(this.employeeName)
答案 2 :(得分:0)
你比较字符串的方式是错误的。见How to compare 2 Strings in Java
(Employee)emp).employeeName== this.employeeName
应该是
(Employee)emp).employeeName.equals(this.employeeName)