Проверьте, содержит ли один список элемент из другого


у меня есть два списка с разными предметами в них.

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 77

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

быстрый способ потребует дополнительного пространства .

например:

  1. поместите все элементы в один список в хэш-набор (Вы должны реализовать хэш-функцию самостоятельно, чтобы использовать объект.getAttributeSame ())

  2. перейдите в другой список и проверьте, есть ли какой-либо элемент в хэш-наборе.

таким образом, каждый объект посещается не более одного раза. и 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