Java 我能够在树集合中插入重复的条目。如何克服这个问题

Java 我能够在树集合中插入重复的条目。如何克服这个问题,java,treeset,Java,Treeset,我有一个名为Employee的类,它将employeeName和employeeId作为其成员变量。我正在创建新的Employee对象,然后将其添加到TreeSet中,在那里我希望根据employeeId对其进行排序。但是,如果有相同的雇员名称< /代码>,我认为2个雇员对象是相等的。集合不允许重复。但在这里我可以观察到一种奇怪的行为。这是我的代码。(我在这里不使用getter和setter。我直接访问成员变量。) packagesecondone; 导入java.util.Set; 导入jav

我有一个名为Employee的类,它将
employeeName
employeeId
作为其成员变量。我正在创建新的Employee对象,然后将其添加到
TreeSet
中,在那里我希望根据
employeeId
对其进行排序。但是,如果有相同的<代码>雇员名称< /代码>,我认为2个雇员对象是相等的。集合不允许重复。但在这里我可以观察到一种奇怪的行为。这是我的代码。(我在这里不使用getter和setter。我直接访问成员变量。)

packagesecondone;
导入java.util.Set;
导入java.util.TreeSet;
类Employee实现了可比较的{
字符串employeeName;
国际雇员ID;
公共雇员(字符串名称,整数id){
this.employeeName=名称;
this.employeeId=id;
}
公共内部比较(员工环境管理计划){
//将此.employeeName.compareTo(emp.employeeName)返回给emp.employeeName;
返回(this.employeeId-emp.employeeId);
}
@凌驾
公共字符串toString(){
返回(“名称为:“+employeeName+”Emp id为:“+employeeId”);
}
@凌驾
公共布尔等于(对象emp){
if(emp instanceof Employee&((Employee)emp).employeeName==此.employeeName){
返回true;
}
返回false;
}
}
具有可比性的公共类测试集{
/**
*@param args
*/
公共静态void main(字符串[]args){
员工e1=新员工(“A”,1);
雇员e2=新雇员(“A”,2);
员工e3=新员工(“B”,3);
Set=新树集();
增加(e1);
添加(e2);
集合。添加(e3);
系统输出打印项次(套);
}
}
此处,上述代码的输出为,
[名称是:Emp id是:1,名称是:Emp id是:2,名称是:B Emp id是:3]

我的第一个问题是,在等式()方法中,我认为如果有相同的雇员名,2个雇员对象是相等的,但是在CuffReto方法中,我使用EnguleID进行排序。在本例中,输出显示employeeName“A”的两个条目。当我考虑2个对象是相同的,如果他们有相同的雇员名称时,TeSESET允许重复的条目。这怎么可能。。? 第二个问题是,在compareTo方法中,如果我使用employeeName进行排序,那么我不会得到相同名称的第二个重复条目。第二种情况下的输出为

[名称为:A Emp id为:1,名称为:B Emp id为:3]


为什么会这样?

比较字符串的方式是错误的。看

应该是

(Employee)emp).employeeName.equals(this.employeeName)
问题在于:

((Employee)emp).employeeName== this.employeeName
必须使用
equals
方法比较
String
s:

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

另外,由于您正在重写
equals
方法,所以最好也重写
hashCode
方法,如合同中所述:

请注意,每当重写hashCode方法时,通常都需要重写该方法,以便维护hashCode方法的一般约定,即相等的对象必须具有相等的哈希代码

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

进一步对其元素提供总排序的集合。元素使用它们的(即实现
可比的
)或通常在排序集创建时提供的
比较器进行排序

您应根据自己的需要在中实施此方法:

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

由于您正在比较字符串,我建议使用提供帮助程序方法的类来避免
null
检查和其他检查。

您应该比较
string
而不是使用==,而是使用
equals()
方法,此外,如果您希望这样做,您还应该重写
compareTo
方法以与
employeeName
进行比较,而不是与
employeeId
进行比较

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


取消对此的注释//返回this.employeeName.compareTo(emp.employeeName);,这不起作用吗?@Piyuesh:是的,它起作用了。如果您使用Eclipse,只需生成equals()和hashCode()。当然,在其他好的IDE中也是如此;-)即使使用equals()方法,我仍然得到相同的输出。我仍在获取重复条目。我在代码中将==改为equals。即使使用equals方法,我仍然得到相同的输出。我仍在获取重复条目。我在代码中将==改为等于。
TreeSet
不使用
equals
方法进行元素比较。@luigimendoza它使用了。。这就是TreeSet.add文档所告诉我们的?请参考我的答案,了解关于这个主题的更多细节,我不想重复:)@sanbhat:Luiggi Mendoza是对的。它根本不使用equals方法进行比较。连我现在都查过了。删除equals方法,并在Luiggi的答案描述中插入compareTo方法。我编辑了使用equals方法比较两个字符串而不是==的代码。但我还是得到了同样的结果。在compareTo方法中,我不想根据两名员工的姓名对他们进行比较,我的要求是根据他们的Id对员工进行排序。因此,我使用他们的Id在compareTo方法中进行排序。在排序之前,当我说两个对象的名称匹配时,为什么Set允许重复条目?为了满足我的请求,我应该使用哪种结构?@Prasad Response在刷新我的脸并重新思考问题后更新。请注意
compareTo
方法的新实现。@Prasad这意味着您首先比较传入的
Employee
对象是否与当前的
Employee同名
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);
}
(Employee)emp).employeeName.equals(this.employeeName)
public int compareTo(Employee emp) {

  return (this.employeeName-emp.employeeName);
}