0

カスタムリストモデルで動作する JList を持つ Swing アプリケーションがあります。

モデルには、使用されるオブジェクトを格納するための ArrayList があります。状況は次のとおりです。

アプリケーションを閉じると、listmodel 内のすべてのオブジェクトがシリアル化され (デフォルトの方法では、クラスは を実装するだけですSerializable)、 を介してファイルに書き込まれますObjectOutputStream。アプリケーションが起動すると、すべてのオブジェクトがファイルから読み込まれ、ListModel再びカスタムに保存されます。

ユーザーが指定したファイルからオブジェクトもインポートできるようにする機能を追加しようとしています。別のクラスの静的メソッドは、ファイルからすべてのオブジェクトを読み取り、ArrayList. 次に、クラスで for-each ループを使用して、返されたMainFormから各オブジェクトを に格納します。ループで、特定のオブジェクトが既に含まれているかどうかを確認したいのですが、これは機能しませんArrayListListModelListModel

コードでは、次のことを行っています。

for(MyObject o: readObjects) {
    if(!myListModel.contains(o)) //listmodel just calls contains() on its ArrayList
        myListModel.addElement(o);
}

ただし、オブジェクトが既に ArrayList にある場合でも (同じファイルからオブジェクトをインポートし続けます)、それらは追加されます。

問題は、デシリアライズされたときにオブジェクトが等しくなくなったのはなぜですか。とにかくそれらを比較する方法はありますか?

4

2 に答える 2

2

これは単純なJavaオブジェクトです

public class MyObject {

private String firstname;
private String lastname;
private String email;

public String getFirstname() {
    return firstname;
}
public void setFirstname(String firstname) {
    this.firstname = firstname;
}
public String getLastname() {
    return lastname;
}
public void setLastname(String lastname) {
    this.lastname = lastname;
}
public String getEmail() {
    return email;
}
public void setEmail(String email) {
    this.email = email;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result
            + ((firstname == null) ? 0 : firstname.hashCode());
    result = prime * result
            + ((lastname == null) ? 0 : lastname.hashCode());
    return result;
}
@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    MyObject other = (MyObject) obj;
    if (firstname == null) {
        if (other.firstname != null)
            return false;
    } else if (!firstname.equals(other.firstname))
        return false;
    if (lastname == null) {
        if (other.lastname != null)
            return false;
    } else if (!lastname.equals(other.lastname))
        return false;
    return true;
}
}

(hashcode と equals auto は eclipse によって生成されます)

equals() メソッドを見ると、フィールド firstname と lastname で 2 つのオブジェクトが比較され、それらの 2 つだけが比較されていることがわかります。これは、このタイプのオブジェクトをリストに挿入すると、 と を使用できることを意味しますcontains(Object o)。オブジェクトに同じ姓と名が含まれている場合は、それが見つかります。

于 2012-04-17T15:43:18.977 に答える
1

オブジェクトの equals および hashcode メソッドをオーバーライドする必要があります (多くの例が SO で利用できます。たとえば、こちら.

これが完了すると、containsList のメソッドは期待どおりに動作します。あなたの問題はシリアライゼーションに関連していないようです。つまり、次のコードです。

List<MyObject> list = new ArrayList<MyObject>();
list.add(new MyObject());
System.out.println(list.contains(new MyObject()));

equals と hashcode をオーバーライドしない場合は false を出力しますが、オーバーライドした場合は true を出力する可能性があります (equals メソッドがこれら 2 つnew MyObject()を等しいと見なすかどうかによって異なります)。IDE には、コードを自動生成する方法が必要です。

メソッドがオブジェクトで期待どおりに機能することに満足したらcontains、シリアライズ/デシリアライズが期待どおりに機能するはずです。

于 2012-04-17T15:38:56.177 に答える