4

この質問への答えはおそらく「不可能」ですが、とにかく質問させてください:)

たとえば、主キーを持つ非常に単純な JAVA クラスがあるとします。

class Person {
    String ssid;
    String name;
    String address;
    ...
}

ここで、人をコレクションに保存したいと考えています。つまり、equals メソッドをオーバーライドする必要があります。完全に些細な問題ではありませんが、基本的には次のようなものがあります。

@Override
public boolean equals (Object other) {
    if(other==this) return true;
    if(!other.getClass().equals(this.getClass()) return false;
    Person otherPerson = (Person)other;
    if(this.ssid.equals(otherPerson.getSsid()) return true;
}

頭からこれを入力するだけで、明らかな失敗を許してください。さて、後でアプリケーションで、ユーザー入力を通じて取得した ssid があるとしましょう。ssid を Person と比較したい場合は、次のように呼び出す必要があります。

String mySsid = getFromSomewhere();
Person myPerson = getFromSomewhere();
if(myPerson.equals(new Person(mySsid)) doSomething();

これは、ssid に基づいて Person を作成するための便利なコンストラクターを作成する必要があることを意味し (まだ作成していない場合)、これも非常に冗長です。単純に電話する方がはるかに良いでしょう

myPerson.equals(mySsid)

しかし、Person equals クラスに文字列比較を追加すると、対称プロパティが壊れてしまいます。文字列は、それ自体を Person と比較する方法の手がかりを持っていないからです。

最後に、大きな問題は、オーバーライドされた equals メソッドを使用して、対称規則を破ることなく、この種の「簡略化された」比較を有効にする方法はありますか?

これについて考えてくれてありがとう!

編集:明確にするために、これは正確な解決策を求める問題というよりも未解決の問題です。equals は、コレクションから Person を抽出したい場合に対応する必要があります。したがって、次のようなことができるはずです。

List<Person> people = ...
people.get(ssid);

主キーに基づいてクラスの等価性を定義できることは明らかで直感的に見えますが、それを行う簡単な方法は見つかりませんでした。

4

6 に答える 6

3

People をマップに保存すると、簡単に取得できます。

HashMap<String, Person> people = new HashMap<String, Person>();

Person p = constructPersonFromStuff();

people.put(p.ssid, p);

その後、その人物が存在するかどうかを確認できます。

String ssid = getFromSomewhere();

if(people.contains(ssid)){
  Person thatGuy = people.get(ssid);
}else{
  //that person DOESN'T EXIST! HE'S A FIGMENT OF YOUR IMGAINATION!
}
于 2010-05-04T16:01:36.513 に答える
2

2 つの s を比較しているのではなく、2 つPersonの s を比較していますssid。私は使うだろう:

myPerson.getSsid().equals(mySsid);
于 2010-05-04T16:01:05.933 に答える
1

Persona が文字列に等しいと言うのは意味がありません。その道をたどらないでください。

私はあなたの問題を理解していません。あなたはこのコードを持っています:

String mySsid = getFromSomewhere();
Person myPerson = getFromSomewhere();
if (myPerson.getSsid().equals(mySsid) doSomething();

それは私には悪く見えません。あなたのためにそれを行う関数を定義できると思います:

if (myPerson.ssidEquals(mySsid)) doSomething();

しかし、それは実際にはそれほど大きな改善ではありません。

どうしたの?

于 2010-05-04T16:01:54.043 に答える
1

Person は ssid と同等ではないと私は主張します。ssid の比較を使用して 2 人の Person が等しいかどうかを判断するという事実は近道です。同じ ssid を持つ 2 人の Person が同じ現実世界の人物を参照することを慣例として受け入れていますが、実際には平等になるわけではありません。真実。

おそらく、ここで本当に必要なのは、Person にブール値の「hasSsid()」メソッドを与えることです。または、電話してmyPerson.getSsid().equals(mySsid)ください。

于 2010-05-04T16:02:03.873 に答える
0

equals メソッドは、その引数がメソッドが呼び出されたクラスのインスタンスでない場合、決して true を返してはなりません。

必要に応じて、Identifiable などのインターフェイスを作成できます。

public interface Identifiable {
    public Serializable getSsid();
}

public class Person implements Identifiable { ...

次に、識別可能という観点から一般的な方法でコードを書くことができます...これは役立つかもしれません。

(本当の問題は、ユーティリティルーチンなどのために、識別可能なオブジェクトを一般的な方法で処理することだと思います)。

于 2010-05-04T16:06:36.797 に答える
0

内部でマップまたはセットを使用するカスタム データ構造を作成できます。

public interface EntityStore<T,K> {
    T get(K id);
    boolean contains(Object o);
    void put(K id, T entity);
    void remove(Object o);
    // ...
}

public class MapEntityStore<T,K> {
    private Map<K,T> entities = new HashMap<K,T>();
    public T get(K id) { return entities.get(id); }
    public boolean contains(Object o) {
        if (entities.keySet().contains(o))
            return true; // search by id
        if(entities.values().contains(o))
            return true; // search by value (this can be optimized if necessary)

        return false;
    }
    ...
}

ファクトリ メソッドを使用して EntityStore のインスタンスを作成できるため、必要に応じて最適化された/手の込んだ実装に変更できます。

于 2010-05-04T16:17:51.857 に答える