为什么 .contains 在我添加副本时返回 false?

Why is .contains returning false when I add a duplicate?

我正在编写一个简单的方法来将一个对象添加到 ArrayList(如果它尚未包含)。我正在使用 .contains 方法,但出于某种原因,当我将对象的副本添加到 ArrayList 时,.contains 方法 returns false,即使我已经将相同的对象添加到 ArrayList。

这是我的 City class:

class City {
  private String name, country;
  //getters, setters, constructor
}

当我有这样的 ArrayList 时:

List<City> destinations = new ArrayList<>();

添加了一个对象

destinations.add(new City("Edmonston", "CA"));

如果我检查它是否包含这样的重复对象,它 returns false

destinations.contains(new City("Edmonston", "CA"))

完整代码如下:

主要方法

输出

城市class

旅行class

感谢您的帮助!

参见下面给出的documentation of List#contains

Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that Objects.equals(o, e).

因此,您需要覆盖 class City 中的 equals 方法。您可以按如下方式进行:

@Override
public boolean equals(Object obj) {
    City other = (City) obj;
    return Objects.equals(name, other.name) && Objects.equals(country, other.country);
}

为了 contains() 正常工作,您必须覆盖 class 中的 equals()hashCode() 方法。如果不这样做,相等的基础是引用的对象是同一个。

例如:

City c1 = new City("London", "UK") ;
City c2 = new City("London", "UK") ;
System.out.println(c1.equals(c2)) ;    // prints false
c2 = c1 ;
System.out.println(c1.equals(c2)) ;    // prints true

编辑:要覆盖 equals() 方法,请参阅 Arvind Kumar Avinash 的回答。

根据 documentationcontains 方法的工作方式是它使用 Objects.equals(o, e),其中 o 是您要检查的对象存在于ArrayListe 是数组中的每个元素。

Objects.equals(a, b) 首先检查两个参数是否为 null,然后使用 a.equals(b) 检查它们是否相同。

默认情况下,Object 中的 equals 方法只执行 a == b,如果 ab,即 ab 都引用内存中的相同位置,并不关心对象内部的变量。

City c = new City("foo", "bar");
c == new City("foo", "bar") //not true
c == c //true

由于 equals 的默认实现:

City c = new City("foo", "bar");
c.equals(new City("foo", "bar")) //not true
c.equals(c) //true

因此,您需要重写 City class 中的 equals 方法,以便检查 2 个 City 对象是否相等。 Arvind Kumar Avinash 的 提供了执行此操作的方法。

但是,每个集合都可以不同地实现 contains 和类似的方法。 HashSets 可以使用对象的哈希码来比较它们。因此,重写 class.

的 hashCode 方法也很重要
public int hashCode() {
  return Objects.hash(name, country);
}

如果您只想在列表中插入一个 City 对象,请使用 HashSet 并在您的 City class.[=12 中覆盖 Object class 中的 equals() 和 hashCode() 方法=]

 public static void main(String[] args) {

    Set<City> list = new HashSet<City>();

    list.add(new City("Edmonston", "CA"));
    list.add(new City("Edmonston", "CA"));
    list.add(new City("Edmonston", "CA"));

    System.out.println(list); //Edmonston in CA
}

还有你的城市class:

class City {

private String name, country;

 public City(String s1, String s2) {
        this.name = s1;
        this.country = s2;
    }

 @Override
public boolean equals(Object obj) {
     if (obj instanceof City)
         return this.name == ((City) obj).name & this.country == ((City) obj).country;
     else
         return false;
}



 @Override
public int hashCode() {

     return this.country.hashCode() + this.name.hashCode();

}


 @Override
    public String toString() {
        return this.name + " in " + this.country;
    }
}