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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13360898/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 12:26:09  来源:igfitidea点击:

Java ArrayList: contains() method returns false when arraylist contains the given object

javaarraysarraylistcontainsevaluation

提问by chribsen

I have a problem with the contains()method which returns false even though the ArrayListcontains the given Object. My code is following:

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

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);
}

I have tried Thread.sleep()between iterations, so the ArrayListwasn't load as eagerly without success.

Thread.sleep()在迭代之间尝试过,所以ArrayList没有成功地急切加载。

回答by amit

The hashCode()and equals()of arrays are a bit broken when it comes to this (it is a long different discussion why).

谈到这一点时,数组的hashCode()andequals()有点坏(这是一个很长的不同讨论为什么)。

A possible work around is to use ArrayList<ArrayList<String>>instead of ArrayList<String[]>, the equals()method for ArrayListwill be as you expect it to.

一种可能的解决方法是使用ArrayList<ArrayList<String>>代替ArrayList<String[]>equals()方法ArrayList将如您所愿。

For example:

例如:

    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));

Will yield true, as expected

会屈服true,正如预期的那样

回答by Stephen C

The problem is that equalsfor arrays is defined to be reference equality. In other words, two different arrays that contain the same elements are NOT equal ... according to the equalsmethod.

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

If you want equalsfor the "transaction" objects to be based on the equality of the strings, you need to create a custom class to hold the String[], and override the equalsmethod and the hashcodemethod.

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



By the way, array equals(Object)method is not "a bit broken". The defined semantics of equalsare simply reflecting the fact that any array object is inherently mutable.

顺便说一句,数组equals(Object)方法并没有“有点坏”。定义的语义equals只是反映了这样一个事实,即任何数组对象本质上都是可变的。

回答by Anton Bessonov

Look at getPendingTransaction and getSentTransactionRequests if it should return SAME array and not create NEW one. Second, try to debug and look for arrays object id. If this is not same, but it should be (and contains same elements), try to workaround of this (for instance create comparator or List or something like).

查看 getPendingTransaction 和 getSentTransactionRequests 是否应该返回 SAME 数组而不是创建新数组。其次,尝试调试并查找数组对象 id。如果这不一样,但它应该是(并且包含相同的元素),请尝试解决此问题(例如创建比较器或 List 或类似的东西)。

回答by luiges90

If you must use List<String[]>, possibly you are out of luck of using equals()or hashCode()it seems......

如果您必须使用List<String[]>,可能是您使用不走运,equals()或者hashCode()看起来......

Maybe you'd better create method to do compare your objects

也许你最好创建方法来比较你的对象

Something like

就像是

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;
}

To test for contains(), you would need another loop...

要测试 for contains(),您需要另一个循环...

Though you should seriously use List<List<String>>instead.

虽然你应该认真使用List<List<String>>

回答by Aleksandr M

It is because String [] transactionis object. And when you are calling containslist compares new object to some other one using equalsmethod. Imagine it like doing

这是因为String [] transaction是对象。当您调用containslist时,会使用equals方法将新对象与其他对象进行比较。想象它喜欢做

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