| /* |
| * Copyright 2008 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package java.util; |
| |
| import java.io.Serializable; |
| |
| /** |
| * Utility methods that operate on collections. <a |
| * href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collections.html">[Sun |
| * docs]</a> |
| */ |
| public class Collections { |
| |
| private static final class EmptyList extends AbstractList implements |
| RandomAccess, Serializable { |
| @Override |
| public boolean contains(Object object) { |
| return false; |
| } |
| |
| @Override |
| public Object get(int location) { |
| throw new IndexOutOfBoundsException(); |
| } |
| |
| @Override |
| public int size() { |
| return 0; |
| } |
| } |
| |
| private static final class EmptySet extends AbstractSet implements |
| Serializable { |
| @Override |
| public boolean contains(Object object) { |
| return false; |
| } |
| |
| @Override |
| public Iterator iterator() { |
| return new Iterator() { |
| public boolean hasNext() { |
| return false; |
| } |
| |
| public Object next() { |
| throw new NoSuchElementException(); |
| } |
| |
| public void remove() { |
| throw new UnsupportedOperationException(); |
| } |
| }; |
| } |
| |
| @Override |
| public int size() { |
| return 0; |
| } |
| } |
| |
| private static final class EmptyMap extends AbstractMap implements |
| Serializable { |
| @Override |
| public boolean containsKey(Object key) { |
| return false; |
| } |
| |
| @Override |
| public boolean containsValue(Object value) { |
| return false; |
| } |
| |
| @Override |
| public Set entrySet() { |
| return EMPTY_SET; |
| } |
| |
| @Override |
| public Object get(Object key) { |
| return null; |
| } |
| |
| @Override |
| public Set keySet() { |
| return EMPTY_SET; |
| } |
| |
| @Override |
| public int size() { |
| return 0; |
| } |
| |
| @Override |
| public Collection values() { |
| return EMPTY_LIST; |
| } |
| } |
| |
| private static final class SingletonList<E> extends AbstractList<E> implements Serializable { |
| private E element; |
| |
| public SingletonList(E element) { |
| this.element = element; |
| } |
| |
| public boolean contains(Object item) { |
| return Utility.equalsWithNullCheck(element, item); |
| } |
| |
| public E get(int index) { |
| if (index == 0) { |
| return element; |
| } else { |
| throw new IndexOutOfBoundsException(); |
| } |
| } |
| |
| public int size() { |
| return 1; |
| } |
| } |
| |
| /* |
| * TODO: make the unmodifiable collections serializable. |
| */ |
| |
| static class UnmodifiableCollection<T> implements Collection<T> { |
| protected final Collection<? extends T> coll; |
| |
| public UnmodifiableCollection(Collection<? extends T> coll) { |
| this.coll = coll; |
| } |
| |
| public boolean add(T o) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean addAll(Collection<? extends T> c) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public void clear() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean contains(Object o) { |
| return coll.contains(o); |
| } |
| |
| public boolean containsAll(Collection<?> c) { |
| return coll.containsAll(c); |
| } |
| |
| public boolean isEmpty() { |
| return coll.isEmpty(); |
| } |
| |
| public Iterator<T> iterator() { |
| return new UnmodifiableCollectionIterator<T>(coll.iterator()); |
| } |
| |
| public boolean remove(Object o) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean removeAll(Collection<?> c) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean retainAll(Collection<?> c) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public int size() { |
| return coll.size(); |
| } |
| |
| public Object[] toArray() { |
| return coll.toArray(); |
| } |
| |
| public <E> E[] toArray(E[] a) { |
| return coll.toArray(a); |
| } |
| |
| public String toString() { |
| return coll.toString(); |
| } |
| } |
| |
| static class UnmodifiableList<T> extends UnmodifiableCollection<T> implements |
| List<T> { |
| private final List<? extends T> list; |
| |
| public UnmodifiableList(List<? extends T> list) { |
| super(list); |
| this.list = list; |
| } |
| |
| public void add(int index, T element) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean addAll(int index, Collection<? extends T> c) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| return list.equals(o); |
| } |
| |
| public T get(int index) { |
| return list.get(index); |
| } |
| |
| @Override |
| public int hashCode() { |
| return list.hashCode(); |
| } |
| |
| public int indexOf(Object o) { |
| return list.indexOf(o); |
| } |
| |
| @Override |
| public boolean isEmpty() { |
| return list.isEmpty(); |
| } |
| |
| public int lastIndexOf(Object o) { |
| return list.lastIndexOf(o); |
| } |
| |
| public ListIterator<T> listIterator() { |
| return listIterator(0); |
| } |
| |
| public ListIterator<T> listIterator(int from) { |
| return new UnmodifiableListIterator<T>(list.listIterator(from)); |
| } |
| |
| public T remove(int index) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public T set(int index, T element) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public List<T> subList(int fromIndex, int toIndex) { |
| return new UnmodifiableList<T>(list.subList(fromIndex, toIndex)); |
| } |
| } |
| |
| static class UnmodifiableMap<K, V> implements Map<K, V> { |
| |
| static class UnmodifiableEntrySet<K, V> extends |
| UnmodifiableSet<Map.Entry<K, V>> { |
| |
| private static class UnmodifiableEntry<K, V> implements Map.Entry<K, V> { |
| private Map.Entry<? extends K, ? extends V> entry; |
| |
| public UnmodifiableEntry(Map.Entry<? extends K, ? extends V> entry) { |
| this.entry = entry; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| return entry.equals(o); |
| } |
| |
| public K getKey() { |
| return entry.getKey(); |
| } |
| |
| public V getValue() { |
| return entry.getValue(); |
| } |
| |
| @Override |
| public int hashCode() { |
| return entry.hashCode(); |
| } |
| |
| public V setValue(V value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public String toString() { |
| return entry.toString(); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| public UnmodifiableEntrySet( |
| Set<? extends Map.Entry<? extends K, ? extends V>> s) { |
| super((Set<? extends Entry<K, V>>) s); |
| } |
| |
| @Override |
| public boolean contains(Object o) { |
| return coll.contains(o); |
| } |
| |
| @Override |
| public boolean containsAll(Collection<?> o) { |
| return coll.containsAll(o); |
| } |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| public Iterator<Map.Entry<K, V>> iterator() { |
| final Iterator<Map.Entry<K, V>> it = (Iterator<Entry<K, V>>) coll.iterator(); |
| return new Iterator<Map.Entry<K, V>>() { |
| public boolean hasNext() { |
| return it.hasNext(); |
| } |
| |
| public Map.Entry<K, V> next() { |
| return new UnmodifiableEntry<K, V>(it.next()); |
| } |
| |
| public void remove() { |
| throw new UnsupportedOperationException(); |
| } |
| }; |
| } |
| |
| @Override |
| public Object[] toArray() { |
| Object[] array = super.toArray(); |
| wrap(array, array.length); |
| return array; |
| } |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| public <T> T[] toArray(T[] a) { |
| Object[] result = super.toArray(a); |
| wrap(result, coll.size()); |
| return (T[]) result; |
| } |
| |
| /** |
| * Wrap an array of Map.Entries as UnmodifiableEntries. |
| * |
| * @param array array to wrap |
| * @param size number of entries to wrap |
| */ |
| @SuppressWarnings("unchecked") |
| private void wrap(Object[] array, int size) { |
| for (int i = 0; i < size; ++i) { |
| array[i] = new UnmodifiableEntry<K, V>((Map.Entry<K, V>) array[i]); |
| } |
| } |
| } |
| |
| private transient UnmodifiableSet<Map.Entry<K, V>> entrySet; |
| private transient UnmodifiableSet<K> keySet; |
| private final Map<? extends K, ? extends V> map; |
| private transient UnmodifiableCollection<V> values; |
| |
| public UnmodifiableMap(Map<? extends K, ? extends V> map) { |
| this.map = map; |
| } |
| |
| public void clear() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean containsKey(Object key) { |
| return map.containsKey(key); |
| } |
| |
| public boolean containsValue(Object val) { |
| return map.containsValue(val); |
| } |
| |
| public Set<Map.Entry<K, V>> entrySet() { |
| if (entrySet == null) { |
| entrySet = new UnmodifiableEntrySet<K, V>(map.entrySet()); |
| } |
| return entrySet; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| return map.equals(o); |
| } |
| |
| public V get(Object key) { |
| return map.get(key); |
| } |
| |
| @Override |
| public int hashCode() { |
| return map.hashCode(); |
| } |
| |
| public boolean isEmpty() { |
| return map.isEmpty(); |
| } |
| |
| public Set<K> keySet() { |
| if (keySet == null) { |
| keySet = new UnmodifiableSet<K>(map.keySet()); |
| } |
| return keySet; |
| } |
| |
| public V put(K key, V value) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public void putAll(Map<? extends K, ? extends V> t) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public V remove(Object key) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public int size() { |
| return map.size(); |
| } |
| |
| @Override |
| public String toString() { |
| return map.toString(); |
| } |
| |
| public Collection<V> values() { |
| if (values == null) { |
| values = new UnmodifiableCollection<V>(map.values()); |
| } |
| return values; |
| } |
| } |
| |
| static class UnmodifiableRandomAccessList<T> extends UnmodifiableList<T> |
| implements RandomAccess { |
| public UnmodifiableRandomAccessList(List<? extends T> list) { |
| super(list); |
| } |
| } |
| |
| static class UnmodifiableSet<T> extends UnmodifiableCollection<T> implements |
| Set<T> { |
| public UnmodifiableSet(Set<? extends T> set) { |
| super(set); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| return coll.equals(o); |
| } |
| |
| @Override |
| public int hashCode() { |
| return coll.hashCode(); |
| } |
| } |
| |
| static class UnmodifiableSortedMap<K, V> extends UnmodifiableMap<K, V> |
| implements SortedMap<K, V> { |
| |
| private SortedMap<K, ? extends V> sortedMap; |
| |
| public UnmodifiableSortedMap(SortedMap<K, ? extends V> sortedMap) { |
| super(sortedMap); |
| this.sortedMap = sortedMap; |
| } |
| |
| public Comparator<? super K> comparator() { |
| return sortedMap.comparator(); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| return sortedMap.equals(o); |
| } |
| |
| public K firstKey() { |
| return sortedMap.firstKey(); |
| } |
| |
| @Override |
| public int hashCode() { |
| return sortedMap.hashCode(); |
| } |
| |
| public SortedMap<K, V> headMap(K toKey) { |
| return new UnmodifiableSortedMap<K, V>(sortedMap.headMap(toKey)); |
| } |
| |
| public K lastKey() { |
| return sortedMap.lastKey(); |
| } |
| |
| public SortedMap<K, V> subMap(K fromKey, K toKey) { |
| return new UnmodifiableSortedMap<K, V>(sortedMap.subMap(fromKey, toKey)); |
| } |
| |
| public SortedMap<K, V> tailMap(K fromKey) { |
| return new UnmodifiableSortedMap<K, V>(sortedMap.tailMap(fromKey)); |
| } |
| } |
| |
| static class UnmodifiableSortedSet<E> extends UnmodifiableSet<E> implements |
| SortedSet<E> { |
| private SortedSet<E> sortedSet; |
| |
| @SuppressWarnings("unchecked") |
| public UnmodifiableSortedSet(SortedSet<? extends E> sortedSet) { |
| super(sortedSet); |
| this.sortedSet = (SortedSet<E>) sortedSet; |
| } |
| |
| public Comparator<? super E> comparator() { |
| return sortedSet.comparator(); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| return sortedSet.equals(o); |
| } |
| |
| public E first() { |
| return sortedSet.first(); |
| } |
| |
| @Override |
| public int hashCode() { |
| return sortedSet.hashCode(); |
| } |
| |
| public SortedSet<E> headSet(E toElement) { |
| return new UnmodifiableSortedSet<E>(sortedSet.headSet(toElement)); |
| } |
| |
| public E last() { |
| return sortedSet.last(); |
| } |
| |
| public SortedSet<E> subSet(E fromElement, E toElement) { |
| return new UnmodifiableSortedSet<E>(sortedSet.subSet(fromElement, |
| toElement)); |
| } |
| |
| public SortedSet<E> tailSet(E fromElement) { |
| return new UnmodifiableSortedSet<E>(sortedSet.tailSet(fromElement)); |
| } |
| } |
| |
| private static class UnmodifiableCollectionIterator<T> implements Iterator<T> { |
| private final Iterator<? extends T> it; |
| |
| private UnmodifiableCollectionIterator(Iterator<? extends T> it) { |
| this.it = it; |
| } |
| |
| public boolean hasNext() { |
| return it.hasNext(); |
| } |
| |
| public T next() { |
| return it.next(); |
| } |
| |
| public void remove() { |
| throw new UnsupportedOperationException(); |
| } |
| } |
| |
| private static class UnmodifiableListIterator<T> extends |
| UnmodifiableCollectionIterator<T> implements ListIterator<T> { |
| private final ListIterator<? extends T> lit; |
| |
| private UnmodifiableListIterator(ListIterator<? extends T> lit) { |
| super(lit); |
| this.lit = lit; |
| } |
| |
| public void add(T o) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public boolean hasPrevious() { |
| return lit.hasPrevious(); |
| } |
| |
| public int nextIndex() { |
| return lit.nextIndex(); |
| } |
| |
| public T previous() { |
| return lit.previous(); |
| } |
| |
| public int previousIndex() { |
| return lit.previousIndex(); |
| } |
| |
| public void set(T o) { |
| throw new UnsupportedOperationException(); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static final List EMPTY_LIST = new EmptyList(); |
| |
| @SuppressWarnings("unchecked") |
| public static final Map EMPTY_MAP = new EmptyMap(); |
| |
| @SuppressWarnings("unchecked") |
| public static final Set EMPTY_SET = new EmptySet(); |
| |
| private static Comparator<Comparable<Object>> reverseComparator = new Comparator<Comparable<Object>>() { |
| public int compare(Comparable<Object> o1, Comparable<Object> o2) { |
| return o2.compareTo(o1); |
| } |
| }; |
| |
| public static <T> boolean addAll(Collection<? super T> c, T... a) { |
| boolean result = false; |
| for (T e : a) { |
| result |= c.add(e); |
| } |
| return result; |
| } |
| |
| /** |
| * Perform a binary search on a sorted List, using natural ordering. |
| * |
| * <p> |
| * Note: The GWT implementation differs from the JDK implementation in that it |
| * does not do an iterator-based binary search for Lists that do not implement |
| * RandomAccess. |
| * </p> |
| * |
| * @param sortedList object array to search |
| * @param key value to search for |
| * @return the index of an element with a matching value, or a negative number |
| * which is the index of the next larger value (or just past the end |
| * of the array if the searched value is larger than all elements in |
| * the array) minus 1 (to ensure error returns are negative) |
| * @throws ClassCastException if <code>key</code> is not comparable to |
| * <code>sortedList</code>'s elements. |
| */ |
| public static <T> int binarySearch( |
| final List<? extends Comparable<? super T>> sortedList, final T key) { |
| return binarySearch(sortedList, key, null); |
| } |
| |
| /* |
| * These methods are commented out because they cannot currently be |
| * implemented in GWT. The signatures are included in case that changes. |
| */ |
| // public static <E> Collection<E> checkedCollection(Collection<E> c, Class<E> |
| // type) { |
| // // FUTURE: implement |
| // return null; |
| // } |
| // |
| // static <E> List<E> checkedList(List<E> list, Class<E> type) { |
| // // FUTURE: implement |
| // return null; |
| // } |
| // |
| // public static <K,V> Map<K,V> checkedMap(Map<K,V> list, Class<K> keyType, |
| // Class<V> valueType) { |
| // // FUTURE: implement |
| // return null; |
| // } |
| // |
| // public static <E> Set<E> checkedSet(Set<E> list, Class<E> type) { |
| // // FUTURE: implement |
| // return null; |
| // } |
| // |
| // public static <K,V> SortedMap<K,V> checkedSortedMap(SortedMap<K,V> m, |
| // Class<K> keyType, Class<V> valueType) { |
| // // FUTURE: implement |
| // return null; |
| // } |
| // |
| // public static <E> SortedSet<E> checkedSortedSet(SortedSet<E> list, Class<E> |
| // type) { |
| // // FUTURE: implement |
| // return null; |
| // } |
| /** |
| * Perform a binary search on a sorted List, using a user-specified comparison |
| * function. |
| * |
| * <p> |
| * Note: The GWT implementation differs from the JDK implementation in that it |
| * does not do an iterator-based binary search for Lists that do not implement |
| * RandomAccess. |
| * </p> |
| * |
| * @param sortedList List to search |
| * @param key value to search for |
| * @param comparator comparision function, <code>null</code> indicates |
| * <i>natural ordering</i> should be used. |
| * @return the index of an element with a matching value, or a negative number |
| * which is the index of the next larger value (or just past the end |
| * of the array if the searched value is larger than all elements in |
| * the array) minus 1 (to ensure error returns are negative) |
| * @throws ClassCastException if <code>key</code> and |
| * <code>sortedList</code>'s elements cannot be compared by |
| * <code>comparator</code>. |
| */ |
| public static <T> int binarySearch(final List<? extends T> sortedList, |
| final T key, Comparator<? super T> comparator) { |
| /* |
| * TODO: This doesn't implement the "iterator-based binary search" described |
| * in the JDK docs for non-RandomAccess Lists. Until GWT provides a |
| * LinkedList, this shouldn't be an issue. |
| */ |
| if (comparator == null) { |
| comparator = Comparators.natural(); |
| } |
| int low = 0; |
| int high = sortedList.size() - 1; |
| |
| while (low <= high) { |
| final int mid = low + ((high - low) >> 1); |
| final T midVal = sortedList.get(mid); |
| final int compareResult = comparator.compare(midVal, key); |
| |
| if (compareResult < 0) { |
| low = mid + 1; |
| } else if (compareResult > 0) { |
| high = mid - 1; |
| } else { |
| // key found |
| return mid; |
| } |
| } |
| // key not found. |
| return -low - 1; |
| } |
| |
| public static <T> void copy(List<? super T> dest, List<? extends T> src) { |
| // TODO(jat): optimize |
| dest.addAll(src); |
| } |
| |
| public static boolean disjoint(Collection<?> c1, Collection<?> c2) { |
| Collection<?> iterating = c1; |
| Collection<?> testing = c2; |
| |
| // See if one of these objects possibly implements a fast contains. |
| if ((c1 instanceof Set) && !(c2 instanceof Set)) { |
| iterating = c2; |
| testing = c1; |
| } |
| |
| for (Object o : iterating) { |
| if (testing.contains(o)) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| @SuppressWarnings(value = {"unchecked", "cast"}) |
| public static <T> List<T> emptyList() { |
| return (List<T>) EMPTY_LIST; |
| } |
| |
| @SuppressWarnings(value = {"unchecked", "cast"}) |
| public static <K, V> Map<K, V> emptyMap() { |
| return (Map<K, V>) EMPTY_MAP; |
| } |
| |
| @SuppressWarnings(value = {"unchecked", "cast"}) |
| public static <T> Set<T> emptySet() { |
| return (Set<T>) EMPTY_SET; |
| } |
| |
| public static <T> Enumeration<T> enumeration(Collection<T> c) { |
| final Iterator<T> it = c.iterator(); |
| return new Enumeration<T>() { |
| public boolean hasMoreElements() { |
| return it.hasNext(); |
| } |
| |
| public T nextElement() { |
| return it.next(); |
| } |
| }; |
| } |
| |
| public static <T> void fill(List<? super T> list, T obj) { |
| for (ListIterator<? super T> it = list.listIterator(); it.hasNext();) { |
| it.next(); |
| it.set(obj); |
| } |
| } |
| |
| public static int frequency(Collection<?> c, Object o) { |
| int count = 0; |
| for (Object e : c) { |
| if (o == null ? e == null : o.equals(e)) { |
| ++count; |
| } |
| } |
| return count; |
| } |
| |
| public static <T> ArrayList<T> list(Enumeration<T> e) { |
| ArrayList<T> arrayList = new ArrayList<T>(); |
| while (e.hasMoreElements()) { |
| arrayList.add(e.nextElement()); |
| } |
| return arrayList; |
| } |
| |
| public static <T extends Object & Comparable<? super T>> T max( |
| Collection<? extends T> coll) { |
| return max(coll, null); |
| } |
| |
| public static <T> T max(Collection<? extends T> coll, |
| Comparator<? super T> comp) { |
| |
| if (comp == null) { |
| comp = Comparators.natural(); |
| } |
| |
| Iterator<? extends T> it = coll.iterator(); |
| |
| // Will throw NoSuchElementException if coll is empty. |
| T max = it.next(); |
| |
| while (it.hasNext()) { |
| T t = it.next(); |
| if (comp.compare(t, max) > 0) { |
| max = t; |
| } |
| } |
| |
| return max; |
| } |
| |
| public static <T extends Object & Comparable<? super T>> T min( |
| Collection<? extends T> coll) { |
| return min(coll, null); |
| } |
| |
| public static <T> T min(Collection<? extends T> coll, |
| Comparator<? super T> comp) { |
| return max(coll, reverseOrder(comp)); |
| } |
| |
| public static <T> List<T> nCopies(int n, T o) { |
| ArrayList<T> list = new ArrayList<T>(); |
| for (int i = 0; i < n; ++i) { |
| list.add(o); |
| } |
| return unmodifiableList(list); |
| } |
| |
| public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal) { |
| boolean modified = false; |
| for (ListIterator<T> it = list.listIterator(); it.hasNext();) { |
| T t = it.next(); |
| if (t == null ? oldVal == null : t.equals(oldVal)) { |
| it.set(newVal); |
| modified = true; |
| } |
| } |
| return modified; |
| } |
| |
| public static <T> void reverse(List<T> l) { |
| if (l instanceof RandomAccess) { |
| for (int iFront = 0, iBack = l.size() - 1; iFront < iBack; ++iFront, --iBack) { |
| Collections.swap(l, iFront, iBack); |
| } |
| } else { |
| ListIterator<T> head = l.listIterator(); |
| ListIterator<T> tail = l.listIterator(l.size()); |
| while (head.nextIndex() < tail.previousIndex()) { |
| T headElem = head.next(); |
| T tailElem = tail.previous(); |
| head.set(tailElem); |
| tail.set(headElem); |
| } |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static <T> Comparator<T> reverseOrder() { |
| return (Comparator<T>) reverseComparator; |
| } |
| |
| public static <T> Comparator<T> reverseOrder(final Comparator<T> cmp) { |
| if (cmp == null) { |
| return reverseOrder(); |
| } |
| return new Comparator<T>() { |
| public int compare(T t1, T t2) { |
| return cmp.compare(t2, t1); |
| } |
| }; |
| } |
| |
| public static <T> Set<T> singleton(T o) { |
| HashSet<T> set = new HashSet<T>(1); |
| set.add(o); |
| return unmodifiableSet(set); |
| } |
| |
| // TODO(tobyr) Is it worth creating custom singleton sets, lists, and maps? |
| // More efficient at runtime, but more code bloat to download |
| |
| public static <T> List<T> singletonList(T o) { |
| return new SingletonList<T>(o); |
| } |
| |
| public static <K, V> Map<K, V> singletonMap(K key, V value) { |
| Map<K, V> map = new HashMap<K, V>(1); |
| map.put(key, value); |
| return unmodifiableMap(map); |
| } |
| |
| public static <T> void sort(List<T> target) { |
| Object[] x = target.toArray(); |
| Arrays.sort(x); |
| replaceContents(target, x); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public static <T> void sort(List<T> target, Comparator<? super T> c) { |
| Object[] x = target.toArray(); |
| Arrays.sort(x, (Comparator<Object>) c); |
| replaceContents(target, x); |
| } |
| |
| public static void swap(List<?> list, int i, int j) { |
| swapImpl(list, i, j); |
| } |
| |
| public static <T> Collection<T> unmodifiableCollection( |
| final Collection<? extends T> coll) { |
| return new UnmodifiableCollection<T>(coll); |
| } |
| |
| public static <T> List<T> unmodifiableList(List<? extends T> list) { |
| return (list instanceof RandomAccess) |
| ? new UnmodifiableRandomAccessList<T>(list) : new UnmodifiableList<T>( |
| list); |
| } |
| |
| public static <K, V> Map<K, V> unmodifiableMap( |
| final Map<? extends K, ? extends V> map) { |
| return new UnmodifiableMap<K, V>(map); |
| } |
| |
| public static <T> Set<T> unmodifiableSet(Set<? extends T> set) { |
| return new UnmodifiableSet<T>(set); |
| } |
| |
| public static <K, V> SortedMap<K, V> unmodifiableSortedMap( |
| SortedMap<K, ? extends V> map) { |
| return new UnmodifiableSortedMap<K, V>(map); |
| } |
| |
| public static <T> SortedSet<T> unmodifiableSortedSet( |
| SortedSet<? extends T> set) { |
| return new UnmodifiableSortedSet<T>(set); |
| } |
| |
| /** |
| * Replace contents of a list from an array. |
| * |
| * @param <T> element type |
| * @param target list to replace contents from an array |
| * @param x an Object array which can contain only T instances |
| */ |
| @SuppressWarnings("unchecked") |
| private static <T> void replaceContents(List<T> target, Object[] x) { |
| int size = target.size(); |
| assert (x.length == size); |
| for (int i = 0; i < size; i++) { |
| target.set(i, (T) x[i]); |
| } |
| } |
| |
| private static <T> void swapImpl(List<T> list, int i, int j) { |
| T t = list.get(i); |
| list.set(i, list.get(j)); |
| list.set(j, t); |
| } |
| } |