2012-04-17 35 views
0

我有一個JList的Swing應用程序與自定義listmodel一起工作。比較對象與反序列化對象

該模型有一個ArrayList來存儲所使用的對象。這種情況如下:

在關閉應用程序,在ListModel的所有對象序列化(默認方式,類只是實現了Serializable),並通過ObjectOutputStream寫入一個文件。當應用程序啓動時,所有對象都將從文件中讀取並再次存儲在我的自定義ListModel中。

我想添加一個功能,讓用戶也從他指定的文件中導入對象。另一個類中的靜態方法讀取文件中的所有對象,並將其返回到ArrayList中。然後,我使用MainForm類中的for-each循環來存儲ListModel中返回的ArrayList中的每個對象。在循環中,我想檢查ListModel是否已經包含某個對象,但這不起作用

在代碼中,我做了以下內容:

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

然而,即使對象是已經在ArrayList中(我一直進口來自同一個文件對象),他們仍然增加。

問題是,在反序列化時,對象是不是再平等了,是否有方法來比較它們呢?

+1

你是否重寫對象類中的equals()方法? – 2012-04-17 15:21:30

+0

不,我不知道。我是不是該? – MarioDS 2012-04-17 15:21:56

+0

@MarioDeSchaepmeester如果不覆蓋equals,contains將測試引用是否相等(Object類中equals的默認行爲)。即使不使用序列化,如果使用相同的字段創建2個對象,上面的代碼將無法達到您所期望的效果(例如:'list.add(new MyObject());'和'list.contains(new MyObject ))'會返回false)。 – assylias 2012-04-17 15:23:45

回答

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

(哈希碼和等於Eclipse生成自動)

如果你看看equals()方法,你會看到2個物體上的字段比較名字和姓氏,只有那些。這意味着如果你在列表中插入這種類型的對象,你將能夠使用contains(Object o),如果一個對象包含相同的名字和姓氏,你會發現它。

+0

謝謝,這很明顯。但是,爲每個對象生成一個隨機生成的ID爲'long'會不會更好?因爲我的對象也有名字和姓氏,但這不是因爲兩個人重合纔會有相同的第一個和最後一個名字,他們是同一個人......當對象是另一個對象但是具有相同的第一個和最後一個時它會起作用名字呢? – MarioDS 2012-04-17 16:36:31

+2

@MarioDeSchaepmeester你需要編寫一個等價方法,給你所需的行爲 - 這是一個設計決定。如果兩個不同的人可以具有相同的名稱,並且equals應該返回false,那麼您需要爲您的類添加一個唯一的標識符,equals方法將使用這個標識符來測試是否相等,而不是名稱。 – assylias 2012-04-17 16:43:33

+0

@assylias謝謝,現在已經很清楚了。 – MarioDS 2012-04-17 17:28:14

1

你需要重寫equals和你的對象的hashCode方法(很多例子可在SO,例如here

一旦你這樣做,你期望名單的contains法的行爲。 。似乎你的問題不涉及到系列化換句話說,下面的代碼:

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

將打印假的,如果你不重寫等於如果你(取決於你的equals &哈希碼,而這可能會打印真方法考慮那些2 new MyObject()等於或不等於)。您的IDE應該有一種方法可以爲您自動生成代碼。

一旦你很高興contains方法在你的對象上按預期工作,序列化/反序列化應該按預期工作。