3

employeeNameメンバー変数としてとを持つ Employee というクラスがあります。新しい Employee オブジェクトを作成し、に基づいて並べ替えたい場所にemployeeId追加しています。しかし、2つの Employee オブジェクトが同じである場合、それらは等しいと見なします。セットは重複を許可しません。しかし、ここで私は奇妙な振る舞いを観察できます。これが私のコードです (ここでは getter と setter を使用していません。メンバー変数に直接アクセスしています。)TreeSetemployeeIdemployeeName

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() メソッドでは、2 つの Employee オブジェクトが同じ employeeName を持つ場合に等しいと見なしますが、compareTo メソッドでは、employeeId を使用してソートしています。この場合、出力は employeeName 'A' の 2 つのエントリを示しています。2つのオブジェクトが同じemployeeNameを持っている場合に同じであると考えると、TreeSetはどのように重複エントリを許可しますか? これはどのように可能ですか..?そして2番目の質問は、compareToメソッドで、employeeNameを使用してソートすると、同じ名前の2番目の繰り返しエントリを取得できないことです。この 2 番目のケースの出力は次のとおりです。
[Name is: A Emp id is: 1, Name is: B Emp id is: 3]

どうしてこんなに..?

4

3 に答える 3

8

問題はここにあります:

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

メソッドStringを使用して s を比較する必要があります。equals

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

Java で文字列を比較するにはどうすればよいですか? を参照してください。

また、メソッドをオーバーライドしているため、契約に記載されているように、メソッドもequalsオーバーライドするとよいでしょう。hashCodeObject#equals

通常、このメソッドがオーバーライドされるときは常に、hashCode メソッドをオーバーライドする必要があることに注意してください。これは、等しいオブジェクトには等しいハッシュ コードが必要であると述べている、hashCode メソッドの一般的な契約を維持するためです。

追加:を使用しているため、およびメソッドの代わりに メソッドTreeSetを使用します。これは、インターフェイスを実装しているためです。javadocを参照してください(強調鉱山):compareToequalshashCodeTreeSetSortedSetSortedSet

要素の全体的な順序付けをさらに提供する 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 と比較する必要があります。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 に答える