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

我有两个不同对象的列表。

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

但我认为有一个更好、更快的方法可以做到这一点:) 有人能提议吗?

谢谢!

283502 次浏览

为了使它更快,您可以添加一个 break; 这样,如果 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;
}

如果您使用的是 map 而不是使用 Attribute 属性的列表,那么您可以更快地检查一个 map 中的值,看看第二个 map 中是否有相应的值。

根据 .contains(Object obj)的 JavaDoc:

如果此列表包含指定的元素,则返回 true 正式地,当且仅当该列表包含至少一个 元素 e 使得(o = = null? e = = null: o.equals (e))。

因此,如果重写给定对象的 .equals()方法,应该能够执行: if(list1.contains(object2))...

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

你可以使用 Apache Commons CollectionUtils:

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

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

更快的方式将需要额外的空间。

例如:

  1. 将一个列表中的所有项目放入一个 HashSet (您必须自己实现散列函数才能使用 object.getAttributeSame ())

  2. 浏览其他列表并检查 HashSet 中是否有任何项。

通过这种方式,每个对象最多被访问一次。HashSet 的速度足以检查或插入 O (1)中的任何对象。

Collection一种方法命名为 retainAll,但有一些 副作用为您 参考文献

控件中包含的此列表中的元素 指定的集合(可选操作)。换句话说,删除 列表中不包含的所有元素 指定的集合。

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

就像

boolean b = list1.retainAll(list2);

你能定义你持有的数据类型吗? 是大数据吗? 是排序的吗? 我认为您需要根据数据考虑不同的效率方法。

例如,如果您的数据很大且未排序,您可以尝试通过索引将两个列表迭代在一起,并将每个列表属性存储在另一个列表帮助器中。 然后可以通过帮助器列表中的当前属性进行交叉检查。

祝你好运

编辑: 并且我不建议重载 equals。它很危险,可能会违背你的对象 oop 的意思。

如果您只是需要测试基本的相等性,那么可以使用基本的 JDK 来完成,而不需要修改一行中的输入列表

!Collections.disjoint(list1, list2);

如果你需要测试一个特定的属性,那就更难了。我建议,默认情况下,

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

它收集 list2中不同的数值并测试 list1中的每个数值是否存在。

洛伊斯的回答是正确的,我只是想加一个例子:

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

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

使用 java 8,我们可以像下面这样检查一个列表是否包含其他列表的任何元素

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

为了简化纳伦德拉的逻辑,你可以这样说:

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