两个列表中的公共元素

我有两个 ArrayList对象,每个对象有三个整数。我想找到一种方法来返回这两个列表的公共元素。有人知道我该怎么做吗?

222421 次浏览

You can use set intersection operations with your ArrayList objects.

就像这样:

List<Integer> l1 = new ArrayList<Integer>();


l1.add(1);
l1.add(2);
l1.add(3);


List<Integer> l2= new ArrayList<Integer>();
l2.add(4);
l2.add(2);
l2.add(3);


System.out.println("l1 == "+l1);
System.out.println("l2 == "+l2);


List<Integer> l3 = new ArrayList<Integer>(l2);
l3.retainAll(l1);


System.out.println("l3 == "+l3);

现在,l3应该只有 l1l2之间的公共元素。

CONSOLE OUTPUT
l1 == [1, 2, 3]
l2 == [4, 2, 3]
l3 == [2, 3]

使用 Collection#retainAll()

listA.retainAll(listB);
// listA now contains only the elements which are also contained in listB.

如果希望避免 listA中的更改受到影响,那么需要创建一个新的更改。

List<Integer> common = new ArrayList<Integer>(listA);
common.retainAll(listB);
// common now contains only the elements which are contained in listA and listB.

为什么要重新发明轮子? 使用 Commons Collections:

CollectionUtils.intersection(java.util.Collection a, java.util.Collection b)

如果你想自己动手的话。

List<Integer> commons = new ArrayList<Integer>();


for (Integer igr : group1) {
if (group2.contains(igr)) {
commons.add(igr);
}
}


System.out.println("Common elements are :: -");
for (Integer igr : commons) {
System.out.println(" "+igr);
}

结合使用 Java8的 Stream.filter()方法和 List.contains():

import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;


/* ... */


List<Integer> list1 = asList(1, 2, 3, 4, 5);
List<Integer> list2 = asList(1, 3, 5, 7, 9);
    

List<Integer> common = list1.stream().filter(list2::contains).collect(toList());
    // Create two collections:
LinkedList<String> listA =  new LinkedList<String>();
ArrayList<String> listB =  new ArrayList<String>();


// Add some elements to listA:
listA.add("A");
listA.add("B");
listA.add("C");
listA.add("D");


// Add some elements to listB:
listB.add("A");
listB.add("B");
listB.add("C");


// use


List<String> common = new ArrayList<String>(listA);
// use common.retainAll


common.retainAll(listB);


System.out.println("The common collection is : " + common);

enter image description here

List<String> lista =new ArrayList<String>();
List<String> listb =new ArrayList<String>();


lista.add("Isabella");
lista.add("Angelina");
lista.add("Pille");
lista.add("Hazem");


listb.add("Isabella");
listb.add("Angelina");
listb.add("Bianca");


// Create an aplusb list which will contain both list (list1 and list2) in which common element will occur twice
List<String> listapluslistb =new ArrayList<String>(lista);
listapluslistb.addAll(listb);
                

// Create an aunionb set which will contain both list (list1 and list2) in which common element will occur once
Set<String> listaunionlistb =new HashSet<String>(lista);
listaunionlistb.addAll(listb);
                

for(String s:listaunionlistb)
{
listapluslistb.remove(s);
}
System.out.println(listapluslistb);

您可以使用该方法获取两个列表之间的公共元素 "retainAll". This method will remove all unmatched elements from the list to 它适用于。

Ex.: list.retainAll(list1);

在这种情况下,来自列表的所有不在 list1中的元素都将是 删除,只有那些将被保留的共同之间的列表和 清单1。

List<Integer> list = new ArrayList<>();
list.add(10);
list.add(13);
list.add(12);
list.add(11);


List<Integer> list1 = new ArrayList<>();
list1.add(10);
list1.add(113);
list1.add(112);
list1.add(111);
//before retainAll
System.out.println(list);
System.out.println(list1);
//applying retainAll on list
list.retainAll(list1);
//After retainAll
System.out.println("list::"+list);
System.out.println("list1::"+list1);

