2010-10-05 37 views
0

我期待以下內容返回true。對象列表與字符串值比較

public class HudsonJob { 

    private String name; 
    private String status; 
    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 
    public String getStatus() { 
     return status; 
    } 
    public void setStatus(String status) { 
     this.status = status; 
    } 

    public boolean equals(Object jobName) { 
     return name.toLowerCase().equals(((String)jobName).toLowerCase()); 
    } 

    public int hashCode() { 
     return name.hashCode(); 
    } 
    } 

List<HudsonJob> existingJbsLst = hudsonUtil.getAllJobs(); // returns multiple HudsonJob objects in the list. 

我期待回到真正的說法是:

boolean isExistingJob = existingJbsLst.contains("AnExistingJOB"); 總是返回false。

boolean isExistingJob = existingJbsLst.equals("AnExistingJOB");也返回false。

我應該在代碼中添加/更改以獲得預期的返回值。

+0

您應該添加null檢查,或默認初始化..所以您的代碼不會對空 – Nix 2010-10-05 13:13:46

+0

崩潰這只是一個樣本代碼,而不是完整的代碼,請採取目標 – srinannapa 2010-10-05 13:15:34

+0

你的例子是令人困惑的人。請明確說明您如何進行比較,以及您正在比較哪些類型。 – Nix 2010-10-05 13:19:42

回答

1

「contains」操作符循環遍歷集合中的所有元素,並將「want」值與「found」值進行比較。我非常小心地說。如果說 「joblist.contains(wantjob)」,這給了 - 留下了一些複雜性,相關部分:

for (HudsonJob gotjob : joblist) 
{ 
    if (wantjob.equals(gotjob)) 
    return true; 
} 

也就是說,比較 「objectIAmLookingFor.equals(objectInList)」,而不是「 objectInList.equals(objectIAmLookingFor)」。

因此,當您搜索HudsonJob的一個String列表時,它使用String.equals函數,而不是您的HudsonJob.equals函數。而String.equals對HudsonJobs一無所知,所以它立即返回false。

有兩種方法可以做你想做的。

的一種方法是改變你的HudsonJob.equals功能

public boolean equals(Object o) 
{ 
    if (o==null || !(o instanceof HudsonJob)) 
    return false; 
    return this.name.toLowerCase().equals(((HudsonJob)o).name.toLowerCase()); 
} 

然後寫

HudsonJob wantjob=new HudsonJob(); 
wantjob.setName("AnExistingJob"); 
if (existingJobList.contains(wantjob)) 
    ... whatever ... 

另一種方法是不使用「載」,而是寫自己的搜索功能,如:

public boolean jobInList(List<HudsonJob> existingJobs, String wantJob) 
{ 
    for (HudsonJob gotjob : existingJobs) 
    { 
    if (gotjob.name.toLowerCase().equals(wantJob.toLowerCase()) 
     return true; 
    } 
    return false; 
} 

(實際上,如果您需要toLowerCase,最好是將wantJob.toLow前erCase循環,但不管。)

那麼你可以說

if (jobInList(existingJobs,"AnExistingJob")) 
... do something ... 
+0

如何在返回'this.name'的HudsonJob類中添加toString()。因此,包含列表的方法查找「AnExistingJOB」.equals(hudsonjob) - > hudsonjob的字符串返回相同的,我在上面檢查,並返回true。 - – srinannapa 2010-10-06 05:06:07

+0

不幸的是,這是行不通的。 String.equals不會將字符串與其他對象的.toString進行比較。它檢查另一個對象是否是一個字符串,如果不是,則返回false。所以String.equals(x)其中x不是一個String總是返回false,句號,故事結束。 – Jay 2010-10-06 14:03:01

2
  • 你應該傳遞HudsonJob對象(不是String)到contains(..)方法。例如(如果添加了一個構造函數取名字作爲參數):

    boolean exists = existingJbsLst.contains(new HudsonJob("AnExistingJOB")); 
    
  • 讓你的IDE生成equalshashCode方法 - 將加適量null檢查,類型檢查等

  • 你正在打破equals的合同。 See here
  • 使用string.equalsIgnoreCase(..)
+0

是的「AnExistingJOB」是在我的上下文中的哈德森工作,說它不是 – srinannapa 2010-10-05 13:18:18

+0

。這是一個'字符串'。 – Bozho 2010-10-05 13:20:38

2

第二個表達式真的應該返回false,因爲你比較列表爲String。如果第一個表達式返回false,那麼顯然在列表中沒有這樣的工作。等於的實現 是正確的 (好的,你應該測試'null'和相同的類)

在寫關於缺少的測試 - 等於沒有正確實現,它不應該採取工作名稱,而是HudsonJob對象:

equals方法
public boolean equals(Object obj) { 
    if (obj == null) return false; 
    if (!(obj instanceof HudsonJob)) return false; 
    HudsonJob that = (HudsonJob) obj; 
    return this.name.equals(that.name); 
} 
+0

您不需要obj == null檢查爲空instanceof HudsonJob始終爲false。 – 2010-10-05 14:44:53

+0

如何在HudsonJob類中添加返回'this.name'的toString()。因此,包含列表的方法查找「AnExistingJOB」.equals(hudsonjob) - > hudsonjob的字符串返回相同的,我在上面檢查,並返回true。 – srinannapa 2010-10-05 19:44:09

4

你剎車the contract。例如:
它是對稱的:對於任何非空引用值x和y,當且僅當y.equals(x)返回true時,x.equals(y)才返回true。
而在你的情況下,job.equals(string)可能是正確的,但string.equals(job)將永遠是錯誤的。

什麼可能發生在你的列表是元素相比較另一種方式:

for (Object el : list) { 
    if (parameter.equals(el)) { 
     ... 
    } 
} 

這就是爲什麼它不工作的技術原因:"AnExistingJOB".equals(jobObject)永遠是假的。

編輯
順便說一句,你hashCode方法是錯也。如果在equals方法中比較忽略大小寫,則也可以在hashCode中忽略它。 Bozho的建議可能是一個很好的建議:IDE會更好地生成這些方法。此外,您可以檢查Andreas_D對有效實施的回答。