ArrayList equals()在其contains方法中使用,以查看提供对象是否等于列表中的任何项目,如文档所示:
如果此列表包含指定的元素,则返回true.更正式地,当且仅当此列表包含至少一个元素e时才返回true(o == null?e == null:o.equals(e)).看到这个
我有这门课
class Foo
{
private String value;
public Foo(String value)
{
this.value = value;
}
@Override
public boolean equals(Object o)
{
return o == null ? this.value == null : o.toString().equals(this.value);
}
}
Run Code Online (Sandbox Code Playgroud)
我想用contains方法检查项目是否存在这样
List<Foo> list = new ArrayList<Foo>();
Foo item1 = new Foo("item1");
Foo item2 = new Foo("item2");
list.add(item1);
list.add(item2);
System.out.println(item1.equals("item1")); //return true
System.out.println(list.contains("item1")); //false !! why?!
Run Code Online (Sandbox Code Playgroud)
但contains方法返回false,而item1.equals("item1")返回true.
为什么contains在使用equals提供对象的方法时返回false
您的equals()实施违反了对称原则:
它是对称的:对于任何非空引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)才应返回true.
item1.equals("item1") 回报 true
而
"item1".equals(item1)回报false.
所以你不应该期望这种Collection方法contains()能够以一致的方式工作.
作为一般规则,equals()重写不应该尝试与其他类互操作,而只应与底层类的实例互操作.
在您的情况下,它仅适用于String传递给方法的参数.
你应该使它适用于Foo实例参数:
@Override
public boolean equals(Object o) {
if (!(o instanceof Foo){
return false;
}
Foo other = (Foo) o;
return Objects.equals(other.value, this.value);
}
Run Code Online (Sandbox Code Playgroud)
看看这里的文档,contains将在字符串"item1"上使用equals方法,而不在item1上使用equals方法.例如
"item1".equals(item1)
Run Code Online (Sandbox Code Playgroud)
并不是
item1.equals("item1")
Run Code Online (Sandbox Code Playgroud)
你可以list.contains(new Foo("item1"))改用.
你的问题是你的平等不对称.Foo == String并不意味着String == Foo.
如果你看一下你的实现,ArrayList.contains就会看到它的调用objectToFind.equals(objectInList),这可能与你的期望相反:
o.equals(elementData[i])
Run Code Online (Sandbox Code Playgroud)
所以在你的情况下String.equals(Foo).因为String.equals对于不是String的任何内容将返回false,ArrayList.contains返回false.
| 归档时间: |
|
| 查看次数: |
1121 次 |
| 最近记录: |