为什么 .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 的回答。
根据 documentation,contains
方法的工作方式是它使用 Objects.equals(o, e)
,其中 o
是您要检查的对象存在于ArrayList
和 e
是数组中的每个元素。
Objects.equals(a, b)
首先检查两个参数是否为 null
,然后使用 a.equals(b)
检查它们是否相同。
默认情况下,Object
中的 equals
方法只执行 a == b
,如果 a
与b
,即 a
和 b
都引用内存中的相同位置,并不关心对象内部的变量。
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
和类似的方法。 HashSet
s 可以使用对象的哈希码来比较它们。因此,重写 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;
}
}
我正在编写一个简单的方法来将一个对象添加到 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 的回答。
根据 documentation,contains
方法的工作方式是它使用 Objects.equals(o, e)
,其中 o
是您要检查的对象存在于ArrayList
和 e
是数组中的每个元素。
Objects.equals(a, b)
首先检查两个参数是否为 null
,然后使用 a.equals(b)
检查它们是否相同。
默认情况下,Object
中的 equals
方法只执行 a == b
,如果 a
与b
,即 a
和 b
都引用内存中的相同位置,并不关心对象内部的变量。
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
和类似的方法。 HashSet
s 可以使用对象的哈希码来比较它们。因此,重写 class.
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;
}
}