Java. containsAll для списка массивов

279
19 сентября 2017, 06:48

Есть список, состоящий из массивов ArrayList<int[]> list1;. И второй список поменьше ArrayList<int[]> list2;.

Но чтобы сравнить, содержит ли список list1 в себе list2, такая запись почему-то не работает:

list1.containsAll(list2);

всегда выдает false, даже если заранее знать, что list1 содержит в себе list2.

В чем может быть проблема?

Answer 1

Принцип работы метода collectionA.containsAll(collectionB) состоит в следующем:

Для каждого элемента коллекции B происходит проверка на его принадлежность коллекции А.

Проверка эта заключается в следующем:

Берется один элемент B и в цикле сравнивается с каждым элементом коллекции А.

Причем сравнение идет с помощью метода equals. У вас в коллекциях содержатся массивы. У массивов метод equals не переопределен. Таким образом, будет использоваться метод equals от класса Object, который даст true только в том случае, если обе ссылки будут ссылаться на один и тот же массив в памяти.
Это все равно, что сравнивать массивы через оператор ==. В вашем случае в разных коллекциях у вас лежат разные массивы, которые никогда не дадут true при вызове метода equals

Answer 2

Подозреваю, что Вас может не устроить логика работы метода containsAll() по умолчанию.

Поэтому, предлагаю переопределить методы на те, которые Вам нужны по сути работы.

Ниже пример реализации своего сравнения ArrayList<int[]> с логикой сравнения по значениям без учета последовательности.

Кстати, сам метод containsAll() мы не переопределяем, т.к. его реализация в классе ArrayList нас устраивает. То есть метод containsAll() вызывает последовательно метод contains() для каждого элемента списка. Соответственно нам нужно переопределить только метод contains(), чтобы добиться нужной нам логики работы.

Ниже класс MyArrayList

import java.util.*;
public class MyArrayList extends ArrayList<int[]> {
    /*переопределяем метод contains(), потому что метод containsAll()
      будет вызывать метод contains()
    для каждого объекта списка ArrayList.
    */
    @Override
    public boolean contains(Object o) {
        int[] arr = (int[])o;
        //сортируем входящий массив "o" по значениям.
        Arrays.sort(arr);
        //каждый объекта нашего списка "this" сравниваем с объектом "o".
        for (int[] i : this) {
            //сортируем выбранный массив "i" по значениям.
            Arrays.sort(i);
            //Сравниваем два массива "i" и "o" по содержимому.
            if(Arrays.toString(i).compareTo(Arrays.toString(arr)) == 0) {
                return true;
            }
        }
        /*если заданный отсортированный массив "o" не был найден
          ни в одном массиве списка "this", то contains()=false
        */
        return false;
    }
}

Ниже класс Application для тестирования

import java.util.*;
public class Application {
    public static void main( String[] args ) {
        List<int[]> list1 = new MyArrayList();
        List<int[]> list2 = new MyArrayList();
        List<int[]> list3 = new MyArrayList();
        list1.add(new int[]{1, 2, 3});
        list1.add(new int[]{9, 4, 5, 6});
        list1.add(new int[]{4, 5, 6});
        list2.add(new int[]{4, 5, 6});
        list2.add(new int[]{1, 2, 3});
        list3.add(new int[]{1, 2, 3});
        list3.add(new int[]{4, 5, 55, 6});
        System.out.println("containsAll() list2 in list1 = " + list1.containsAll(list2));
        System.out.println("containsAll() list3 in list1 = " + list1.containsAll(list3));
    }
}

Результат запуска этого примера ниже:

containsAll() list2 in list1 = true
containsAll() list3 in list1 = false

Описание:

То есть все отсортированные массивы в списке list2 содержатся в отсортированных массивах списка list1, поэтому наш переопределенный метод containsAll() вернул true.

Но для list3 containsAll() вернул false, потому что не все отсортированные массивы в списке list3 содержатся в отсортированных массивах списка list1.

READ ALSO
Как открыть информацию о приложении?

Как открыть информацию о приложении?

Зная имя пакета, хочу открыть информацию о приложении в настройках(где можно остановить приложение, стереть данные, удалить и тп

246
Получить значение метода onResponse в переменную

Получить значение метода onResponse в переменную

Получить значение метода onResponse в переменную

274
AssetManager долго грузит звук

AssetManager долго грузит звук

Пытаюсь загрузить 'bangogg' из папки assets с помощью AssetManager:

278
Запуск тестов автоматически

Запуск тестов автоматически

Есть виртуалка для прокрутки тестов

235