Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get intersection of several Lists using retainAll in Java

Tags:

java

arraylist

I'm having troubles to get the intersection of several Lists on Java. What I'm doing is this: I get (lets say) 3 Lists of integer numbers:

list 1: [2, 2, 2, 2, 5, 5]

list 2: [2, 2, 103]

list 3: [2, 431]

I'm applying retainAll to the first one using each of the remaining lists:

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

And I'm getting this result:

list1: [2, 2, 2, 2]

But I'd expect to get this one:

list1: [2]

...Since the only element all lists share is one 2 and not four 2.

I know this is probably the expected behaviour of the retainAll function, but I need to get the result I mentioned above.

Any help?

Edit: Using a HashSet to disallow duplicates won't do the trick either. In this case, for instance:

list 1: [2, 2, 2, 2, 5, 5]

list 2: [2, 2, 103]

list 3: [2, 2, 2, 431]

I need to get a result of:

list 1: [2, 2] (since all lists have at least a pair of 2's)

Instead of

list 1: [2]

like image 461
Multitut Avatar asked Feb 08 '13 23:02

Multitut


3 Answers

What about this method:

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)));
}
like image 114
Mikhail Vladimirov Avatar answered Nov 06 '22 02:11

Mikhail Vladimirov


This problem can be solved easier with a multiset data structure. For example, if you use guava's Multiset, you can use Multisets.retainOccurrences()

like image 36
ataylor Avatar answered Nov 06 '22 03:11

ataylor


I would use some kind of Set, perhaps a HashSet. They won't add duplicate elements, and they have the retainAll method.

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

Here's the javadocs for Set.

like image 29
rgettman Avatar answered Nov 06 '22 02:11

rgettman