Java 两个列表的有效交集<;字符串>;在爪哇?

Java 两个列表的有效交集<;字符串>;在爪哇?,java,list,intersection,Java,List,Intersection,问题很简单: 我有两张单子 List<String> columnsOld = DBUtils.GetColumns(db, TableName); List<String> columnsNew = DBUtils.GetColumns(db, TableName); List columnsall=DBUtils.GetColumns(db,TableName); List columnsNew=DBUtils.GetColumns(db,TableName);

问题很简单:

我有两张单子

List<String> columnsOld = DBUtils.GetColumns(db, TableName);
List<String> columnsNew = DBUtils.GetColumns(db, TableName);
List columnsall=DBUtils.GetColumns(db,TableName);
List columnsNew=DBUtils.GetColumns(db,TableName);
我需要得到这些的交叉点。有没有一种快速的方法可以实现这一点?

您可以使用以下方法:


由于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);
}
List columnsall=DBUtils.GetColumns(db,TableName);
List columnsNew=DBUtils.GetColumns(db,TableName);
对于(int i=columnsNew.size()-1;i>-1;--i){
String str=columnsNew.get(i);
如果(!columnsaled.remove(str))
柱新。删除(str);
}
交点将是列new中留下的值。删除columnsOld中已比较的值将减少所需的比较次数。

如何

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;
}
私有列表相交(列表A、列表B){
List rtnList=新链接列表();
for(字符串dto:A){
如果(B.包含(dto)){
rtnList.add(dto);
}
}
返回rtnList;
}
使用谷歌图书馆:

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

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

流有一种很好的方法,它可以在一行代码中完成这一点,并且您可以使用containsAll方法afaik无法实现的两个不同类型的列表:

columnsOld.stream().filter(c -> columnsNew.contains(c)).collect(Collectors.toList());
不同类型列表的示例。如果您在foo和bar之间有关联,并且您可以从foo获得bar对象,那么您可以修改流:

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());
listwoolist=newarraylist(Arrays.asList(newfoo(),newfoo());
List barList=newarraylist(Arrays.asList(new bar(),new bar());
foulist.stream().filter(f->barList.contains(f.getBar()).collect(Collectors.toList());

如果你把第二个列表放在一个集合中,比如HashSet。只需在第一个列表上迭代检查集合中是否存在,如果不存在则删除,那么第一个列表最终将具有所需的交集。 它将比保留或包含在列表中快得多。 这里的重点是使用集合而不是列表。查找是O(1)。
firstList.retainAll(新哈希集(secondList))也将起作用。

如果不关心出现的情况,则使用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是org.apache.commons.collections4.ListUtils#intersection中的一个实用类,但是您的代码应该被提取到一个新的单独的方法中,因为从这个代码中完全不清楚它是做什么的。我也不会拒绝对这段代码进行额外的单元测试。同意,很好的方法分离、命名和单元测试ests始终是第一条规则。此方法不应该将ColumnSell中找不到的元素添加到columnsNew中吗?结果中似乎缺少这些元素。从ColumnSell中删除列的优化实际上可能没有什么区别(删除本身就有成本)或者甚至在ArrayList中a移除移动元素的情况下更慢。如果B包含不包含在a中的元素,则无需对这些元素进行迭代,因为我们正在尝试查找a和B中的所有元素。@JohnnyCoder Severy?@Ungeheuer如果您只想在B中包含重复的元素,则这不起作用oth listsNote:要使它与
字符串
以外的其他对象一起工作,您当然需要实现
等于
哈希代码
。代码很简单,但算法复杂度很低:O(n×m),而不是O(n+m)对于200万个项目列表,这是万亿次操作和数百万次操作之间的差异。
c->columnsNew.contains(c)
lambda可以重写为更简洁的方法引用:
columnsNew::contains
。但是这不会在O(n^2)时间内运行吗?
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]