产出:

[10, 13, 12, 11]
[10, 113, 112, 111]
list::[10]
list1::[10, 113, 112, 111]

注意: 在 retainAll 应用于列表之后,列表包含 清单和清单1。

public <T> List<T> getIntersectOfCollections(Collection<T> first, Collection<T> second) {
return first.stream()
.filter(second::contains)
.collect(Collectors.toList());
}

上面的一些答案是相似的,但不是相同的,所以张贴它作为一个新的答案。

解决方案:
1. 使用 HashSet 保存需要删除的元素
2. 将 list1的所有元素添加到 HashSet
3.迭代 list2并从一个 HashSet 中删除 list2 = = > 中存在的元素,list1和 list2中都存在这些元素
4.现在迭代 HashSet 并从 list1中删除元素(因为我们已经将 list1的所有元素添加到 set 中) ,最后,list1具有所有公共元素
注意: 我们可以添加 list2的所有元素,在第3次迭代中,我们应该从 list2中删除元素。

时间复杂度: O (n)
空间复杂度: O (n)

密码:

import com.sun.tools.javac.util.Assert;
import org.apache.commons.collections4.CollectionUtils;


List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
list1.add(3);
list1.add(4);
list1.add(5);


List<Integer> list2 = new ArrayList<>();
list2.add(1);
list2.add(3);
list2.add(5);
list2.add(7);
Set<Integer> toBeRemoveFromList1 = new HashSet<>(list1);
System.out.println("list1:" + list1);
System.out.println("list2:" + list2);
for (Integer n : list2) {
if (toBeRemoveFromList1.contains(n)) {
toBeRemoveFromList1.remove(n);
}
}
System.out.println("toBeRemoveFromList1:" + toBeRemoveFromList1);
for (Integer n : toBeRemoveFromList1) {
list1.remove(n);
}
System.out.println("list1:" + list1);
System.out.println("collectionUtils:" + CollectionUtils.intersection(list1, list2));
Assert.check(CollectionUtils.intersection(list1, list2).containsAll(list1));

产出:

list1:[1, 2, 3, 4, 5]
list2:[1, 3, 5, 7]
toBeRemoveFromList1:[2, 4]
list1:[1, 3, 5]
collectionUtils:[1, 3, 5]

考虑两个列表 L1和 L2

使用 Java8我们可以很容易地找到它

L1.stream().filter(L2::contains).collect(Collectors.toList())

低于密码 删除列表中的公共元素

List<String> result =  list1.stream().filter(item-> !list2.contains(item)).collect(Collectors.toList());

检索公共元素

List<String> result = list1.stream()
.distinct()
.filter(list::contains)
.collect(Collectors.toList());
public static <T> List<T> getCommonElements(
java.util.Collection<T> a,
java.util.Collection<T> b
) {
if(a==null && b==null) return new ArrayList<>();
if(a!=null && a.size()==0) return new ArrayList<>(b);
if(b!=null && b.size()==0) return new ArrayList<>(a);
        

Set<T> set= a instanceof HashSet?(HashSet<T>)a:new HashSet<>(a);
return b.stream().filter(set::contains).collect(Collectors.toList());
}

为了获得更好的时间性能,请使用 HashSet (O (1)查找)而不是 List (O (n)查找)

时间复杂度-< em > O (b) 空间复杂性-< em > O (a)

这个问题讨论了三个项目,许多建议建议使用 retainAll。我认为必须指出的是,随着名单的规模越来越大,所有似乎都变得更加低效。

在我的测试中,我发现转换到 Set 和循环比使用 retainAll for List 处理1000个项目要快60倍左右

  List<Integer> common(List<Integer> biggerList, List<Integer> smallerList) {
Set<Integer> set1 = new HashSet<>(biggerList);
List<Integer> result = new ArrayList<>(smallerList.size());
for (Integer i : smallerList) {
if (set1.contains(i)) {
result.add(i);
}
}
return result;
}