Get crossroads of multiple lists using keepAll in Java

I'm having trouble getting intersection of multiple lists in Java. What I do is: I get (say) 3 Lists of integers:

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

list 2: [2, 2, 103]

list 3: [2, 431]

I apply keepAll to the first, using each of the remaining lists:

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

And I get this result:

list1: [2, 2, 2, 2]

But I would expect to get this:

list1: [2]

... Since a single item has a common list, it is one 2, not four 2.

I know that this is probably the expected behavior of the keepAll function, but I need to get the result that I mentioned above.

Any help?

Edit: Using a HashSet to prohibit duplicates will not help either. In this case, for example:

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

list 2: [2, 2, 103]

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

I need to get the result:

1: [2, 2] ( )

1: [2]

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

- Set, , HashSet. , retainAll.

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

javadocs Set.

+2

With retainAllyou will get the wrong answer, as you said. I would recommend you use HashMapsaving integer/countpairs and browsing each other's list and narrow yours map.

  • Enter mapfrom the values list1.
  • Scroll through the list to each other and grab min(# of intg in other_list, map.get(intg))and refresh with mapthis value.
  • The result mapwill be the intersection of all lists.
0
source

Here is one that you like, and it's recursive.

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

All Articles