Check if one list contains element from the other

JavaListFindElement

Java Problem Overview


I have two lists with different objects in them.

List<Object1> list1;
List<Object2> list2;

I want to check if element from list1 exists in list2, based on specific attribute (Object1 and Object2 have (among others), one mutual attribute (with type Long), named attributeSame).

right now, I do it like this:

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;
}

But I think there is a better and faster way to do this :) Can someone propose it?

Thanks!

Java Solutions


Solution 1 - Java

If you just need to test basic equality, this can be done with the basic JDK without modifying the input lists in the one line

!Collections.disjoint(list1, list2);

If you need to test a specific property, that's harder. I would recommend, by default,

list1.stream()
   .map(Object1::getProperty)
   .anyMatch(
     list2.stream()
       .map(Object2::getProperty)
       .collect(toSet())
       ::contains)

...which collects the distinct values in list2 and tests each value in list1 for presence.

Solution 2 - Java

To shorten Narendra's logic, you can use this:

boolean var = lis1.stream().anyMatch(element -> list2.contains(element));

Solution 3 - Java

You can use Apache Commons CollectionUtils:

if(CollectionUtils.containsAny(list1,list2)) {  
    // do whatever you want
} else { 
    // do other thing 
}  

This assumes that you have properly overloaded the equals functionality for your custom objects.

Solution 4 - Java

There is one method of Collection named retainAll but having some side effects for you reference

> Retains only the elements in this list that are contained in the > specified collection (optional operation). In other words, removes > from this list all of its elements that are not contained in the > specified collection.

> true if this list changed as a result of the call

Its like

boolean b = list1.retainAll(list2);

Solution 5 - Java

Loius answer is correct, I just want to add an example:

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

Solution 6 - Java

to make it faster, you can add a break; that way the loop will stop if found is set to 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;
}

If you would have maps in stead of lists with as keys the attributeSame, you could check faster for a value in one map if there is a corresponding value in the second map or not.

Solution 7 - Java

According to the JavaDoc for the .contains(Object obj):

> Returns true if this list contains the specified element. More > formally, returns true if and only if this list contains at least one > element e such that (o==null ? e==null : o.equals(e)).

So if you override your .equals() method for your given object, you should be able to do: if(list1.contains(object2))...

If the elements will be unique (ie. have different attributes) you could override the .equals() and .hashcode() and store everything in HashSets. This will allow you to check if one contains another element in constant time.

Solution 8 - Java

faster way will require additional space .

For example:

  1. put all items in one list into a HashSet ( you have to implement the hash function by yourself to use object.getAttributeSame() )

  2. Go through the other list and check if any item is in the HashSet.

In this way each object is visited at most once. and HashSet is fast enough to check or insert any object in O(1).

Solution 9 - Java

Can you define the type of data you hold ? is it big data ? is it sorted ? I think that you need to consider different efficiency approaches depending on the data.

For example, if your data is big and unsorted you could try and iterate the two lists together by index and store each list attribute in another list helper. then you could cross check by the current attributes in the helper lists.

good luck

edited : and I wouldn't recommend overloading equals. its dangerous and probably against your object oop meaning.

Solution 10 - Java

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

Solution 11 - Java

With java 8, we can do like below to check if one list contains any element of other list

boolean var = lis1.stream().filter(element -> list2.contains(element)).findFirst().isPresent();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNedView Question on Stackoverflow
Solution 1 - JavaLouis WassermanView Answer on Stackoverflow
Solution 2 - JavaketanjainView Answer on Stackoverflow
Solution 3 - JavaWoot4MooView Answer on Stackoverflow
Solution 4 - JavaHarmeet SinghView Answer on Stackoverflow
Solution 5 - JavaMatias ElorriagaView Answer on Stackoverflow
Solution 6 - JavaTomView Answer on Stackoverflow
Solution 7 - JavanpintiView Answer on Stackoverflow
Solution 8 - JavalavinView Answer on Stackoverflow
Solution 9 - JavaR-E-LView Answer on Stackoverflow
Solution 10 - JavaakjainView Answer on Stackoverflow
Solution 11 - JavaNarendra JaggiView Answer on Stackoverflow