最好的使用方法包含在Java中的ArrayList中?
我在Java中有一个ArrayList,它由一个包含两个字符串和一个整数的类型组成。 我可以成功测试此ArrayList的一个元素是否等于另一个但我发现contains方法失败。 我相信这是因为我的类型不是原始的。
现在我看到两个替代方案,我想知道哪个是最好的选择:
-
通过迭代ArrayList并测试每个元素与我正在寻找的那个元素的相等性然后打破循环来实现我自己的contains方法。
-
或者使用我的类型的HashMap作为键,使用整数作为值而不是ArrayList。 在这里,我可以使用方法containsKey来检查HashMap中是否已存在元素。
对#2进行处理的唯一警告是,在我的情况下,该值很大程度上是多余的。
最有可能的是,您只是忘记在类型中覆盖equals()
和hashCode()
。 equals()
是contains()
检查的内容。
来自Javadoc :
如果此列表包含指定的元素,则返回
true
。 更正式地,当且仅当此列表包含至少一个元素e
时才返回true
(o==null ? e==null : o.equals(e))
。
由于equals
test的默认实现用于引用相等,因此它不适合像这样的自定义数据类型。
(如果你没有覆盖equals
和hashCode
,那么在HashMap
使用你的类型作为键同样是徒劳的。)
编辑:请注意,要覆盖,您必须提供确切的签名。
class MyDataType { public boolean equals(MyDataType other) { // WRONG! ... } public boolean equals(Object other) { // Right! ... } }
这是使用@Override
注释的一个非常强大的论据; 如果用@Override
注释,第一个例子在编译时会失败。
我的猜测是你只编写了一个“强类型”equals方法而不是覆盖equals(Object)。 换句话说,如果你有:
public boolean equals(Foo f)
你需要
public boolean equals(Object o)
以及覆盖Object.equals。
这将适合“equals工作,但包含不适合,因为您的测试可能会调用强类型的等号,但ArrayList不会。
你是否覆盖了equals方法? 这是使包含正常工作所必需的。
请记住,如果不覆盖equals()方法,那么如果它们是该对象的同一实例 ,则该类型的两个对象仅相等。 ArrayList类使用此方法检查它是否包含给定对象。 此外,您需要准确匹配签名,这意味着它必须将Object作为参数而不是Foo。
此外,Object契约规定,只要覆盖equals(),就必须覆盖hashCode()。 如果你不这样做,那么HashMap或HashSet将不会将你的两个对象识别为相等,即使ArrayList这样做(HashMap检查相同的哈希值,然后对它们调用equals()以检查实际的相等性)。 因此,如果ArrayList表示两个项不相等,那么HashMap也无法做到。 这意味着您的第二个解决方案不起作用。
我的建议是检查你是否真正正确地覆盖了equals()和hashCode(),并且它们的签名与Object类中的签名匹配。
也许使用Integer类? 然后你可以做对象比较