0

I know that arrays are only equal to each other if they share the same reference, but also that a deepEquals can check for the actual values' equality. If i have a list of arrays, such as List<int[]> visited, how can i use something similar to deepEquals to check to see if visited contains an array that i specify?

ex:

List<int[]> visited = new ArrayList<int[]>();
int[] myArray = {2, 1};
visited.add(myArray);
int[] checkFor = {2, 1};
System.out.println(visited.contains(checkFor));

should print out true.

4 Answers4

1
private static boolean containsArray(List<int[]> list, int[] expected) {
    for(int i=0; i<list.size; i++) {
        if(deepEquals(list[i], expected) {
            return true;
        }
    }
    return false;
}
TIMBERings
  • 361
  • 1
  • 4
  • 17
  • That will return true if only the first elements match. you probably meant `if (!deepEquals(...)) { return false; }` and then `return true;` if it makes it through. Also you should test array length before you bother iterating through. – indivisible Mar 19 '14 at 03:08
  • It'll do nothing if the first element doesn't match. It loops until deepequals returns true. If it never returns true, it will exit the loop (when the list has been iterated through) then return false. This will work. Although I don't know if it should be size or length or size() or length(), I always forget. – TIMBERings Mar 19 '14 at 03:11
  • 1
    You can use `Arrays.equals()` for `deepEquals()`. – Jason C Mar 19 '14 at 03:14
0

The problem is, ArrayList#containts is using Object#equals whose default operation works like this == obj

myArray and checkFor are two different objects, they have nothing in common.

For example System.out.println(myArray == checkFor); will print out false. You can test this further by doing...

checkFor[1] = 3;
System.out.println(Arrays.toString(myArray));
System.out.println(Arrays.toString(checkFor));

Which will output:

[2, 1]
[2, 3]

So clearly, the two arrays have nothing in common and therefore aren't equal in any way...

However...

System.out.println(visited.contains(myArray));

Would output true or

int[] myArray = {2, 1};
visited.add(myArray);
int[] checkFor = myArray;
System.out.println(visited.contains(checkFor));

Would output true...

You could also use Arrays.equals(myArray, checkFor)

About the only way I know that you might be able to make this work, would be iterate the List and use Arrays.equals, for example...

public class TestArrayCollection {

    public static void main(String[] args) {
        List<int[]> visited = new ArrayList<int[]>();
        int[] myArray = {2, 1};
        visited.add(myArray);
        int[] checkFor = {2, 1};
        System.out.println(contains(visited, checkFor));
    }

    public static boolean contains(List<int[]> values, int[] match) {

        boolean contains = false;
        for (int[] element : values) {
            if (Arrays.equals(element, match)) {
                contains = true;
                break;
            }
        }
        return contains;

    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

The method you are trying to use does not produce the correct result. From List.contains():

returns true if and only if this list contains at least one element e such that (o==null ? e==null : o.equals(e))

However, int[].equals(int[]) is equivalent to ==, which isn't what you want (you want behavior like Arrays.equals()).

You have a couple of options. One option, if your code is flexible, is to create a simple class that holds an array, and implement its equals() method to test for equality (also consider overriding hashCode() and possibly implementing Comparable), e.g.:

static class Data {

    int[] array;

    @Override public boolean equals (Object other) {
        if (other == null || !(other instanceof Data))
            return false;
        else
            return Arrays.equals(array, ((Data)other).array);
    }

}

Now you can use a List<Data> and its contains() will behave appropriately.

Another option is to not use List.contains(), and instead implement your own method to check, e.g.:

static boolean containsArray (List<int[]> haystack, int[] needle) {
    for (int[] item : haystack)
        if (Arrays.equals(item, needle))
            return true; 
    return false;
}
Community
  • 1
  • 1
Jason C
  • 38,729
  • 14
  • 126
  • 182
0

This is kinda hacky, but...

only because you're dealing with int[], this will work (even if both are null)

public static void main(String[] args) {
    List<int[]> visited = new ArrayList<int[]>();
    int[] myArray = {2, 1};
    visited.add(myArray);
    int[] checkFor = {2, 1};
    System.out.println(contains(visited,checkFor));

}

private static boolean contains(List<int[]> visited, int[] checkFor) {
    for(int[] i:visited){
        if (Arrays.toString(i).equals(Arrays.toString(checkFor))){
            return true;
        }
    }
    return false;
}

not elegant, neither the most efficient way. Just a dirty hack.

Leo
  • 6,480
  • 4
  • 37
  • 52