两个 List的高效交集在Java中?

发布于 2024-08-23 20:12:52 字数 228 浏览 7 评论 0原文

问题很简单:

我有两个列表

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

,我需要获得它们的交集。有没有一种快速的方法可以实现这一目标?

Question is simple:

I have two List

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

And I need to get the intersection of these. Is there a quick way to achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

萝莉病 2024-08-30 20:12:52

您可以使用 retainAll 方法:

columnsOld.retainAll (columnsNew);

You can use retainAll method:

columnsOld.retainAll (columnsNew);
笑,眼淚并存 2024-08-30 20:12:52

使用 Google 的 Guava 库:

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

注意: 这就是很多比天真地与两个列表进行交集更有效:它是 O(n+m),而 列表版本的 O(n×m) 。对于两百万个项目的列表,这就是数百万次操作和数万亿次操作之间的区别。

Using Google's Guava library:

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

Note: This is much more efficient than naively doing the intersection with two lists: it's O(n+m), versus O(n×m) for the list version. With two million-item lists it's the difference between millions of operations and trillions of operations.

少女净妖师 2024-08-30 20:12:52

由于 keepAll 不会触及参数集合,因此速度会更快:

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 中留下的值。从旧列中删除已比较的值将减少所需的比较次数。

Since retainAll won't touch the argument collection, this would be faster:

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

The intersection will be the values left in columnsNew. Removing already compared values fom columnsOld will reduce the number of comparisons needed.

悲喜皆因你 2024-08-30 20:12:52

怎么样

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

How about

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;
}
沉溺在你眼里的海 2024-08-30 20:12:52

如果不关心出现的情况,则使用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< 中的一个实用程序类< /a>

using retainAll if don't care occurrences, otherwise using 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 is an utility class in abacus-common

深海不蓝 2024-08-30 20:12:52

对于流,有一种很好的方法,它可以在一行代码中完成此操作,并且您可以使用两个不同类型的列表,这对于 containsAll 方法来说是不可能的,据我所知:

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

There is a nice way with streams which can do this in one line of code and you can two lists which are not from the same type which is not possible with the containsAll method afaik:

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

An example for lists with different types. If you have a realtion between foo and bar and you can get a bar-object from foo than you can modify your stream:

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());
对风讲故事 2024-08-30 20:12:52

如果将第二个列表放入一个集合中,例如 HashSet。只需迭代第一个列表,检查集合中是否存在,如果不存在则删除,您的第一个列表最终将具有您需要的交集。
它比列表中的retainAll或contains要快得多。
这里强调的是使用集合而不是列表。查找的时间复杂度为 O(1)。
firstList.retainAll(new HashSet(secondList))也将起作用。

If you put the second list in a set say HashSet. And just iterate over the first list checking for presence on the set and removing if not present, your first list will eventually have the intersection you need.
It will be way faster than retainAll or contains on a list.
The emphasis here is to use a set instead of list. Lookups are O(1).
firstList.retainAll (new HashSet (secondList)) will also work.

·深蓝 2024-08-30 20:12:52

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

use org.apache.commons.collections4.ListUtils#intersection

爱殇璃 2024-08-30 20:12:52

使用 Java 8 Stream API(和 Java 9 List.of())您可以执行以下操作:

List<Integer> list1 = List.of(1, 1, 2, 2);
List<Integer> list2 = List.of(2, 2, 3, 3);

List<Integer> intersection = list1.stream()
    .filter(list2::contains)
    .distinct()
    .collect(Collectors.toList()); 

With Java 8 Stream API (and Java 9 List.of()) you can do following:

List<Integer> list1 = List.of(1, 1, 2, 2);
List<Integer> list2 = List.of(2, 2, 3, 3);

List<Integer> intersection = list1.stream()
    .filter(list2::contains)
    .distinct()
    .collect(Collectors.toList()); 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文