Как проще всего найти, если два списка содержат абсолютно одинаковые элементы в стандартных библиотеках Java?
Не должно иметь значения, являются ли два списка одинаковым экземпляром или нет, и не должно иметь значения, отличаются ли параметры типа списков.
например
List list1
List<String> list2;
// ... construct etc
list1.add("A");
list2.add("A");
// the function, given these two lists, should return true
Там, наверное, что-то смотрит мне в лицо, я знаю :-)
РЕДАКТИРОВАТЬ: Чтобы уточнить, я искал точно так же элементы и количество элементов, по порядку.
java
collections
Grundlefleck
источник
источник
Ответы:
Если вы заботитесь о порядке, просто используйте метод equals:
От Javadoc:
Если вы хотите проверить независимость от порядка, вы можете скопировать все элементы в Sets и использовать equals в результирующих наборах:
Ограничением этого подхода является то, что он не только игнорирует порядок, но и частоту повторяющихся элементов. Например, если
list1
было ["A", "B", "A"] иlist2
было ["A", "B", "B"], тоSet
подход будет считать их равными.Если вам нужно быть нечувствительным к порядку, но чувствительным к частоте дублирования, вы можете:
источник
a = [x, y, x]
аb = [x, y, z]
затем размеры равны иb.containsAll(a)
вернут true, ноb
содержат элемент не вa
.Я разместил кучу вещей в комментариях, думаю, это оправдывает свой ответ.
Как все говорят здесь, использование equals () зависит от порядка. Если вы не заботитесь о заказе, у вас есть 3 варианта.
Опция 1
Использование
containsAll()
. Этот вариант, на мой взгляд, не идеален, потому что он предлагает производительность в худшем случае, O (n ^ 2).Вариант 2
Есть два варианта этого:
2a) Если вы не хотите поддерживать порядок в своих списках ... используйте
Collections.sort()
оба списка. Тогда используйтеequals()
. Это O (nlogn), потому что вы делаете два вида, а затем сравниваете O (n).2b) Если вам нужно поддерживать порядок списков, вы можете сначала скопировать оба списка. Затем вы можете использовать решение 2а в обоих скопированных списках. Однако это может быть непривлекательно, если копирование очень дорого.
Это ведет к:
Вариант 3
Если ваши требования такие же, как в части 2b , но копирование слишком дорого. Вы можете использовать TreeSet, чтобы выполнить сортировку за вас. Дамп каждого списка в свой собственный TreeSet. Он будет отсортирован в наборе, а исходные списки останутся нетронутыми. Затем проведите
equals()
сравнение на обоихTreeSet
с. ВTreeSets
ы могут быть встроены в O (NlogN) времени, и представляетequals()
собой О (п).Сделайте ваш выбор :-).
РЕДАКТИРОВАТЬ: Я почти забыл ту же оговорку, на которуюуказывает Лоуренс Гонсалвес . Реализация TreeSet устранит дубликаты. Если вы заботитесь о дубликатах, вам понадобится какой-то сортированный мультимножество.
источник
a.containsAll(b) && b.containsAll(a)
Если вы используете (или с удовольствием используете) Коллекции Apache Commons, вы можете использовать CollectionUtils.isEqualCollection, который «возвращает истину, если данные Коллекции содержат абсолютно одинаковые элементы с одинаковым количеством элементов».
источник
Очень поздно на вечеринку, но хотел добавить эту нулевую безопасную проверку:
источник
Я знаю, что это старая ветка, но ни один из других ответов полностью не решил мой вариант использования (я думаю, что Guava Multiset может сделать то же самое, но здесь нет примера). Пожалуйста, извините за мое форматирование. Я все еще новичок в размещении на стеке обмена. Дополнительно сообщите мне, если есть какие-либо ошибки
Допустим, у вас есть
List<T>
a иList<T>
b, и вы хотите проверить, соответствуют ли они следующим условиям:1) O (n) ожидаемое время выполнения.
2) Равенство определяется как: Для всех элементов в a или b число раз, когда элемент встречается в a, равно числу раз, которое элемент встречается в b. Равенство элементов определяется как T.equals ()
Время выполнения - O (n), потому что мы делаем O (2 * n) вставки в hashmap и O (3 * n) выбирает hashmap. Я не полностью протестировал этот код, так что будьте осторожны :)
источник
Попробуйте эту версию, которая не требует, чтобы порядок был одинаковым, но поддерживает наличие нескольких одинаковых значений. Они совпадают, только если у каждого одинаковое количество любого значения.
источник
Метод equals в List сделает это, списки упорядочены, поэтому для того, чтобы они равнялись, два списка должны иметь одинаковые элементы в одинаковом порядке.
источник
Решение для случая, когда два списка имеют одинаковые элементы, но разный порядок:
источник
removeAll()
вместоcontainsAll()
(мое понимание таково, что если listTwo содержит дубликаты, которые содержатся только один раз в listOne, метод containsAll () неправильно сообщит списки как равные).Том отвечает отлично, я полностью согласен с его ответами!
Интересный аспект этого вопроса заключается в том, нужен ли вам сам
List
тип и его внутреннее упорядочение.Если нет, вы можете понизить
Iterable
илиCollection
получить некоторую гибкость при передаче структур данных, отсортированных по времени вставки, а не во время, когда вы хотите проверить.Если порядок не имеет значения (и у вас нет дублирующих элементов), рассмотрите возможность использования
Set
.Если порядок имеет значение, но определяется временем вставки (и у вас нет дубликатов), рассмотрите a,
LinkedHashSet
который похож на TreeSet, но упорядочен по времени вставки (дубликаты не учитываются). Это также дает вамO(1)
амортизированный доступO(log n)
.источник
Образец кода:
источник
В дополнение к ответу Лоуренса, если вы также хотите сделать его нуль-безопасным:
источник
if (list1 == null) return list2==null; if (list2 == null) return false;
Если ваш список содержит пользовательский класс MyClass, этот класс должен переопределить
equals
функцию.Примечание: если вы хотите проверить равно на java.util.Set, а не на a
java.util.List
, тогда ваш объект должен переопределитьhashCode
функцию.источник
List.equals ()
http://java.sun.com/j2se/1.5/docs/api/java/util/List.html#equals(java.lang.Object)
источник
Вы можете использовать библиотеку Apache org.apache.commons.collections: http://commons.apache.org/collections/apidocs/org/apache/commons/collections/ListUtils.html
источник
Проверьте, что оба списка не являются нулевыми. Если их размеры разные, то эти списки не равны. Создайте карты, состоящие из элементов списков в качестве ключей и их повторений в качестве значений, и сравните карты.
Предположения, если оба списка равны нулю, я считаю их равными.
Пожалуйста, обратите внимание, метод equals должен быть правильно определен для этих объектов. https://stackoverflow.com/a/24814634/4587961
источник
[x, x, y]
vs[x, y, y]
вернет true в вашей реализации.Это зависит от того, какой конкретный класс List вы используете. У абстрактного класса AbstractCollection есть метод containsAll (Collection), который принимает другую коллекцию (List - это коллекция) и:
Таким образом, если ArrayList передается внутрь, вы можете вызвать этот метод, чтобы увидеть, точно ли они совпадают.
Причина для метода containsAll () заключается в том, что он перебирает первый список в поисках совпадения во втором списке. Поэтому, если они вышли из строя, функция equals () не поднимет их.
РЕДАКТИРОВАТЬ: Я просто хочу прокомментировать здесь амортизированное время выполнения различных предлагаемых опций. Важно ли время бега? Конечно. Это единственное, что вы должны рассмотреть? Нет.
Стоимость копирования КАЖДОГО отдельного элемента из ваших списков в другие списки требует времени, а также занимает значительную часть памяти (фактически удваивая объем используемой памяти).
Таким образом, если память в вашей JVM не имеет значения (как это обычно и должно быть), вам все равно нужно учитывать время, необходимое для копирования каждого элемента из двух списков в два TreeSets. Помните, что он сортирует каждый элемент по мере его поступления.
Мой последний совет? Вам необходимо рассмотреть ваш набор данных и количество элементов в вашем наборе данных, а также размер каждого объекта в вашем наборе данных, прежде чем вы сможете принять правильное решение. Поиграйте с ними, создайте один из них и посмотрите, какой из них работает быстрее. Это хорошее упражнение.
источник