/***************************************************************************
* Copyright (C) 2011 by H-Store Project *
* Brown University *
* Massachusetts Institute of Technology *
* Yale University *
* *
* http://hstore.cs.brown.edu/ *
* *
* Permission is hereby granted, free of charge, to any person obtaining *
* a copy of this software and associated documentation files (the *
* "Software"), to deal in the Software without restriction, including *
* without limitation the rights to use, copy, modify, merge, publish, *
* distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to *
* the following conditions: *
* *
* The above copyright notice and this permission notice shall be *
* included in all copies or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
***************************************************************************/
package edu.brown.utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import org.apache.commons.collections15.set.ListOrderedSet;
import org.apache.commons.lang.NotImplementedException;
/**
* @author pavlo
*/
public abstract class CollectionUtil {
private static final Random RANDOM = new Random();
public static <T extends Comparable<T>> List<T> sort(List<T> list) {
Collections.sort(list);
return (list);
}
public static <T extends Comparable<T>> Collection<T> sort(Collection<T> items) {
List<T> list = new ArrayList<T>(items);
Collections.sort(list);
return (list);
}
/**
* Put all of the elements in items into the given array This assumes that
* the array has been pre-allocated
*
* @param <T>
* @param items
* @param array
*/
public static <T> void toArray(Collection<T> items, Object array[], boolean convert_to_primitive) {
assert (items.size() == array.length);
int i = 0;
for (T t : items) {
if (convert_to_primitive) {
if (t instanceof Long) {
array[i] = ((Long) t).longValue();
} else if (t instanceof Integer) {
array[i] = ((Integer) t).intValue();
} else if (t instanceof Double) {
array[i] = ((Double) t).doubleValue();
} else if (t instanceof Boolean) {
array[i] = ((Boolean) t).booleanValue();
}
} else {
array[i] = t;
}
}
return;
}
/**
* Convert a Collection of Numbers to an array of primitive ints
* Null values will be skipped in the array
* @param items
* @return
*/
public static int[] toIntArray(Collection<? extends Number> items) {
int ret[] = new int[items.size()];
int idx = 0;
for (Number n : items) {
if (n != null) ret[idx] = n.intValue();
idx += 1;
} // FOR
return (ret);
}
/**
* Convert a Collection of Numbers to an array of primitive longs
* Null values will be skipped in the array
* @param items
* @return
*/
public static long[] toLongArray(Collection<? extends Number> items) {
long ret[] = new long[items.size()];
int idx = 0;
for (Number n : items) {
if (n != null) ret[idx] = n.longValue();
idx += 1;
} // FOR
return (ret);
}
/**
* Convert a Collection of Numbers to an array of primitive doubles
* Null values will be skipped in the array
* @param items
* @return
*/
public static double[] toDoubleArray(Collection<? extends Number> items) {
double ret[] = new double[items.size()];
int idx = 0;
for (Number n : items) {
if (n != null) ret[idx] = n.doubleValue();
idx += 1;
} // FOR
return (ret);
}
/**
* Put all the values of an Iterator into a List
*
* @param <T>
* @param it
* @return
*/
public static <T> List<T> list(Iterator<T> it) {
List<T> list = new ArrayList<T>();
CollectionUtil.addAll(list, it);
return (list);
}
/**
* Put all of the values of an Enumeration into a new List
*
* @param <T>
* @param e
* @return
*/
public static <T> List<T> list(Enumeration<T> e) {
return (list(iterable(e)));
}
/**
* Put all of the values of an Iterable into a new List
*
* @param <T>
* @param it
* @return
*/
public static <T> List<T> list(Iterable<T> it) {
return (list(it.iterator()));
}
/**
* Put all the values of an Iterator into a Set
*
* @param <T>
* @param it
* @return
*/
public static <T> Set<T> set(Iterator<T> it) {
Set<T> set = new HashSet<T>();
CollectionUtil.addAll(set, it);
return (set);
}
/**
* Put all of the values of an Iterable into a new Set
*
* @param <T>
* @param it
* @return
*/
public static <T> Set<T> set(Iterable<T> it) {
return (set(it.iterator()));
}
/**
* Returns a list containing the string representations of the elements in
* the collection
*
* @param <T>
* @param data
* @return
*/
public static <T> List<String> toStringList(Collection<T> data) {
List<String> ret = new ArrayList<String>();
for (T t : data)
ret.add(t.toString());
return (ret);
}
/**
* Returns a set containing the string representations of the elements in
* the collection
*
* @param <T>
* @param data
* @return
*/
public static <T> Set<String> toStringSet(Collection<T> data) {
Set<String> ret = new HashSet<String>();
for (T t : data)
ret.add(t.toString());
return (ret);
}
/**
* Return a random value from the given Collection
*
* @param <T>
* @param items
*/
public static <T> T random(Collection<T> items) {
return (CollectionUtil.random(items, RANDOM));
}
/**
* Return a random value from the given Collection
*
* @param <T>
* @param items
* @param rand
* @return
*/
public static <T> T random(Collection<T> items, Random rand) {
int idx = rand.nextInt(items.size());
return (CollectionUtil.get(items, idx));
}
/**
* Return a random value from the given Iterable
*
* @param <T>
* @param it
* @return
*/
public static <T> T random(Iterable<T> it) {
return (CollectionUtil.random(it, RANDOM));
}
/**
* Return a random value from the given Iterable
*
* @param <T>
* @param it
* @param rand
* @return
*/
public static <T> T random(Iterable<T> it, Random rand) {
List<T> list = new ArrayList<T>();
for (T t : it) {
list.add(t);
} // FOR
return (CollectionUtil.random(list, rand));
}
@SuppressWarnings("unchecked")
public static <E extends Enum<?>> Set<E> getAllExcluding(E elements[], E... excluding) {
Set<E> exclude_set = new HashSet<E>();
for (E e : excluding)
exclude_set.add(e);
Set<E> elements_set = new HashSet<E>();
for (int i = 0; i < elements.length; i++) {
if (!exclude_set.contains(elements[i]))
elements_set.add(elements[i]);
} // FOR
return (elements_set);
// Crappy java....
// Object new_elements[] = new Object[elements_set.size()];
// elements_set.toArray(new_elements);
// return ((E[])new_elements);
}
/**
* Add all the items in the array to a Collection
*
* @param <T>
* @param data
* @param items
*/
@SuppressWarnings("unchecked")
public static <T> Collection<T> addAll(Collection<T> data, T... items) {
for (T i : (T[]) items) {
data.add(i);
}
return (data);
}
/**
* Add all the items in the Enumeration into a Collection
*
* @param <T>
* @param data
* @param items
*/
public static <T> Collection<T> addAll(Collection<T> data, Enumeration<T> items) {
while (items.hasMoreElements()) {
data.add(items.nextElement());
} // WHILE
return (data);
}
/**
* Add all of the items from the Iterable into the given collection
*
* @param <T>
* @param data
* @param items
*/
public static <T> Collection<T> addAll(Collection<T> data, Iterable<T> items) {
return (CollectionUtil.addAll(data, items.iterator()));
}
/**
* Add all of the items from the Iterator into the given collection
*
* @param <T>
* @param data
* @param items
*/
public static <T> Collection<T> addAll(Collection<T> data, Iterator<T> items) {
while (items.hasNext()) {
data.add(items.next());
} // WHILE
return (data);
}
/**
* @param <T>
* @param <U>
* @param map
* @return
*/
public static <T, U extends Comparable<U>> T getGreatest(Map<T, U> map) {
T max_key = null;
U max_value = null;
for (T key : map.keySet()) {
U value = map.get(key);
if (max_value == null || value.compareTo(max_value) > 0) {
max_value = value;
max_key = key;
}
} // FOR
return (max_key);
}
/**
* Return the first item in a Iterable
*
* @param <T>
* @param items
* @return
*/
public static <T> T first(Iterable<T> items) {
return (CollectionUtil.get(items, 0));
}
/**
* Return the first item in a Iterator
*
* @param <T>
* @param items
* @return
*/
public static <T> T first(Iterator<T> items) {
return (items.hasNext() ? items.next() : null);
}
/**
* Returns the first item in an Enumeration
*
* @param <T>
* @param items
* @return
*/
public static <T> T first(Enumeration<T> items) {
return (items.hasMoreElements() ? items.nextElement() : null);
}
/**
* Return the ith element of a set. Super lame
*
* @param <T>
* @param items
* @param idx
* @return
*/
public static <T> T get(Iterable<T> items, int idx) {
if (items == null) {
return (null);
}
else if (items instanceof List<?>) {
return ((List<T>) items).get(idx);
}
else if (items instanceof ListOrderedSet<?>) {
return ((ListOrderedSet<T>) items).get(idx);
}
else if (items instanceof SortedSet<?> && idx == 0) {
SortedSet<T> set = (SortedSet<T>)items;
return (set.isEmpty() ? null : set.first());
}
int ctr = 0;
for (T t : items) {
if (ctr++ == idx) return (t);
}
return (null);
}
/**
* Return the last item in an Iterable
*
* @param <T>
* @param items
* @return
*/
public static <T> T last(Iterable<T> items) {
T last = null;
if (items instanceof List<?>) {
List<T> list = (List<T>) items;
last = (list.isEmpty() ? null : list.get(list.size() - 1));
}
else if (items instanceof SortedSet<?>) {
SortedSet<T> set = (SortedSet<T>)items;
last = (set.isEmpty() ? null : set.last());
}
else {
for (T t : items) {
last = t;
}
}
return (last);
}
/**
* Return the last item in an array
*
* @param <T>
* @param items
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T last(T... items) {
if (items != null && items.length > 0) {
return (items[items.length - 1]);
}
return (null);
}
/**
* Return a new map sorted by the values of the given original map
*
* @param <K>
* @param <V>
* @param map
* @return
*/
public static <K, V extends Comparable<V>> Map<K, V> sortByValues(Map<K, V> map) {
return sortByValues(map, false);
}
/**
* @param <K>
* @param <V>
* @param map
* @param reverse
* @return
*/
public static <K, V extends Comparable<V>> Map<K, V> sortByValues(Map<K, V> map, boolean reverse) {
SortedMap<K, V> sorted = new TreeMap<K, V>(new MapValueComparator<K, V>(map, reverse));
sorted.putAll(map);
return (sorted);
}
// public static <K, V extends Comparable<? super V>> List<K>
// getKeysSortedByValue(Map<K, V> map) {
// final int size = map.size();
// final List<K> keys = new ArrayList<K>(size);
// if (true || size == 1) {
// keys.addAll(map.keySet());
// } else {
// final List<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>(size);
// list.addAll(map.entrySet());
// final ValueComparator<V> cmp = new ValueComparator<V>();
// Collections.sort(list, cmp);
// for (int i = 0; i < size; i++) {
// keys.set(i, list.get(i).getKey());
// }
// }
// return keys;
// }
//
// private static final class ValueComparator<V extends Comparable<? super
// V>> implements Comparator<Map.Entry<?, V>> {
// public int compare(Map.Entry<?, V> o1, Map.Entry<?, V> o2) {
// return o1.getValue().compareTo(o2.getValue());
// }
// }
/**
* @param <K>
* @param <V>
* @param map
* @return
*/
public static <K extends Comparable<?>, V> List<V> getSortedList(SortedMap<K, Collection<V>> map) {
List<V> ret = new ArrayList<V>();
for (K key : map.keySet()) {
ret.addAll(map.get(key));
} // FOR
return (ret);
}
/**
* Wrap an Iterable around an Iterator
*
* @param <T>
* @param it
* @return
*/
public static <T> Iterable<T> iterable(final Iterator<T> it) {
return (new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return (it);
}
});
}
public static <T> Iterable<T> iterable(final T values[]) {
return (new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private int idx = 0;
@Override
public boolean hasNext() {
return (this.idx < values.length);
}
@Override
public T next() {
return (values[this.idx++]);
}
@Override
public void remove() {
throw new NotImplementedException();
}
};
}
});
}
/**
* Wrap an Iterable around an Enumeration
* @param <T>
* @param e
* @return
*/
public static <T> Iterable<T> iterable(final Enumeration<T> e) {
return (new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
@Override
public boolean hasNext() {
return (e.hasMoreElements());
}
@Override
public T next() {
return (e.nextElement());
}
@Override
public void remove() {
throw new NotImplementedException();
}
};
}
});
}
/**
* Wrap an Iterable around an Enumeration that is automatically
* cast to the specified type
* @param <T>
* @param e
* @return
*/
public static <T> Iterable<T> iterable(final Enumeration<?> e, Class<T> castType) {
return (new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
@Override
public boolean hasNext() {
return (e.hasMoreElements());
}
@SuppressWarnings("unchecked")
@Override
public T next() {
return ((T)e.nextElement());
}
@Override
public void remove() {
throw new NotImplementedException();
}
};
}
});
}
public static <T> T pop(Collection<T> items) {
T t = CollectionUtil.first(items);
if (t != null) {
boolean ret = items.remove(t);
assert (ret);
}
return (t);
}
/**
* Return an ordered array of the hash codes for the given items Any null
* item will have a null hash code
*/
public static int[] hashCode(Iterable<?> items) {
List<Integer> codes = new ArrayList<Integer>();
for (Object o : items) {
codes.add(o != null ? o.hashCode() : null);
}
return CollectionUtil.toIntArray(codes);
}
}