Check if one list contains an item from another

I have two lists with different objects in them.

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

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

right now, I am doing 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 anyone suggest this?

Thank!

+90
java list find element
Aug 03 2018-12-12T00:
source share
11 answers

If you just need to check the basic equality, this can be done using the basic JDK without changing the input lists in one line

 !Collections.disjoint(list1, list2); 

If you need to check a specific property, this is more complicated. I would recommend, by default,

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

... which collects individual values ​​in list2 and checks each value in list1 for availability.

+198
Aug 03 '12 at 15:59
source share

You can use Apache Commons CollectionUtils :

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

This assumes that you overloaded the equals function correctly for your custom objects.

+34
Aug 03 2018-12-12T00:
source share

There is one method from Collection called retainAll , but with some side effects for you reference

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

true if this list has changed as a result of a call

Its like

 boolean b = list1.retainAll(list2); 
+9
Aug 03 2018-12-12T00:
source share

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 
+5
Feb 19 '16 at 16:57
source share

to make it faster, you can add break; so that the loop stops if found 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 have cards instead of lists with attributeSame keys, you can quickly check the value on one card, if the second card has a corresponding value.

+2
Aug 03 2018-12-12T00:
source share

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

Returns true if this list contains the specified item. More formally, it 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 a given object, you should be able to: if(list1.contains(object2))...

If the elements are unique (i.e. have different attributes), you can override .equals() and .hashcode() and save everything in HashSets . This will allow you to check if one element contains constant time.

+2
Aug 03 '12 at 13:13
source share

a faster way will require additional space.

For example:

  • put all the items in one list in a HashSet (you need to implement the hash function yourself using object.getAttributeSame ())

  • Go to another list and check if any item is in the HashSet.

Thus, each object is visited no more than once. and the HashSet is fast enough to check or insert any object in O (1).

+2
Aug 03 2018-12-12T00:
source share

To shorten the logic of Narendra, you can use this:

 boolean var = lis1.stream().anyMatch(element -> list2.contains(element)); 
+1
Apr 28 '19 at 11:24
source share

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

For example, if your data is large and unsorted, you can try and iterate over two lists together by index and save each attribute of the list in a different auxiliary list. then you can cross-check the current attributes in the auxiliary lists.

luck

edited: and I would not recommend overloading peers. it is dangerous and probably against your facility.

0
Aug 03 2018-12-12T00:
source share

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 
0
Feb 13 '18 at 7:04
source share

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

 boolean var = lis1.stream().filter(element -> list2.contains(element)).findFirst().isPresent(); 
0
Mar 15 '19 at 10:50
source share



All Articles