chribsen
chribsen

Reputation: 6610

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

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

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 ArrayList wasn't load as eagerly without success.

Upvotes: 4

Views: 15825

Answers (6)

Chetan Yeshi
Chetan Yeshi

Reputation: 81

I had faced the similar issue. I just wrote the below snippet:

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

Upvotes: 0

luiges90
luiges90

Reputation: 4598

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

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...

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

Upvotes: 0

Stephen C
Stephen C

Reputation: 718798

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

If you want equals for 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 equals method and the hashcode method.


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

Upvotes: 1

amit
amit

Reputation: 178451

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

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

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

Upvotes: 8

Aleksandr M
Aleksandr M

Reputation: 24396

It is because String [] transaction is object. And when you are calling contains list compares new object to some other one using equals method. Imagine it like doing

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

Upvotes: 0

Anton Bessonov
Anton Bessonov

Reputation: 9813

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

Upvotes: 1

Related Questions