繁体   English   中英

Java:为什么我的Equals方法无效?

[英]Java: Why Doesn’t My Equals Method Work?

我使用@annotation在我的Person对象中实现了equal的方法,但是,当我在主类中创建一个对象并将其与我的Person对象列表进行比较时,它不会返回正确的索引。 它说它们都是1,但是应该是1和3。

目的:

检查列表中是否存在“ Andy Bernard”,如果存在,请显示对象的索引。

import java.util.ArrayList;
import java.util.List;

public class Person {
    private String firstName;
    private String lastName;

    public Person(String firstName,String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

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

    @Override 
    public String toString() {
        return String.format(this.firstName + " " + this.lastName);  
    }

    @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;
        Person other = (Person) 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;
    }

    private static List<Person> deletePeople = new ArrayList<>();

    public static void main(String[] args) {
         addPerson("Micheal","Scott");
         addPerson("Andy","Bernard");
         addPerson("Micheal","Scott");
         addPerson("Andy","Bernard");
         display();

    }

    public static void addPerson(String firstname, String lastname) {
        Person createPerson = new Person(firstname,lastname);
        deletePeople.add(createPerson);
    }

    public static void display() {
        Person checkPerson = new Person("Andy","Bernard");

        for (Person display : deletePeople) {
            if(display.equals(checkPerson)) {
                System.out.println((display.getFirstName() + " " +
                display.getLastName() + " " + deletePeople.indexOf(display)));
            }
        }
    }
}

indexOf返回第一次出现的索引,该索引与List中的相同(根据equals方法)。 这就是为什么您看到两个都打印出来的原因。

返回指定元素在此列表中首次出现的索引;如果此列表不包含该元素,则返回-1。 更正式地,返回最低索引i,使其(o == null?get(i)== null:o.equals(get(i)));如果没有这样的索引,则返回-1。

并且您可以看到实现(对于ArrayList ,但是对于LinkedList ,这是相同的想法,只不过您要迭代其他节点):

229  public int indexOf(Object o) {
230      if (o == null) {
231          for (int i = 0; i < size; i++)
232              if (elementData[i]==null)
233                  return i;
234      } else {
235          for (int i = 0; i < size; i++)
236              if (o.equals(elementData[i]))
237                  return i;
238      }
239      return -1;
240  }

如果要打印关联的索引,可以使用在每次迭代时增加的计数器。

int index = 0;
for (Person display : deletePeople) {
    if(display.equals(checkPerson)){
        System.out.println((display.getFirstName() + " " + display.getLastName() + " " + index));
    }
    index++;
}

使用标准的for循环也是可能的。

for(int i = 0; i < deletePeople.size(); i++){
    Person display = deletePeople.get(i);
    if(display.equals(checkPerson)){
        System.out.println((display.getFirstName() + " " + display.getLastName() + " " + i));
    }
}

但是,请注意后一种实现,因为如果列表的基础表示形式为LinkedList ,则上述循环的复杂度将为O(n^2)而不是O(n)

通过调用indexOf()您将打印匹配的第一个索引,而不是当前索引。 如果您有兴趣跟踪列表中的位置,最好的方法是手动执行此操作,而不是逐个循环:

for(Object o : ls) {
  // the syntax is nice, but we don't have an easy way to
  // tell how far into the list we are
  System.out.println(o);
}

相反,请使用简单的for循环:

for(int i = 0; i < ls.size(); i++) {
  Object o = ls.get(i);
  // Now we have access to the object *and* its index
  System.out.println(i+": "+o);
}

此外,您可以在代码中进行很多简单的清理,如果您会原谅我的话,这里有一些建议:

  1. 避免在您的对象中允许null很少有null实际上有意义,并且允许它强制所有调用代码在任何地方进行null检查。

     public Person(String firstName,String lastName) { if(firstName == null || lastName == null) { throw new NullPointerException("First/Last name cannot be null"); } this.firstName = firstName; this.lastName = lastName; } 
  2. 正确使用String.format()或避免使用它。 您当前的toString()方法调用String.format(this.firstName + " " + this.lastName) ,实际上它什么也没做; 您也可能只返回没有String.format()的串联字符串。 另外,您可以正确使用格式功能,如下所示:

     String.format("%s %s", firstName, lastName); 
  3. 为您的hashCode()equals()方法利用Java 7的Objects类:

     @Override public int hashCode() { return Objects.hash(firstName, lastName); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; return Objects.equals(firstName, other.firstName) && Objects.equals(lastName, other.lastName); } 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM