一个ArrayList的contains()方法如何评估对象?
说我创build一个对象,并将其添加到我的ArrayList
。 如果我然后创build具有完全相同的构造函数input的另一个对象,将contains()
方法评估这两个对象是相同的? 假设构造函数不会对input做任何有趣的事情,并且存储在两个对象中的variables是相同的。
ArrayList<Thing> basket = new ArrayList<Thing>(); Thing thing = new Thing(100); basket.add(thing); Thing another = new Thing(100); basket.contains(another); // true or false?
class Thing { public int value; public Thing (int x) { value = x; } equals (Thing x) { if (x.value == value) return true; return false; } }
这是如何实现class
有contains()
返回true
?
ArrayList implements
列表接口。
如果您查看contains
方法的List
的Javadoc,您会看到它使用equals()
方法来评估两个对象是否相同。
我认为正确的实施应该是
public class Thing { public int value; public Thing (int x) { this.value = x; } @Override public boolean equals(Object object) { boolean sameSame = false; if (object != null && object instanceof Thing) { sameSame = this.value == ((Thing) object).value; } return sameSame; } }
ArrayList使用在类中实现的equals方法(您的情况Thing类)来执行equals比较。
通常,每次重写equals()
,也应该重写hashCode()
equals()
,即使只是为了提高性能。 HashCode()
决定你的对象在进行比较时被分类到哪个“bucket”,所以hashCode
equal()
求值为true的任何两个对象都应该返回相同的hashCode
value()
。 我不记得hashCode()
的默认行为(如果它返回0,那么你的代码应该工作,但慢,但如果它返回的地址,那么你的代码将失败)。 我记得很多次,当我的代码失败,因为我忘了重写hashCode()
。 🙂
它在对象上使用equals方法。 因此,除非Thing重写equals并使用存储在对象中的variables进行比较,否则contains()
方法不会返回true。
class Thing { public int value; public Thing (int x) { value = x; } equals (Thing x) { if (x.value == value) return true; return false; } }
你必须写:
class Thing { public int value; public Thing (int x) { value = x; } public boolean equals (Object o) { Thing x = (Thing) o; if (x.value == value) return true; return false; } }
现在它的工作;)
其他海报已经解决了关于contains()如何工作的问题。
你的问题的一个同样重要的方面是如何正确实现equals()。 而这个答案真的取决于什么构成这个特定类的对象平等。 在你提供的例子中,如果你有两个不同的对象,都有x = 5,它们是相等的吗? 这实际上取决于你想要做什么。
如果您只对对象相等感兴趣,那么.equals()(由Object提供的)的默认实现仅使用标识(即this == other)。 如果这就是你想要的,那么就不要在你的类上实现equals()(让它inheritanceObject)。 你编写的代码,如果你正在寻求身份authentication,那么这个代码将永远不会出现在一个真正的类B / C中,它不会使用默认的Object.equals()实现。
如果你刚刚开始使用这个东西,我强烈推荐Joshua Bloch的Effective Java书。 这是一个很好的阅读,并涵盖了这种事情(加上如何正确实现equals(),当你试图做比基于身份比较更多)
只是想要注意的是,当value
不是基本types时,下面的实现是错误的:
public class Thing { public Object value; public Thing (Object x) { this.value = x; } @Override public boolean equals(Object object) { boolean sameSame = false; if (object != null && object instanceof Thing) { sameSame = this.value == ((Thing) object).value; } return sameSame; } }
在这种情况下,我build议如下:
public class Thing { public Object value; public Thing (Object x) { value = x; } @Override public boolean equals(Object object) { if (object != null && object instanceof Thing) { Thing thing = (Thing) object; if (value == null) { return (thing.value == null); } else { return value.equals(thing.value); } } return false; } }
来自JavaDoc的快捷方式:
boolean contains(Object o)
如果此列表包含指定的元素,则返回true。 更正式地,返回true当且仅当该列表包含至less一个元素e以使得(o == null?e == null:o.equals(e))