2

I want to add an int[] to an ArrayList if it doesn't already have that int[], but for some reason, it's not working. In this case, arrlist is the ArrayList<int[]> and arr is the int[]. This code is in a for loop where arr is defined in the loop, so the values in arr changes. Even though I printed out arrlist and it had arr, the code would always say that arrlist didn't contain arr. Is there another way to check if an ArrayList contains an int[]?

int n = scan.nextInt();
ArrayList<int[]> arrlist = new ArrayList<>();
int[][] coordinates = new int[n][2];
boolean[] isTrue = new boolean[n];
for (int j = 0; j < n; j++) {
    int[] arr = new int[2];
    arr[0] = coordinates[j][0];
    arr[1] = coordinates[j][1];
    if (arrlist.contains(arr)) {
        isTrue[j] = true;
    } else {
        arrlist.add(arr);
    }
}
Julie P
  • 19
  • 4

5 Answers5

0

Consider this code:

int[] a = {1, 2};
int[] b = {1, 2};
System.out.println(a.equals(b));

Do you understand why the output is "false"?

This is the cause of your problems: two arrays with equal content are not equal according to the 'equals' method, which is explicitly invoked here, and implicitly invoked in your List<> example.

I don't see an easy fix as long as you want to use int[] arrays. You cannot define an equals method. Your best approach, I think, is to not use an array at all to contain the coordinates.

Define a class whose instances hold the required two integers:

class Point {
    int x, y;

    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public boolean equals(Object o) {
        return o instanceof Point
                && x == ((Point) o).x
                && y == ((Point) o).y;
    }
}

and then keep an ArrayList<Point>. 'contains' will now work as expected.

(You should also define hashCode in class Point, but I skipped that, it is not immediately relevant to the answer).

Community
  • 1
  • 1
a guest
  • 462
  • 3
  • 5
0

Since arrays don't compare on a per element basis you can't use contains as implemented by ArrayList. You can use the Arrays class to do it as follows. Create a helper method that takes the List and the array to check. Remember that arrays are not like sets, so equality depends on order.

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    int n = scan.nextInt();
    List<int[]> arrlist = new ArrayList<>();
    int[][] coordinates = new int[n][2];
    boolean[] isTrue = new boolean[n];
    for(int j = 0; j < n; j++) {
        int[] arr = new int[2];
        arr[0] = coordinates[j][0];
        arr[1] = coordinates[j][1];
        if (contains(arrlist,arr)) {
            isTrue[j] = true;
        } else {
            arrlist.add(arr);
        }
    }
}
private static boolean contains(List<int[]> list, int[] b) {
    for (int[] a : list) {
        if (Arrays.equals(a,b)) {
            return true;
        }
    }
    return false;
}

You could always just use a List<List<Integer>> instead of a List<int[]> since it is pretty much understood that arrays don't play well with lists.

WJS
  • 36,363
  • 4
  • 24
  • 39
0

In this case, when creating an ArrayList instance, you can override its contains method with a custom one, which compares the contents of two arrays instead of comparing the references of two array objects. This code should work on Java 7:

int[] a = {1, 2};
int[] b = {1, 2};

ArrayList<int[]> arrayList = new ArrayList<>() {
    @Override
    public boolean contains(Object that) {
        for (int i = 0; i < this.size(); i++)
            if (Arrays.equals(this.get(i), (int[]) that))
                return true;
        return false;
    }
};

arrayList.add(a);
System.out.println(arrayList.size());      // 1
System.out.println(arrayList.contains(a)); // true
System.out.println(arrayList.contains(b)); // true

You can use TreeSet instead of ArrayList with a comparator that compares the contents of two arrays. Then you can use TreeSet.contains method as follows:

TreeSet<int[]> treeSet = new TreeSet<>(Arrays::compare);

treeSet.add(new int[]{1, 2});
treeSet.add(new int[]{1, 2});
treeSet.add(new int[]{1, 3});

System.out.println(treeSet.size());                    // 2
System.out.println(treeSet.contains(new int[]{1, 2})); // true
System.out.println(treeSet.contains(new int[]{1, 3})); // true
treeSet.stream().map(Arrays::toString).forEach(System.out::println);
// [1, 2]
// [1, 3]

See also:
Check if an array exists in a HashSet<int[]>
How to make two arrays having different references?

0

You need to compare each int-value in arr against the corresponding int-values of all arrays contained in Your ArrayList arrlist.
The shortest solution should be the following lambda:

boolean contains = arrlist.stream().anyMatch( a -> arr[0] == a[0] && arr[1] == a[1] );

anyMatch stopps as soon as the first match is found

Kaplan
  • 2,572
  • 13
  • 14
-2

try this:

if(arrlist.indexOf(arr)!=-1){
   isTrue[j] = true;
}

I think there might be something funky going on with the .contains method when checking if an array object is in the list.

grant martin
  • 107
  • 1
  • 7
  • 1
    That's going to fail in the same way as the OP's code. for the same reason. If you read the documentation of **contains** and **indexOf**, they both are defined in terms of the result of **equals**. – a guest Dec 31 '20 at 03:31