Проверьте, содержит ли один список элемент из другого
у меня есть два списка с разными предметами в них.
List<Object1> list1;
List<Object2> list2;
Я хочу проверить, существует ли элемент из list1 в list2, основанный на определенном атрибуте (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;
}
но я думаю, что есть лучший и более быстрый способ сделать это :) Может кто-нибудь предложить это?
спасибо!
9 ответов:
Это можно сделать с помощью базового JDK без изменения входных списков в одной строке
!Collections.disjoint(list1, list2);
можно использовать Apache Commons CollectionUtils:
if(CollectionUtils.containsAny(list1,list2)) { // do whatever you want } else { // do other thing }
это предполагает, что вы правильно перегрузили функциональность equals для своих пользовательских объектов.
здесь один способ на
Collection
имениretainAll
но побочные эффекты для вас ссылкасохраняет только те элементы в этом списке, которые содержатся в указанная коллекция (необязательная операция). Другими словами, удаляет из этого списка все его элементы, которые не содержатся в указанная коллекция.
true, если этот список изменяется в результате звоните
как
boolean b = list1.retainAll(list2);
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
быстрый способ потребует дополнительного пространства .
например:
поместите все элементы в один список в хэш-набор (Вы должны реализовать хэш-функцию самостоятельно, чтобы использовать объект.getAttributeSame ())
перейдите в другой список и проверьте, есть ли какой-либо элемент в хэш-наборе.
таким образом, каждый объект посещается не более одного раза. и HashSet достаточно быстро, чтобы проверить или вставить любой объект в O (1).
в соответствии с документацией к
.contains(Object obj)
:возвращает true, если этот список содержит указанный элемент. Больше формально возвращает true тогда и только тогда, когда этот список содержит хотя бы один элемент e такой, что (o= = null ? e= = null: o. равно(e)).
так что если вы переопределите ваш
.equals()
метод для данного объекта, вы должны быть в состоянии сделать:if(list1.contains(object2))...
если элементы будут уникальными (т. е. имеют разные атрибуты) вы может переопределить
.equals()
и.hashcode()
и хранить все вHashSets
. Это позволит вам проверить, если один содержит другой элемент в постоянное время.
чтобы сделать это быстрее, вы можете добавить разрыв; таким образом, цикл остановится, если установлено значение 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; }
Если у вас будут карты вместо списков с ключами as attributeSame, вы можете быстрее проверить значение на одной карте, если есть соответствующее значение на второй карте или нет.
вы можете определить тип данных, которые вы держите ? это большие данные ? это сортировка ? Я думаю, что вам нужно рассмотреть различные подходы к эффективности в зависимости от данных.
например, если ваши данные большие и несортированные, вы можете попробовать итерировать два списка вместе по индексу и сохранить каждый атрибут списка в другом помощнике списка. затем вы можете перекрестно проверить текущие атрибуты в списках помощников.
удачи
редактировать : и я бы не стал рекомендуется перегрузка равна. его опасно и, вероятно, против вашего объекта ООП значение.
орг.springframework.утиль.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