检查一个列表是否包含另一个列表中的元素

时间:2020-11-26 01:37:28

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).

我想检查list1中的元素是否存在于list2中,基于特定属性(Object1和Object2具有(其中包括)一个相互属性(类型为Long),名为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!

谢谢!

9 个解决方案

#1


157  

This can be done with the basic JDK without modifying the input lists in the one line

这可以使用基本JDK完成,而无需修改一行中的输入列表

!Collections.disjoint(list1, list2);

#2


30  

You can use Apache Commons CollectionUtils:

您可以使用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.

这假设您已正确重载自定义对象的equals功能。

#3


8  

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

Collection有一种名为retainAll的方法,但有一些副作用供你参考

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

如果此列表因调用而更改,则为true

Its like

就像是

boolean b = list1.retainAll(list2);

#4


3  

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

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


2  

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

    将所有项目放在一个HashSet中(你必须自己实现hash函数才能使用object.getAttributeSame())

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

    浏览其他列表并检查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).

这样每个对象最多访问一次。和HashSet足够快,可以检查或插入O(1)中的任何对象。

#6


2  

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

根据JavaDoc的.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)).

如果此列表包含指定的元素,则返回true。更正式地,当且仅当此列表包含至少一个元素e时才返回true(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))...

因此,如果您覆盖给定对象的.equals()方法,您应该能够: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.

如果元素是唯一的(即具有不同的属性),则可以覆盖.equals()和.hashcode()并将所有内容存储在HashSet中。这将允许您检查是否在恒定时间内包含另一个元素。

#7


1  

to make it faster, you can add a break; that way the loop will stop if found is set to true:

为了使它更快,你可以添加休息时间;这样,如果found设置为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.

如果你有地图而不是带有按键属性列表的列表,如果第二张地图中有相应的值,你可以更快地检查一张地图中的值。

#8


0  

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.

编辑:我不建议重载equals。它的危险性可能与你的目标有关。

#9


0  

org.springframework.util.CollectionUtils

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

#1


157  

This can be done with the basic JDK without modifying the input lists in the one line

这可以使用基本JDK完成,而无需修改一行中的输入列表

!Collections.disjoint(list1, list2);

#2


30  

You can use Apache Commons CollectionUtils:

您可以使用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.

这假设您已正确重载自定义对象的equals功能。

#3


8  

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

Collection有一种名为retainAll的方法,但有一些副作用供你参考

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

如果此列表因调用而更改,则为true

Its like

就像是

boolean b = list1.retainAll(list2);

#4


3  

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

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


2  

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

    将所有项目放在一个HashSet中(你必须自己实现hash函数才能使用object.getAttributeSame())

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

    浏览其他列表并检查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).

这样每个对象最多访问一次。和HashSet足够快,可以检查或插入O(1)中的任何对象。

#6


2  

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

根据JavaDoc的.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)).

如果此列表包含指定的元素,则返回true。更正式地,当且仅当此列表包含至少一个元素e时才返回true(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))...

因此,如果您覆盖给定对象的.equals()方法,您应该能够: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.

如果元素是唯一的(即具有不同的属性),则可以覆盖.equals()和.hashcode()并将所有内容存储在HashSet中。这将允许您检查是否在恒定时间内包含另一个元素。

#7


1  

to make it faster, you can add a break; that way the loop will stop if found is set to true:

为了使它更快,你可以添加休息时间;这样,如果found设置为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.

如果你有地图而不是带有按键属性列表的列表,如果第二张地图中有相应的值,你可以更快地检查一张地图中的值。

#8


0  

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.

编辑:我不建议重载equals。它的危险性可能与你的目标有关。

#9


0  

org.springframework.util.CollectionUtils

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