簡體   English   中英

使用Java中的retainAll獲取多個列表的交集

[英]Get intersection of several Lists using retainAll in Java

我很難找到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]

但我希望得到這個:

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]

這個方法怎么樣:

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

使用多集數據結構可以更輕松地解決此問題。 例如,如果你使用guava的Multiset ,你可以使用Multisets.retainOccurrences()

我會使用某種Set ,也許是HashSet 它們不會添加重復元素,並且它們具有retainAll方法。

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

這是Setjavadocs

您需要一個名為bag或multiset的數據結構,而不是列表。 例如,Apache commons集合庫包括一個:

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

有了retainAll你會得到錯誤的答案。 我建議你使用HashMap保持integer/count對並掃描彼此列表並縮小你的map

  1. list1的值填充map
  2. 迭代每個其他列表並獲取min(# of intg in other_list, map.get(intg))並使用該值更新map
  3. 結果map將是所有列表的交集。

這是一個你喜歡的,它是遞歸的。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM