Pages

30 January 2013

Union Multiple Collections into a Single Collection

As developing daily tasks at work, I realize the need of a generic method that merges given an array of collections into a single collection as stated in this StackOverflow Thread.

There are reasonable references to well grounded frameworks (e.g. guava)  and sample implementations in that thread. I also check it out the popular "apache commons collections" that already offers a method that union two collections and returns a single non-modifiable collection; however I think it is not enough. There should be still some improvements to raise the bar to the next level.

 As a result i define the method as follows:

public static <T> Collection<T> union(Collection<T>... collections) {  } 


Implementation is as follows, I hope it helps you...


import java.util.Iterator;
import java.util.Collection;

/**
 * This class offers an alternative implementation for union an array of
 * (java.util.Collection) collections instead of only two collections.
 * http://commons.apache.org/collections/apidocs/org/apache/commons/collections/
 * CollectionUtils.html#union%28java.util.Collection,%20java.util.Collection%29
 * 
 * @author oguzhan.acargil
 * @see http://0guzhan.blogspot.com
 * */
public class CollectionUtil {

 public static  Collection union(Collection... collections) {
  if (hasElements(collections)) {
   int totalSize = totalSizeOf(collections);
   final UnmodifiableCollection union = new UnmodifiableCollection(
     totalSize);
   for (Collection collection : collections) {
    if (hasElements(collection)) {
     union.appendAll(collection);
    }
   }
   return union;
  }
  return null;
 }

 private static  int totalSizeOf(Collection... collections) {
  int totalSize = 0;
  if (hasElements(collections)) {
   for (Collection collection : collections) {
    if (hasElements(collection)) {
     totalSize += collection.size();
    }
   }
  }
  return totalSize;
 }

 private static  boolean hasElements(T[] array) {
  if (array != null && array.length > 0) {
   return true;
  } else {
   return false;
  }
 }

 private static  boolean hasElements(Collection collection) {
  if (collection != null && collection.size() > 0) {
   return true;
  } else {
   return false;
  }
 }

 private static class UnmodifiableCollection implements Collection {

  private int cursor;
  private int size;
  private Object[] elements;

  public UnmodifiableCollection(int totalSize) {
   this.cursor = 0;
   this.size = totalSize;
   this.elements = new Object[totalSize];
  }

  private void appendAll(Collection collection) {
   for (T element : collection) {
    elements[this.cursor++] = element;
   }
  }

  @Override
  public int size() {
   return this.size;
  }

  @Override
  public boolean isEmpty() {
   return this.size > 0;
  }

  @Override
  public boolean contains(Object o) {
   if (o != null && !isEmpty()) {
    for (Object element : this.elements) {
     if (o.equals(element)) {
      return true;
     }
    }
   }
   return false;
  }

  @Override
  public Iterator iterator() {
   @SuppressWarnings({ "unchecked", "rawtypes" })
   Iterator iterator = new Iterator() {

    private int current = -1;

    @Override
    public boolean hasNext() {
     return (this.current + 1) < size;
    }

    @Override
    public Object next() {
     return elements[++this.current];
    }

    @Override
    public void remove() {
     throw new RuntimeException(
       "Iterator.remove() is not supported; "
         + "since this is a non-modifable collection implementation");
    }
   };
   return iterator;
  }

  @Override
  public Object[] toArray() {
   return elements;
  }

  @SuppressWarnings({ "unchecked", "hiding" })
  @Override
  public  T[] toArray(T[] a) {
   if (a != null && !isEmpty()) {
    if (a.length == size()) {
     for (int index = 0; index < a.length; index++) {
      a[index] = (T) elements[index];
     }
    }
   }
   return a;
  }

  @Override
  public boolean add(T e) {
   throw new RuntimeException("Collection.add() is not supported; "
     + "since this is a non-modifable collection implementation");
  }

  @Override
  public boolean remove(Object o) {
   throw new RuntimeException(
     "Collection.remove(Object o) is not supported; "
       + "since this is a non-modifable collection implementation");
  }

  @Override
  public boolean containsAll(Collection c) {
   throw new RuntimeException(
     "Collection.containsAll(Collection c) is not supported; "
       + "since this is a non-modifable collection implementation");
  }

  @Override
  public boolean addAll(Collection c) {
   throw new RuntimeException(
     "Collection.addAll(Collection c) is not supported; "
       + "since this is a non-modifable collection implementation");
  }

  @Override
  public boolean removeAll(Collection c) {
   throw new RuntimeException(
     "Collection.removeAll((Collection c) is not supported; "
       + "since this is a non-modifable collection implementation");
  }

  @Override
  public boolean retainAll(Collection c) {
   throw new RuntimeException(
     "Collection.retainAll(Collection c) is not supported; "
       + "since this is a non-modifable collection implementation");
  }

  @Override
  public void clear() {
   throw new RuntimeException("Collection.clear() is not supported; "
     + "since this is a non-modifable collection implementation");
  }
 }
}

No comments:

Post a Comment

Thx for reading! Comments are appreciated...