package edu.berkeley.nlp.util;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
/**
* @author Dan Klein
*/
public class CollectionUtils
{
public interface CollectionFactory<V>
{
Collection<V> newCollection();
}
public static <E extends Comparable<E>> List<E> sort(Collection<E> c)
{
List<E> list = new ArrayList<E>(c);
Collections.sort(list);
return list;
}
public static <E> boolean isSublistOf(List<E> bigger, List<E> smaller)
{
if (smaller.size() > bigger.size()) return false;
for (int start = 0; start + smaller.size() <= bigger.size(); ++start)
{
List<E> sublist = bigger.subList(start, start + smaller.size());
if (sublist.equals(bigger)) { return true; }
}
return false;
}
public static <E> List<E> sort(Collection<E> c, Comparator<E> r)
{
List<E> list = new ArrayList<E>(c);
Collections.sort(list, r);
return list;
}
public static <K, V> void addToValueSet(Map<K, Set<V>> map, K key, V value)
{
addToValueSet(map, key, value, new SetFactory.HashSetFactory<V>());
}
public static <K, V extends Comparable<V>> void addToValueSortedSet(Map<K, SortedSet<V>> map, K key, V value)
{
SortedSet<V> values = map.get(key);
if (values == null)
{
values = new TreeSet<V>();
map.put(key, values);
}
values.add(value);
}
public static <K, V> void addToValueSet(Map<K, Set<V>> map, K key, V value, SetFactory<V> mf)
{
Set<V> values = map.get(key);
if (values == null)
{
values = mf.buildSet();
map.put(key, values);
}
values.add(value);
}
public static <K, V, T> Map<V, T> addToValueMap(Map<K, Map<V, T>> map, K key, V value, T value2)
{
return addToValueMap(map, key, value, value2, new MapFactory.HashMapFactory<V, T>());
}
public static <K, V, T> Map<V, T> addToValueMap(Map<K, Map<V, T>> map, K key, V value, T value2, MapFactory<V, T> mf)
{
Map<V, T> values = map.get(key);
if (values == null)
{
values = mf.buildMap();
map.put(key, values);
}
values.put(value, value2);
return values;
}
public static <K, V> void addToValueList(Map<K, List<V>> map, K key, V value)
{
List<V> valueList = map.get(key);
if (valueList == null)
{
valueList = new ArrayList<V>();
map.put(key, valueList);
}
valueList.add(value);
}
public static <K, V> void addToValueCollection(Map<K, Collection<V>> map, K key, V value, CollectionFactory<V> cf)
{
Collection<V> valueList = map.get(key);
if (valueList == null)
{
valueList = cf.newCollection();
map.put(key, valueList);
}
valueList.add(value);
}
public static <K, V, C extends Collection<V>> void addToValueCollection(Map<K, C> map, K key, V value, Factory<C> fact)
{
C valueList = map.get(key);
if (valueList == null)
{
valueList = fact.newInstance();
map.put(key, valueList);
}
valueList.add(value);
}
public static <K, V> List<V> getValueList(Map<K, List<V>> map, K key)
{
List<V> valueList = map.get(key);
if (valueList == null) return Collections.emptyList();
return valueList;
}
public static <K, V> Set<V> getValueSet(Map<K, Set<V>> map, K key)
{
Set<V> valueSet = map.get(key);
if (valueSet == null) return Collections.emptySet();
return valueSet;
}
public static <T> List<T> makeList(T... args)
{
return new ArrayList<T>(Arrays.asList(args));
}
public static <T> Set<T> makeSet(T... args)
{
return new HashSet<T>(Arrays.asList(args));
}
public static <T> void quicksort(T[] array, Comparator<? super T> c)
{
quicksort(array, 0, array.length - 1, c);
}
public static <T> void quicksort(T[] array, int left0, int right0, Comparator<? super T> c)
{
int left, right;
T pivot, temp;
left = left0;
right = right0 + 1;
final int pivotIndex = (left0 + right0) / 2;
pivot = array[pivotIndex];
temp = array[left0];
array[left0] = pivot;
array[pivotIndex] = temp;
do
{
do
left++;
while (left <= right0 && c.compare(array[left], pivot) < 0);
do
right--;
while (c.compare(array[right], pivot) > 0);
if (left < right)
{
temp = array[left];
array[left] = array[right];
array[right] = temp;
}
} while (left <= right);
temp = array[left0];
array[left0] = array[right];
array[right] = temp;
if (left0 < right) quicksort(array, left0, right, c);
if (left < right0) quicksort(array, left, right0, c);
}
public static <S, T> Iterable<Pair<S, T>> getPairIterable(final Iterable<S> sIterable, final Iterable<T> tIterable)
{
return new Iterable<Pair<S, T>>()
{
public Iterator<Pair<S, T>> iterator()
{
class PairIterator implements Iterator<Pair<S, T>>
{
private Iterator<S> sIterator;
private Iterator<T> tIterator;
private PairIterator()
{
sIterator = sIterable.iterator();
tIterator = tIterable.iterator();
}
public boolean hasNext()
{
// TODO Auto-generated method stub
return sIterator.hasNext() && tIterator.hasNext();
}
public Pair<S, T> next()
{
// TODO Auto-generated method stub
return Pair.newPair(sIterator.next(), tIterator.next());
}
public void remove()
{
// TODO Auto-generated method stub
sIterator.remove();
tIterator.remove();
}
}
;
return new PairIterator();
}
};
}
public static <T> List<T> doubletonList(T t1, T t2)
{
return new DoubletonList(t1, t2);
}
public static class MutableSingletonSet<E> extends AbstractSet<E> implements Serializable
{
private final class MutableSingletonSetIterator implements Iterator<E>
{
private boolean hasNext = true;
public boolean hasNext()
{
return hasNext;
}
public E next()
{
if (hasNext)
{
hasNext = false;
return element;
}
throw new NoSuchElementException();
}
public void remove()
{
throw new UnsupportedOperationException();
}
public void reset()
{
hasNext = true;
}
}
// use serialVersionUID from JDK 1.2.2 for interoperability
private static final long serialVersionUID = 3193687207550431679L;
private E element;
private final MutableSingletonSetIterator iter;
public MutableSingletonSet(E o)
{
element = o;
this.iter = new MutableSingletonSetIterator();
}
public void set(E o)
{
element = o;
}
@Override
public Iterator<E> iterator()
{
iter.reset();
return iter;
}
@Override
public int size()
{
return 1;
}
@Override
public boolean contains(Object o)
{
return eq(o, element);
}
}
private static class DoubletonList<E> extends AbstractList<E> implements RandomAccess, Serializable
{
/**
*
*/
private static final long serialVersionUID = -8444118491195689776L;
private final E element1;
private final E element2;
DoubletonList(E e1, E e2)
{
element1 = e1;
element2 = e2;
}
@Override
public int size()
{
return 2;
}
@Override
public boolean contains(Object obj)
{
return eq(obj, element1) || eq(obj, element2);
}
@Override
public E get(int index)
{
if (index == 0) return element1;
if (index == 1) return element2;
throw new IndexOutOfBoundsException("Index: " + index + ", Size: 2");
}
}
private static boolean eq(Object o1, Object o2)
{
return (o1 == null ? o2 == null : o1.equals(o2));
}
public static <K, V, V2> Map<V, V2> getOrCreateMap(Map<K, Map<V, V2>> map, K key)
{
Map<V, V2> r = map.get(key);
if (r == null) map.put(key, r = new HashMap<V, V2>());
return r;
}
public static Map getMapFromString(String s, Class keyClass, Class valueClass, MapFactory mapFactory) throws ClassNotFoundException, NoSuchMethodException,
IllegalAccessException, InvocationTargetException, InstantiationException
{
Constructor keyC = keyClass.getConstructor(new Class[] { Class.forName("java.lang.String") });
Constructor valueC = valueClass.getConstructor(new Class[] { Class.forName("java.lang.String") });
if (s.charAt(0) != '{') throw new RuntimeException("");
s = s.substring(1); // get rid of first brace
String[] fields = s.split("\\s+");
Map m = mapFactory.buildMap();
// populate m
for (int i = 0; i < fields.length; i++)
{
// System.err.println("Parsing " + fields[i]);
fields[i] = fields[i].substring(0, fields[i].length() - 1); // get rid of following comma or brace
String[] a = fields[i].split("=");
Object key = keyC.newInstance(a[0]);
Object value;
if (a.length > 1)
{
value = valueC.newInstance(a[1]);
}
else
{
value = "";
}
m.put(key, value);
}
return m;
}
public static <T> List<T> concatenateLists(List<? extends T>... lst) {
List<T> finalList = new ArrayList<T>();
for (List<? extends T> ts : lst) {
finalList.addAll(ts);
}
return finalList;
}
public static <T> List<T> truncateList(List<T> lst, int maxTrainDocs) {
if (maxTrainDocs < lst.size()) {
return lst.subList(0,maxTrainDocs);
}
return lst;
}
/**
* Differs from Collections.shuffle by NOT being in place
* @param items
* @param rand
* @param <T>
* @return
*/
public static <T> List<T> shuffle(Collection<T> items, Random rand) {
List<T> shuffled = new ArrayList(items);
Collections.shuffle(shuffled,rand);
return shuffled;
}
}