两个列表中的共同元素


95

我有两个ArrayList三个整数的对象。我想找到一种方法来返回两个列表的共同元素。有谁知道我如何实现这一目标?

Answers:


161

使用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.

RetainAll返回一个新列表?我试图将保留的输出存储到像tempList.addAll(listA.retainAll(listB))这样的新列表中;但它不起作用
zenitis 2011年

1
正如后面的链接中所回答的Collection#retainAll()以及代码片段中的注释一样,不,不是。更改会反映在您正在调用该方法的列表中。
BalusC

问题在于,常见列表的初始化大小为3,然后尝试通过仅返回一个或两个元素来更改其大小。我尝试您的建议,它使我超出范围。
zenitis 2011年

在这种方法中,我将无法匹配元素的出现次数。......例如,如果要执行listB.retainAll(listA),例如说listA {2,3,5}和listB {5 5} ,listB现在将有{5,5} ...在将listA和listB比较为{5}之后,我想要我的最终结果。请建议我们如何实现这一目标
NANCY

1
如果收集对象选择不当,则可能引发UnsupportedOperationException。上面带有ArrayList的示例可以正常工作。
demongolem

39

您可以将集合相交操作与ArrayList对象一起使用。

像这样:

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]

6
请注意,这种方式也反映了更改l2。您可能想说List<Integer> l3 = new ArrayList<Integer>(l2);相反。
BalusC

如果说l1具有2个元素,而l2具有3个相同元素,则问题变得更加混乱。即使该元素仅在l1中包含两次,retainAll返回也将该元素的3放入l3中。
demongolem 2012年

35

为什么要重新发明轮子?使用公共收藏集

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

这是一个很好的解决方案,但是如上所述,它具有与retainAll()重复元素不同的行为。因此,根据您解决问题的方式,一种可能是正确的,另一种是错误的。
demongolem

18

结合使用Java 8的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());

4
包含看起来好像是O(n)操作,它将被调用n次,除非编译器执行了一些聪明的操作。有人知道上面的是线性还是平方时间吗?
Regorsmitz '16

1
这将是一个* n操作!
Lakshmikant Deshpande

5

在此处输入图片说明

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

尽管此代码可以回答问题,但提供有关如何和/或为什么解决问题的其他上下文将提高答案的长期价值。
Michael Parker

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

List<Integer> listB = new ArrayList<>();
    listB.add(1);
    listB.add(5);
    listB.add(6);
    listB.add(7);
System.out.println(listA.stream().filter(listB::contains).collect(Collectors.toList()));


Java 1.8 Stream API Solutions

输出[1,5]


-改进我们可以将列表定义为List <Integer> listA = asList(1、5、3、4); List <Integer> listB = asList(1、5、6、7);
Rajeev Ranjan

4

您可以使用“ retainAll”方法获得两个列表之间的公共元素。此方法将从应用的列表中删除所有不匹配的元素。

Ex.: list.retainAll(list1);

在这种情况下,将从列表中删除所有不在list1中的元素,并且仅保留那些在list和list1之间公用的元素。

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之间的公共元素。



3
    // 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);

3

考虑两个列表L1和L2

使用Java8,我们可以轻松找到它

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


1

万一你想自己做..

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

1
OP正在寻求一种方法来查找哪些元素是通用元素,而不是查找多少个通用元素。
布伦登·杜根

@BrendonDugan-这就是这段代码的作用。该列表commons包含公共元素。第二个for循环将它们打印在控制台上。我看不到代码在哪里计算通用元素。
Ajoy Bhatia

@AjoyBhatia-当我发表评论时(2013年),代码仅返回了一些常见元素。
布伦登·杜根

@BrendonDugan哦,好。对于那个很抱歉。我应该记住,答案可以在适当的位置编辑,但评论通常按时间顺序保留:-)
Ajoy Bhatia

0

上面的某些答案相似但不相同,因此将其发布为新答案。

解决方案:
1.使用HashSet保留需要删除的
元素2.将list1的所有元素添加到HashSet
3.迭代list2并从HashSet中删除list2 ==>中同时存在于list1和list2的元素
4现在迭代HashSet并从list1中删除元素(因为我们已经添加了list1的所有元素进行设置),最后,list1具有所有公共元素
注意:我们可以添加list2的所有元素,并且在第3次迭代中,我们应该从中删除元素清单2。

时间复杂度: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]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.