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

У меня есть два списка с разными объектами в них.

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();