Java ArrayList:当arraylist包含给定对象时,contains()方法返回false
Posted
技术标签:
【中文标题】Java ArrayList:当arraylist包含给定对象时,contains()方法返回false【英文标题】:Java ArrayList: contains() method returns false when arraylist contains the given object 【发布时间】:2012-11-01 21:23:08 【问题描述】:我遇到了 contains()
方法的问题,即使 ArrayList
包含给定的 Object
,它也会返回 false。
我的代码如下:
String [] transaction = dbConnection.getPendingTransaction(username);
if (!onlineConnection.getSentTransactionRequests().contains(transaction))
onlineConnection.getSentTransactionRequests().add(transaction);
String packet = "RTR" + "_" + transaction[0] + "_" + transaction[2] +
"_" + transaction[3] + "_" + transaction[4];
onlineConnection.send(packet);
我在两次迭代之间尝试了Thread.sleep()
,所以ArrayList
没有成功加载。
【问题讨论】:
equals
和 hashcode
显然不是你的朋友。
拜托,拜托,请将您的交易建模为适当的对象,而不是字符串数组。然后看上面@haylem 的评论。
【参考方案1】:
数组的hashCode()
和equals()
在涉及到这一点时有点坏(这是一个很长的不同讨论原因)。
一种可能的解决方法是使用ArrayList<ArrayList<String>>
而不是ArrayList<String[]>
,ArrayList
的equals()
方法将如您所愿。
例如:
ArrayList<String> l1 = new ArrayList<>();
ArrayList<String> l2 = new ArrayList<>();
l1.add("asdf");
l2.add("asdf");
ArrayList<ArrayList<String>> coll = new ArrayList<>();
coll.add(l1);
System.out.println(coll.contains(l2));
将产生true
,正如预期的那样
【讨论】:
如果这确实是问题所在,那么“长期不同的讨论为什么”将是值得的。 @DonRoby:老实说,我相信在 java 7 中仍然是这种方式的主要原因是向后兼容。我相信,如果设计人员可以在不改变 java 的向后兼容性准则的情况下改变它——他们会……但我不是 Oracle 的架构师,所以我可能是错的。我也认为这是题外话。 确实是这个问题,原因在***.com/questions/8777257/…的相关问题中。【参考方案2】:查看 getPendingTransaction 和 getSentTransactionRequests 是否应该返回相同的数组而不是创建新的数组。其次,尝试调试并查找数组对象 ID。如果这不一样,但应该是(并且包含相同的元素),请尝试解决此问题(例如创建比较器或列表或类似的东西)。
【讨论】:
【参考方案3】:问题是数组的equals
被定义为引用相等。换句话说,包含相同元素的两个不同数组不相等...根据equals
方法。
如果您希望“事务”对象的equals
基于字符串的相等性,则需要创建一个自定义类来保存String[]
,并覆盖equals
方法和@987654326 @方法。
顺便说一句,数组equals(Object)
方法不是“有点坏”。 equals
定义的语义只是反映了任何数组对象本质上都是可变的这一事实。
【讨论】:
【参考方案4】:这是因为String [] transaction
是对象。当您调用contains
时,列表使用equals
方法将新对象与其他对象进行比较。想象它喜欢做
new Object().equals(new Object())
【讨论】:
不完全正确,请注意,如果集合包含“asdf”并且您检查list.contains(new String("asdf"))
,您将得到正确的结果。
@amit 谢谢。更新了我的答案。【参考方案5】:
如果你必须使用List<String[]>
,可能你使用equals()
或hashCode()
似乎运气不好......
也许你最好创建方法来比较你的对象
类似
public static boolean stringArrayListEquals(List<String[]> list, List<String[]> list2)
if (list.size() != list2.size()) return false;
for (int i = 0; i < list.size(); ++i)
if (!Arrays.equals(list.get(i), list2.get(i)) return false;
return true;
要测试contains()
,您需要另一个循环...
虽然你应该认真地改用List<List<String>>
。
【讨论】:
【参考方案6】:我也遇到过类似的问题。我刚刚写了下面的sn-p:
assertContains(list, toLookFor); // To call the below private method
private void assertContains(ArrayList<String> list, String toLookFor)
String arrayListToString = rulesList.toString();
if (arrayListToString.contains(toLookFor))
System.out.println("The list contains "+ toLookFor);
else
System.out.println("The list does not contains "+ toLookFor);
【讨论】:
以上是关于Java ArrayList:当arraylist包含给定对象时,contains()方法返回false的主要内容,如果未能解决你的问题,请参考以下文章