对象列表与字符串值比较

时间:2010-10-05 13:11:42

标签: java hudson

我希望以下内容能够返回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"); 总是回归假。

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

我应该在代码中添加/更改什么才能获得预期的返回值。

4 个答案:

答案 0 :(得分:4)

您为equals方法强制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 的答案,了解有效的实施方法。

答案 1 :(得分:2)

  • 您应该将HudsonJob对象(不是String)传递给contains(..)方法。例如(如果添加以名称作为参数的构造函数):

    boolean exists = existingJbsLst.contains(new HudsonJob("AnExistingJOB"));
    
  • 让您的IDE生成equalshashCode方法 - 它会添加正确的null检查,类型检查等。

  • 您违反了equals的合同。 See here
  • 使用string.equalsIgnoreCase(..)

答案 2 :(得分:2)

第二个表达式确实应该返回false,因为您将List与String进行比较。如果第一个表达式返回false,那么显然列表中没有这样的作业。 equals的实现是正确的(好的,你应该测试'null'和相同的类)

在写关于缺失的测试时 - equals没有正确实现,它不应该是一个作业名而是一个HudsonJob对象:

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

答案 3 :(得分:1)

“contains”运算符循环遍历集合中的所有memer,并将“want”值与“found”值进行比较。我非常仔细地说。如果你说“joblist.contains(wantjob)”,这给了 - 省略了一些复杂性,相关部分:

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

也就是说,比较是“objectIAmLookingFor.equals(objectInList)”,而不是“objectInList.equals(objectIAmLookingFor)”。

因此,当你在一个字符串中搜索HudsonJob的列表时,它使用的是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.toLowerCase,但无论如何。)

然后你可以说

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