3

我有一个名为 Employee 的类,它有employeeNameemployeeId作为它的成员变量。我正在创建新的 Employee 对象,然后将它添加到TreeSet我想根据employeeId. 但我认为如果 2 个 Employee 对象相同,则它们是相等的employeeName。Set 不允许重复。但是在这里我可以观察到一个奇怪的行为。这是我的代码。(我在这里没有使用 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() 方法中,如果两个 Employee 对象具有相同的 employeeName,我认为它们是相等的,但在 compareTo 方法中,我使用 employeeId 进行排序。在这种情况下,输出显示employeeName 'A' 的2 个条目。当我认为两个对象具有相同的employeeName 时,TreeSet 如何允许重复条目。这怎么可能..?第二个问题是,在 compareTo 方法中,如果我使用employeeName 进行排序,那么我不会得到相同名称的第二个重复条目。第二种情况的输出是
[Name is: A Emp id is: 1, Name is: B Emp id is: 3]

为什么会这样..?

4

3 回答 3

8

问题在这里:

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

您必须使用方法比较Strings :equals

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

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

此外,由于您要覆盖equals方法,因此最好也覆盖hashCode方法,如Object#equals合同中所述:

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

附加:由于您使用的是TreeSet,它将使用compareTo方法而不是equalsandhashCode方法。这是因为TreeSet实现SortedSet了接口。参考SortedSetjavadoc(重点是我的):

进一步提供对其元素的总排序的 Set。元素使用它们的自然排序(即实现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);
}

由于您正在比较字符串,我建议使用Apache Commons LangStringUtils中的类,该类提供帮助方法以避免检查和其他方法。null

于 2013-07-12T06:07:37.700 回答
1

您不应该与==进行比较 ,而应与方法进行比较,并且如果您希望以这种方式进行比较,还应该覆盖您的方法以与not with进行比较。stringequals()compareToemployeeNameemployeeId

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

public int compareTo(Employee emp) {

  return (this.employeeName-emp.employeeName);
}
于 2013-07-12T06:13:05.020 回答
0

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

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

应该

(Employee)emp).employeeName.equals(this.employeeName)
于 2013-07-12T06:07:27.490 回答