使用Java中的retainAll获取多个列表的交集

时间:2013-02-08 23:23:21

标签: java arraylist

我在Java上获得多个列表的交集时遇到了麻烦。我正在做的是这样的: 我得到(比方说)3个整数列表:

清单1:[2,2,2,2,5,5]

清单2:[2,2,103]

列表3:[2,491]

我使用其余每个列表将retainAll应用于第一个:

list1.retainAll(list2);
list1.retainAll(list3);

我得到了这个结果:

list1:[2,2,2,2]

但是我希望得到这个:

list1:[2]

...由于所有列表共享的唯一元素是一个 2而不是四个 2。

我知道这可能是retainAll函数的预期行为,但我需要得到上面提到的结果。

有任何帮助吗?

修改 使用HashSet来禁止重复项也不会成功。在这种情况下,例如:

清单1:[2,2,2,2,5,5]

清单2:[2,2,103]

列表3:[2,2,2,431]

我需要得到一个结果:

列表1:[2,2](因为所有列表至少有一对2')

而不是

列表1:[2]

6 个答案:

答案 0 :(得分:6)

这种方法怎么样:

public static <T> Collection <T> intersect (Collection <? extends T> a, Collection <? extends T> b)
{
    Collection <T> result = new ArrayList <T> ();

    for (T t: a)
    {
        if (b.remove (t)) result.add (t);
    }

    return result;
}

public static void main (String [] args)
{
    List <Integer> list1 = new ArrayList <Integer> (Arrays.<Integer>asList (2, 2, 2, 2, 5, 5));
    List <Integer> list2 = new ArrayList <Integer> (Arrays.<Integer>asList (2, 2, 103));
    List <Integer> list3 = new ArrayList <Integer> (Arrays.<Integer>asList (2, 431));

    System.out.println (intersect (list1, intersect (list2, list3)));
}

答案 1 :(得分:2)

使用多集数据结构可以更轻松地解决此问题。例如,如果您使用番石榴Multiset,则可以使用Multisets.retainOccurrences()

答案 2 :(得分:2)

我会使用某种Set,也许是HashSet。他们不会添加重复元素,并且他们使用retainAll方法。

Set<Integer> uniqueNums = new HashSet<Integer>(list1);
uniqueNums.retainAll(list2);
uniqueNums.retainAll(list3);

以下是Set的{​​{3}}。

答案 3 :(得分:0)

您需要一个名为bag或multiset的数据结构,而不是列表。例如,Apache commons集合库包括一个:

http://commons.apache.org/collections/apidocs/org/apache/commons/collections/Bag.html#retainAll(java.util.Collection)

答案 4 :(得分:0)

如你所说,retainAll你会得到错误的答案。我建议您使用HashMap保留integer/count对并扫描彼此列表并缩小map范围。

  1. map
  2. 的值中填充list1
  3. 对每个其他列表进行迭代,然后选择min(# of intg in other_list, map.get(intg))并使用该值更新map
  4. 结果map将是所有列表的交集。

答案 5 :(得分:0)

这是一个你喜欢的,它是递归的。

public static <T> List<T> intersect(List<T> c1, List<T> c2) {
    List<T> inter = new ArrayList<>(c1);
    inter.retainAll(c2);
    return inter;
}

public static <T> List<T> intersect(List<T> first, List<T>... rest) {
    if (rest.length == 0)
        return first;

    List<T> second = rest[0];

    first = intersect(first,second);
    rest = Arrays.copyOfRange(rest, 1, rest.length);

    return intersect(first, rest);
}