Проверьте, содержит ли один список элемент из другого
У меня есть два списка с разными объектами в них.
List<Object1> list1;
List<Object2> list2;
Я хочу проверить, существует ли элемент из списка1 в списке2 на основе определенного атрибута (Object1 и Object2 имеют (среди прочих) один взаимный атрибут (с типом Long) с именем attributeSame).
прямо сейчас, я делаю это так:
boolean found = false;
for(Object1 object1 : list1){
for(Object2 object2: list2){
if(object1.getAttributeSame() == object2.getAttributeSame()){
found = true;
//also do something
}
}
if(!found){
//do something
}
found = false;
}
Но я думаю, что есть лучший и быстрый способ сделать это:)
Может ли кто-нибудь это предложить?
Спасибо!
Ответы
Ответ 1
Если вам просто нужно проверить базовое равенство, это можно сделать с помощью базового JDK без изменения списков ввода в одной строке
!Collections.disjoint(list1, list2);
Если вам нужно проверить конкретное свойство, это сложнее. Я бы порекомендовал, по умолчанию,
list1.stream()
.map(Object1::getProperty)
.anyMatch(
list2.stream()
.map(Object2::getProperty)
.collect(toSet())
::contains)
... который собирает отдельные значения в list2
и проверяет каждое значение в list1
на наличие.
Ответ 2
Вы можете использовать Apache Commons CollectionUtils:
if(CollectionUtils.containsAny(list1,list2)) {
// do whatever you want
} else {
// do other thing
}
Это предполагает, что вы правильно перегрузили функцию equals для своих пользовательских объектов.
Ответ 3
Существует один метод из Collection
с именем retainAll
, но с некоторыми побочными эффектами для вас ссылка
Сохраняет только элементы в этом списке, которые содержатся в указанная коллекция (дополнительная операция). Другими словами, удаляет из этого списка все его элементы, которые не содержатся в указанной коллекции.
true, если этот список изменился в результате вызова
Его как
boolean b = list1.retainAll(list2);
Ответ 4
Ответ Loius правильный, я просто хочу добавить пример:
listOne.add("A");
listOne.add("B");
listOne.add("C");
listTwo.add("D");
listTwo.add("E");
listTwo.add("F");
boolean noElementsInCommon = Collections.disjoint(listOne, listTwo); // true
Ответ 5
чтобы сделать это быстрее, вы можете добавить break; таким образом, чтобы цикл остановился, если найдено установлено значение true:
boolean found = false;
for(Object1 object1 : list1){
for(Object2 object2: list2){
if(object1.getAttributeSame() == object2.getAttributeSame()){
found = true;
//also do something
break;
}
}
if(!found){
//do something
}
found = false;
}
Если у вас будут карты вместо списков с ключами attributeSame, вы можете быстрее проверить значение на одной карте, если на второй карте есть соответствующее значение.
Ответ 6
В соответствии с JavaDoc для .contains(Object obj)
:
Возвращает true, если этот список содержит указанный элемент. Больше формально, возвращает true тогда и только тогда, когда этот список содержит хотя бы один элемент e такой, что (o == null? e == null: o.equals(e)).
Итак, если вы переопределите ваш метод .equals()
для данного объекта, вы должны иметь возможность: if(list1.contains(object2))...
Если элементы будут уникальными (т.е. имеют разные атрибуты), вы можете переопределить .equals()
и .hashcode()
и сохранить все в HashSets
. Это позволит вам проверить, содержит ли один элемент в постоянное время.
Ответ 7
более быстрый способ потребует дополнительного пространства.
Например:
-
поместите все элементы в один список в HashSet (вам нужно реализовать хэш-функцию самостоятельно, используя object.getAttributeSame())
-
Перейдите в другой список и проверьте, находится ли какой-либо элемент в HashSet.
Таким образом, каждый объект посещается не чаще одного раза. и HashSet достаточно быстр, чтобы проверять или вставлять какой-либо объект в O (1).
Ответ 8
Чтобы сократить логику Нарендры, вы можете использовать это:
boolean var = lis1.stream().anyMatch(element -> list2.contains(element));
Ответ 9
Можете ли вы определить тип данных, которые вы держите? это большие данные? он сортируется?
Я думаю, что вам нужно рассмотреть различные подходы к эффективности в зависимости от данных.
Например, если ваши данные большие и несортированные, вы можете попробовать и перебрать два списка вместе по индексу и сохранить каждый атрибут списка в другом вспомогательном списке.
то вы можете перекрестно проверить текущие атрибуты в вспомогательных списках.
удача
отредактирован: и я бы не рекомендовал перегружать равных. это опасно и, вероятно, против вашего объекта.
Ответ 10
org.springframework.util.CollectionUtils
boolean containsAny(java.util.Collection<?> source, java.util.Collection<?> candidates)
Return true if any element in 'candidates' is contained in 'source'; otherwise returns false
Ответ 11
С java 8
, мы можем сделать, как показано ниже, чтобы проверить, содержит ли один список какой-либо элемент другого списка
boolean var = lis1.stream().filter(element -> list2.contains(element)).findFirst().isPresent();