3

What is the best way to create a union of N lists in java ?

For eg

List<Integer> LIST_1 = Lists.newArrayList(1);

List<Integer> LIST_2 = Lists.newArrayList(2);

List<Integer> LIST_3 = Lists.newArrayList(3);

List<Integer> LIST_4 = Lists.newArrayList(4);

List<Integer> LIST_1_2_3_4 = Lists.newArrayList(1,2,3,4);

assert LIST_1_2_3_4.equals(union(LIST_1,LIST_2,LIST_3,LIST_4)); 

The union method will take a var args parameter

<Item> List<Item> union(List<Item> ... itemLists)

Is there a library which provides this method.Simplest way is to loop through the array and accumulate each list into one

Abhijeet Kushe
  • 2,477
  • 3
  • 26
  • 39

3 Answers3

6

There may be a library, but including it only for these 3 lines of code would probably not worth another dependency...

private static <Item> List<Item> union(List<Item> ... itemLists)
{
    List<Item> result = new ArrayList<Item>();
    for (List<Item> list : itemLists) result.addAll(list);
    return result;
}
Marco13
  • 53,703
  • 9
  • 80
  • 159
  • You should use a Set to avoid duplicated elements and then return a list containing the elements that are in the set you buit. – Alexis C. Mar 06 '14 at 16:56
  • To avoid increasing the size of the internal array in the result list, i would calculate the total size of the result list and then create it with the total size. Just loop through the itemLists, sum their size and pass it as in argumento for the result ArrayList contructor – andreban Mar 06 '14 at 16:57
  • @ZouZou that, however wouldn't be a true union of the lists, since each list itself could already contain duplicates. – Thomas Mar 06 '14 at 16:57
  • @ZouZou This was not part of the question. Maybe the elements *should* occur as often as they occur in the list? If there should be no duplicates, you're right, of course. – Marco13 Mar 06 '14 at 16:57
  • @Thomas I was thinking of a more mathematical way, i.e the lists you pass as parameters does not contain duplicated elements. If it's not the case, then yes this answer has the right approach. – Alexis C. Mar 06 '14 at 17:03
  • @Marco13 thanks for the quick response.I did implement the method in the way you did.I was wondering if there was already a library present I would use that rather than make my own.Apache Common Collections and Guava have methods but they are only for 2 lists – Abhijeet Kushe Mar 06 '14 at 17:03
  • @AbhijeetKushe no, Guava provides methods for multiple iterables (e.g. lists) – Thomas Mar 06 '14 at 17:05
  • @Thomas I liked the solution which you gave below.Will stick with that for now – Abhijeet Kushe Mar 06 '14 at 17:11
5

You could use Google Guava:

List<Integer> joined = new ArrayList<>( Iterables.concat(LIST_1, LIST_2, LIST_3, LIST_4) );

or for comparison only:

Iterables.elementsEqual( LIST_1_2_3_4, Iterables.concat(LIST_1, LIST_2, LIST_3, LIST_4) );
Thomas
  • 87,414
  • 12
  • 119
  • 157
  • 1
    `Iterables.concat` returns an `Iterable`. I didn't find an ArrayList constructor which takes an `Iterable` as input. Instead, I used Guava's `Lists` like so: `Lists.newArrayList( Iterables.concat(LIST_1, LIST_2, LIST_3, LIST_4) );` – Michael Oct 10 '19 at 04:47
1

I am not sure what you mean by best solution but a simple solution would involve using the addAll method.

For extra performance you may also hint the size by summing all sizes.

new ArrayList<...>(totalSizeHere)

Also see this answer: How to do union, intersect, difference and reverse data in java

Community
  • 1
  • 1
Christophe Roussy
  • 16,299
  • 4
  • 85
  • 85