Вопрос-ответ

Simple way to find if two different lists contain exactly the same elements?

Простой способ определить, содержат ли два разных списка точно такие же элементы?

Какой самый простой способ определить, содержат ли два списка точно такие же элементы, в стандартных библиотеках Java?

Не должно иметь значения, являются ли два списка одним и тем же экземпляром или нет, и не должно иметь значения, отличаются ли параметры типа списков.

например

List list1
List<String> list2;
// ... construct etc

list1.add("A");
list2.add("A");
// the function, given these two lists, should return true

Вероятно, что-то бросается мне в глаза, я знаю :-)


РЕДАКТИРОВАТЬ: Чтобы уточнить, я искал ТОЧНО такие же элементы и количество элементов по порядку.

Переведено автоматически
Ответ 1

Если вам важен порядок, то просто используйте метод equals:

list1.equals(list2)

Из javadoc:


Сравнивает указанный объект с этим списком на предмет равенства. Возвращает true тогда и только тогда, когда указанный объект также является списком, оба списка имеют одинаковый размер и все соответствующие пары элементов в двух списках равны. (Два элемента e1 и e2 равны, если (e1==null ? e2==null : e1.равно(e2)).) Другими словами, два списка считаются равными, если они содержат одинаковые элементы в одинаковом порядке. Это определение гарантирует, что метод equals работает должным образом в разных реализациях интерфейса List.


Если вы хотите проверить независимо от порядка, вы могли бы скопировать все элементы в наборы и использовать equals для результирующих наборов:

public static <T> boolean listEqualsIgnoreOrder(List<T> list1, List<T> list2) {
return new HashSet<>(list1).equals(new HashSet<>(list2));
}

Ограничением этого подхода является то, что он игнорирует не только порядок, но и частоту повторяющихся элементов. Например, если list1 было ["A", "B", "A"] и list2 было ["A", "B", "B"], то Set подход будет считать их равными.

Если вам нужно быть нечувствительным к порядку, но чувствительным к частоте дубликатов, вы можете либо:

Ответ 2

Я опубликовал кучу материала в комментариях, и я думаю, что это заслуживает отдельного ответа.

Как здесь все говорят, использование equals() зависит от порядка. Если вас не волнует порядок, у вас есть 3 варианта.

Вариант 1

Используйте containsAll(). На мой взгляд, этот вариант не идеален, потому что он обеспечивает наихудшую производительность в случае O (n ^ 2).

Вариант 2

Существует два варианта этого:

2a) Если вы не заботитесь о сохранении порядка ваших списков... используйте Collections.sort() в обоих списках. Затем используйте equals(). Это O (nlogn), потому что вы выполняете две сортировки, а затем O (n) сравнение.

2b) Если вам нужно сохранить порядок списков, вы можете сначала скопировать оба списка. ЗАТЕМ вы можете использовать решение 2a для обоих скопированных списков. Однако это может быть непривлекательно, если копирование обходится очень дорого.

Это приводит к:

Вариант 3

Если ваши требования совпадают с требованиями части 2b, но копирование обходится слишком дорого. Вы можете использовать TreeSet для выполнения сортировки за вас. Поместите каждый список в отдельный набор деревьев. Он будет отсортирован в наборе, а исходные списки останутся нетронутыми. Затем выполните equals() сравнение для обоих TreeSet списков. TreeSetsS может быть создан за O (nlogn) времени, и equals() равно O (n).

Выбирайте сами :-).

РЕДАКТИРОВАТЬ: Я чуть не забыл то же самое предостережение, на которое указывает Лоуренс Гонсалвес. Реализация TreeSet устранит дубликаты. Если вас интересуют дубликаты, вам понадобится какой-нибудь отсортированный мультимножество.

Ответ 3

Если вы используете (или рады использовать) Коллекции Apache Commons, вы можете использовать CollectionUtils.isEqualCollection который "возвращает true, если данные коллекции содержат точно такие же элементы с точно такой же мощностью".

Ответ 4

Очень поздно на вечеринку, но хотелось добавить эту нулевую проверку безопасности:

Objects.equals(list1, list2)
2023-05-03 15:18 java collections