73

问题很简单:

我有两个列表

List<String> columnsOld = DBUtils.GetColumns(db, TableName);
List<String> columnsNew = DBUtils.GetColumns(db, TableName);

我需要得到这些的交集。有没有一种快速的方法来实现这一目标?

4

8 回答 8

123

您可以使用retainAll方法:

columnsOld.retainAll (columnsNew);
于 2010-03-08T11:17:27.427 回答
20

使用 Google 的Guava库:

Sets.intersection(Sets.newHashSet(setA), Sets.newHashSet(setB))

注意:这比简单地与两个列表进行交集要有效得多:它是 O(n+m),而列表版本是 O(n×m) 。拥有 200 万个项目的列表是数百万次操作和数万亿次操作之间的区别。

于 2013-03-28T14:27:21.137 回答
19

由于 retainAll 不会触及参数集合,这会更快:

List<String> columnsOld = DBUtils.GetColumns(db, TableName); 
List<String> columnsNew = DBUtils.GetColumns(db, TableName); 

for(int i = columnsNew.size() - 1; i > -1; --i){
    String str = columnsNew.get(i);
    if(!columnsOld.remove(str))
        columnsNew.remove(str);
}

交集将是 columnsNew 中留下的值。从 columnsOld 中删除已经比较的值将减少所需的比较次数。

于 2010-03-08T12:24:03.430 回答
9

怎么样

private List<String> intersect(List<String> A, List<String> B) {
    List<String> rtnList = new LinkedList<>();
    for(String dto : A) {
        if(B.contains(dto)) {
            rtnList.add(dto);
        }
    }
    return rtnList;
}
于 2013-01-05T22:45:52.513 回答
4

流有一种很好的方法可以在一行代码中执行此操作,并且您可以使用两个不属于同一类型的列表,这对于 containsAll 方法 afaik 是不可能的:

columnsOld.stream().filter(c -> columnsNew.contains(c)).collect(Collectors.toList());

不同类型列表的示例。如果您在 foo 和 bar 之间有一个实体,并且您可以从 foo 获得一个 bar-object,那么您可以修改您的流:

List<foo> fooList = new ArrayList<>(Arrays.asList(new foo(), new foo()));
List<bar> barList = new ArrayList<>(Arrays.asList(new bar(), new bar()));

fooList.stream().filter(f -> barList.contains(f.getBar()).collect(Collectors.toList());
于 2014-09-11T15:09:24.380 回答
3

如果不关心出现,则使用 retainAll,否则使用 N.intersection

a = N.asList(12, 16, 16, 17, 19);
b = N.asList(16, 19, 107);
a.retainAll(b); // [16, 16, 19]
N.println(a);

a = N.asList(12, 16, 16, 17, 19);
b = N.asList(16, 19, 107);
a = N.intersect(a, b);
N.println(a); // [16, 19]

N 是abacus-common中的一个实用类

于 2016-11-09T00:20:27.377 回答
1

如果您将第二个列表放入一个集合中,请说 HashSet。并且只需遍历第一个列表,检查集合中是否存在,如果不存在则删除,您的第一个列表最终将具有您需要的交集。这将比 retainAll 或包含在列表中要快得多。这里的重点是使用集合而不是列表。查找是 O(1)。firstList.retainAll (new HashSet (secondList)) 也可以。

于 2016-05-06T23:56:45.723 回答
0

使用 org.apache.commons.collections4.ListUtils#intersection

于 2019-04-09T08:09:16.943 回答