/*************************************************************************** * 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); } }