6

我在获取 Java 上几个列表的交集时遇到了麻烦。我正在做的是:我得到(可以说)3个整数列表:

列表 1:[2、2、2、2、5、5]

清单 2:[2, 2, 103]

清单 3:[2, 431]

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

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

我得到了这个结果:

list1: [2, 2, 2, 2]

但我希望得到这个:

清单 1:[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]

4

6 回答 6

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)));
}
于 2013-02-08T23:29:01.350 回答
2

使用多集数据结构可以更轻松地解决此问题。例如,如果你使用 guava's Multiset,你可以使用Multisets.retainOccurrences()

于 2013-02-08T23:29:54.690 回答
2

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

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

Set. _

于 2013-02-08T23:33:56.450 回答
0

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

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

于 2013-02-08T23:27:20.857 回答
0

retainAll正如你所说,你会得到错误的答案。我建议您使用HashMap保持integer/count配对并相互扫描列表并缩小您的map.

  1. map从 的值填充list1
  2. 遍历其他列表并使用该值min(# of intg in other_list, map.get(intg))更新和更新map
  3. 结果map将是所有列表的交集。
于 2013-02-08T23:27:56.923 回答
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);
}
于 2015-09-25T23:19:44.303 回答