Java ArrayList:contains()方法在ArrayList包含给定对象时返回false

Java ArrayList:contains()方法在ArrayList包含给定对象时返回false,java,arrays,arraylist,contains,evaluation,Java,Arrays,Arraylist,Contains,Evaluation,我对contains()方法有问题,该方法返回false,即使ArrayList包含给定的对象。 我的代码如下: String [] transaction = dbConnection.getPendingTransaction(username); if (!onlineConnection.getSentTransactionRequests().contains(transaction)) { onlineConnection.getSentTransactionRequests

我对
contains()
方法有问题,该方法返回false,即使
ArrayList
包含给定的
对象。
我的代码如下:

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
并没有被如此急切地加载,但没有成功。

这是因为
String[]transaction
是对象。当您调用
contains
时,列表使用
equals
方法将新对象与其他对象进行比较。想象一下这样做

new Object().equals(new Object())

如果getPendingTransaction和getSentTransactionRequests应该返回相同的数组,而不是创建新数组,请查看它们。第二,尝试调试并查找数组对象id。如果这不相同,但应该相同(并且包含相同的元素),请尝试解决这一问题(例如创建比较器或列表或类似内容)。

数组的
hashCode()
equals()
在这方面有点混乱(这是一个漫长而不同的讨论)

一种可能的解决方法是使用
ArrayList
而不是
ArrayList
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));
ArrayList l1=新的ArrayList();
ArrayList l2=新的ArrayList();
l1.添加(“asdf”);
l2.添加(“asdf”);
ArrayList coll=新的ArrayList();
coll.add(l1);
System.out.println(coll.contains(l2));

将产生
true
,正如预期的那样

问题在于数组的
equals
定义为引用相等。换句话说,根据
equals
方法,包含相同元素的两个不同数组不相等

如果希望“transaction”对象的
equals
基于字符串的相等性,则需要创建一个自定义类来保存
字符串[]
,并重写
equals
方法和
hashcode
方法



顺便说一句,array
equals(Object)
方法并不是“有点破绽”。定义的
equals
语义只是反映了一个事实,即任何数组对象本身都是可变的。

如果您必须使用
列表
,那么您可能是运气不好,没有使用
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;
}
公共静态布尔StringArrayListQuals(列表,列表2){
if(list.size()!=list2.size())返回false;
对于(int i=0;i
要测试
contains()
,您需要另一个循环


尽管你应该认真地使用
列表

我也遇到过类似的问题。我只是写了以下代码片段:

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);
        
    }
assertContains(list,toLookFor);//调用下面的私有方法
私有void资产内容(ArrayList,字符串toLookFor){
字符串arrayListToString=rulesList.toString();
if(arrayListToString.contains(toLookFor))
System.out.println(“列表包含”+toLookFor);
其他的
System.out.println(“列表中不包含“+toLookFor”);
}

equals
hashcode
显然不是您的朋友。请,请,请,请将您的事务建模为一个适当的对象,而不是字符串数组。然后查看上面@haylem的注释。不完全正确,请注意,如果集合包含“asdf”,并且您检查了
list.contains(新字符串(“asdf”))
你会明白的。@amit谢谢你。更新了我的答案。如果这确实是问题所在,“长期不同的讨论为什么”唐罗比:老实说,我相信java 7中仍然如此的主要原因是向后兼容。我相信如果设计师可以在不改变java向后兼容准则的情况下改变它,他们会……但我不是Oracle的架构师,所以我可能错了。我也相信这是离题的。这是indeed问题,原因在相关问题中。