Java中两个不同对象列表的交集

9

我有两个POJO类,每个类都有一个唯一ID的不同字段。

我想要对两个List<A>List<B>进行交集操作。

最好的方法是什么?一种方法是简单地迭代两次,但复杂度太高,为n2。

是否有更好的办法?我能用比较器做到吗?

Class A {
Id, Name ,DOB}

Class B{
id, aid ,location }

我有一个A列表和一个B列表

现在想要获取A列表中在B列表中的位置


你的列表是否已经按照id/Id排序? - Ben van Gompel
1
@Bohemian,SetList并不完全相同。 - Paul
不,我从来没有说过我想用Set来做。不,List没有排序。 - Zuned Ahmed
@Paul,针对这个问题,你可以使用两次 new HashSet<?>(list) 就可以了。 - Bohemian
但是集合将消除重复条目。 - Zuned Ahmed
5个回答

3

需要注意的是,CollectionUtils.intersection不能保证结果中项目的顺序(它的返回类型是Collection)。由于你正在处理列表,请记住这一点。 - NBJack
如果顺序很重要,你应该尝试使用ListUtils.intersection。 - NBJack

2

使用Java 8流

List<A> listA = new ArrayList<A>();
List<B> listB = new ArrayList<B>();

Set<Integer> aIdsFromBList = listB.stream().map(B::getAId).collect(Collectors.toSet());

return listA.stream
    .filter(a -> aIdsFromBList.contains(a.getId()))
    .collect(Collectors.toList());

2
你可以将List<B>元素放入一个HashMap<Integer,B>中,其中id是键。
这样做后,你可以遍历List<A>的元素,并使用哈希映射快速查找相应的B元素。这将提供所需的结构("在B中位置的A列表")。

你一定是在开玩笑吧。这个解决方案真的很烂,但如果你非得这么做,那就使用 Set 而不是 Map(你只是在使用 map 的 keyset - 这听起来很熟悉.. keySET?... SET?) 天啊... - Bohemian
1
@Bohemian:你显然有不同的解决方案。为什么不把它作为答案发布呢? - NPE
1
公平挑战 - 我已经发布了一个解决方案。那是漫长的一天结束了 - 对于我的态度感到抱歉。我本可以说得更好听一些。然而,Map仍然是错误的工具。 - Bohemian

2
  1. 按Id递增的顺序对列表进行排序。

  2. 从List A开始,在List B中找到相应的索引。记住List B的当前索引,称为(indB)

  3. 从List A的下一个索引开始,并从(indB+1)开始在List B中比较。

  4. 重复步骤1-4,直到List A或List B结束为止。


1

试试这个:

public static void main(String[] args) {System.nanoTime()
    List<A> as = new ArrayList<A>();
    List<B> bs = new ArrayList<B>();

    // Collect all A.ids in the list of B into a Set
    Set<String> baids = new HashSet<String>();
    for (B b : bs)
        baids.add(b.aid);

    // iterate through the list of A discarding those that don't have a B
    for (Iterator<A> i = as.iterator(); i.hasNext();)
        if (!baids.contains(i.next().Id)) // contains() executes fast for a Set
            i.remove();

    // now list "as" contains all A that have a B with A.Id = B.aid 
}

所需的输出是“在B中具有A位置的列表”。这个算法如何实现这一点? - NPE
但是我现在要用第一个for循环从一个列表中获取id,第二个for循环从第二个列表中获取,并且在内部保留所有都是通过循环来完成的。之后,我将再运行一个for循环以获取精确对象。我们能否使用对象和重写equals方法来实现这一点? - Zuned Ahmed
@aix(想着天哪...我必须要给你讲得明明白白吗?)好吧...我添加了一行代码,展示如何解决从集合中获取列表的神秘问题。 - Bohemian
不是很清楚谁需要给谁喂食,但你的 main() 的最后一行可能甚至无法编译。即使它能够编译,你已经失去了 A 的所有属性。坦白地说,我认为这场辩论对我们两个人来说都是浪费时间。我们显然没有达成共识。 - NPE
@aix 是的,那段代码我没有好好思考。我已经修复了它,现在我认为它是一个很好的解决方案。 - Bohemian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接