All Downloads are FREE. Search and download functionalities are using the official Maven repository.

panda.lang.Collections Maven / Gradle / Ivy

package panda.lang;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Deque;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Queue;
import java.util.Random;
import java.util.RandomAccess;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;

import panda.lang.collection.CaseInsensitiveMap;
import panda.lang.collection.CaseInsensitiveSet;
import panda.lang.collection.SafeMap;

@SuppressWarnings({ "rawtypes", "unchecked" })
public abstract class Collections {
	/** Constant to avoid repeated object creation */
	private static Integer INTEGER_ONE = new Integer(1);

	/**
	 * Clear collection
	 * @param c collection
	 */
	public static void clear(Collection c) {
		if (c != null) {
			c.clear();
		}
	}

	/**
	 * Clear map
	 * @param m map
	 */
	public static void clear(Map m) {
		if (m != null) {
			m.clear();
		}
	}
	
	/**
	 * Returns a {@link Collection} containing the union of the given {@link Collection}s.
	 * 

* The cardinality of each element in the returned {@link Collection} will be equal to the * maximum of the cardinality of that element in the two given {@link Collection}s. * * @param a the first collection, must not be null * @param b the second collection, must not be null * @return the union of the two collections * @see Collection#addAll */ public static Collection union(final Collection a, final Collection b) { ArrayList list = new ArrayList(); Map mapa = getCardinalityMap(a); Map mapb = getCardinalityMap(b); Set elts = new HashSet(a); elts.addAll(b); Iterator it = elts.iterator(); while (it.hasNext()) { Object obj = it.next(); for (int i = 0, m = Math.max(getFreq(obj, mapa), getFreq(obj, mapb)); i < m; i++) { list.add(obj); } } return list; } /** * Returns a {@link Collection} containing the intersection of the given {@link Collection}s. *

* The cardinality of each element in the returned {@link Collection} will be equal to the * minimum of the cardinality of that element in the two given {@link Collection}s. * * @param a the first collection, must not be null * @param b the second collection, must not be null * @return the intersection of the two collections * @see Collection#retainAll * @see #containsAny */ public static Collection intersection(final Collection a, final Collection b) { ArrayList list = new ArrayList(); Map mapa = getCardinalityMap(a); Map mapb = getCardinalityMap(b); Set elts = new HashSet(a); elts.addAll(b); Iterator it = elts.iterator(); while (it.hasNext()) { Object obj = it.next(); for (int i = 0, m = Math.min(getFreq(obj, mapa), getFreq(obj, mapb)); i < m; i++) { list.add(obj); } } return list; } /** * Returns a {@link Collection} containing the exclusive disjunction (symmetric difference) of * the given {@link Collection}s. *

* The cardinality of each element e in the returned {@link Collection} will be equal to * max(cardinality(e,a),cardinality(e,b)) - min(cardinality(e,a),cardinality(e,b)). *

* This is equivalent to * {@link #subtract subtract}({@link #union union(a,b)},{@link #intersection intersection(a,b)}) * or * {@link #union union}({@link #subtract subtract(a,b)},{@link #subtract subtract(b,a)}). * * @param a the first collection, must not be null * @param b the second collection, must not be null * @return the symmetric difference of the two collections */ public static Collection disjunction(final Collection a, final Collection b) { ArrayList list = new ArrayList(); Map mapa = getCardinalityMap(a); Map mapb = getCardinalityMap(b); Set elts = new HashSet(a); elts.addAll(b); Iterator it = elts.iterator(); while (it.hasNext()) { Object obj = it.next(); for (int i = 0, m = ((Math.max(getFreq(obj, mapa), getFreq(obj, mapb))) - (Math.min( getFreq(obj, mapa), getFreq(obj, mapb)))); i < m; i++) { list.add(obj); } } return list; } /** * Returns a new {@link Collection} containing a - b. The cardinality of * each element e in the returned {@link Collection} will be the cardinality of e * in a minus the cardinality of e in b, or zero, whichever is greater. * * @param a the collection to subtract from, must not be null * @param b the collection to subtract, must not be null * @return a new collection with the results * @see Collection#removeAll */ public static Collection subtract(final Collection a, final Collection b) { ArrayList list = new ArrayList(a); for (Iterator it = b.iterator(); it.hasNext();) { list.remove(it.next()); } return list; } /** * Returns a {@link Map} mapping each unique element in the given {@link Collection} to an * {@link Integer} representing the number of occurrences of that element in the * {@link Collection}. *

* Only those elements present in the collection will appear as keys in the map. * * @param coll the collection to get the cardinality map for, must not be null * @return the populated cardinality map */ public static Map getCardinalityMap(final Collection coll) { Map count = new HashMap(); for (Iterator it = coll.iterator(); it.hasNext();) { T obj = it.next(); Integer c = (Integer)(count.get(obj)); if (c == null) { count.put(obj, INTEGER_ONE); } else { count.put(obj, new Integer(c.intValue() + 1)); } } return count; } /** * Returns true iff a is a sub-collection of b, that is, iff the * cardinality of e in a is less than or equal to the cardinality of e in * b, for each element e in a. * * @param a the first (sub?) collection, must not be null * @param b the second (super?) collection, must not be null * @return true iff a is a sub-collection of b * @see #isProperSubCollection * @see Collection#containsAll */ public static boolean isSubCollection(final Collection a, final Collection b) { Map mapa = getCardinalityMap(a); Map mapb = getCardinalityMap(b); Iterator it = a.iterator(); while (it.hasNext()) { Object obj = it.next(); if (getFreq(obj, mapa) > getFreq(obj, mapb)) { return false; } } return true; } /** * Returns true iff a is a proper sub-collection of b, that is, * iff the cardinality of e in a is less than or equal to the cardinality of * e in b, for each element e in a, and there is at least one * element f such that the cardinality of f in b is strictly greater than * the cardinality of f in a. *

* The implementation assumes *

    *
  • a.size() and b.size() represent the total cardinality of * a and b, resp.
  • *
  • a.size() < Integer.MAXVALUE
  • *
* * @param a the first (sub?) collection, must not be null * @param b the second (super?) collection, must not be null * @return true iff a is a proper sub-collection of b * @see #isSubCollection * @see Collection#containsAll */ public static boolean isProperSubCollection(final Collection a, final Collection b) { return (a.size() < b.size()) && Collections.isSubCollection(a, b); } /** * Returns true iff the given {@link Collection}s contain exactly the same elements * with exactly the same cardinalities. *

* That is, iff the cardinality of e in a is equal to the cardinality of e * in b, for each element e in a or b. * * @param a the first collection, must not be null * @param b the second collection, must not be null * @return true iff the collections contain the same elements with the same * cardinalities. */ public static boolean isEqualCollection(final Collection a, final Collection b) { if (a.size() != b.size()) { return false; } else { Map mapa = getCardinalityMap(a); Map mapb = getCardinalityMap(b); if (mapa.size() != mapb.size()) { return false; } else { Iterator it = mapa.keySet().iterator(); while (it.hasNext()) { Object obj = it.next(); if (getFreq(obj, mapa) != getFreq(obj, mapb)) { return false; } } return true; } } } /** * Returns the number of occurrences of obj in coll. * * @param obj the object to find the cardinality of * @param coll the collection to search * @return the the number of occurrences of obj in coll */ public static int cardinality(Object obj, final Collection coll) { if (coll instanceof Set) { return (coll.contains(obj) ? 1 : 0); } int count = 0; if (obj == null) { for (Iterator it = coll.iterator(); it.hasNext();) { if (it.next() == null) { count++; } } } else { for (Iterator it = coll.iterator(); it.hasNext();) { if (obj.equals(it.next())) { count++; } } } return count; } // ----------------------------------------------------------------------- /** * Adds an element to the collection unless the element is null. * * @param collection the collection to add to, must not be null * @param object the object to add, if null it will not be added * @return true if the collection changed * @throws NullPointerException if the collection is null */ public static boolean addIgnoreNull(Collection collection, Object object) { return (object == null ? false : collection.add(object)); } /** * Adds all elements in the iteration to the given collection. * * @param collection the collection to add to, must not be null * @param iterator the iterator of elements to add, must not be null * @throws NullPointerException if the collection or iterator is null */ public static void addAll(Collection collection, Iterator iterator) { while (iterator.hasNext()) { collection.add(iterator.next()); } } /** * Adds all elements in the enumeration to the given collection. * * @param collection the collection to add to, must not be null * @param enumeration the enumeration of elements to add, must not be null * @throws NullPointerException if the collection or enumeration is null */ public static void addAll(Collection collection, Enumeration enumeration) { while (enumeration.hasMoreElements()) { collection.add(enumeration.nextElement()); } } public static void insert(List list, int index, Object value) { if (index < 0 || index >= list.size()) { throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + list.size()); } list.add(null); for (int i = list.size() - 1; i > index; i--) { list.set(i, list.get(i - 1)); } list.set(index, value); } /** * return first key of map * @param map the map * @return first key */ public static K firstKey(Map map) { if (isEmpty(map)) { return null; } return map.keySet().iterator().next(); } /** * return first value of map * @param map the map * @return first value */ public static V firstValue(Map map) { if (isEmpty(map)) { return null; } return map.values().iterator().next(); } /** * return first entry of map * @param map the map * @return first entry */ public static Entry firstEntry(Map map) { if (isEmpty(map)) { return null; } return map.entrySet().iterator().next(); } // ----------------------------------------------------------------------- /** * Null-safe check if the specified collection is empty. *

* Null returns true. * * @param coll the collection to check, may be null * @return true if empty or null */ public static boolean isEmpty(Collection coll) { return (coll == null || coll.isEmpty()); } /** * Null-safe check if the specified collection is not empty. *

* Null returns false. * * @param coll the collection to check, may be null * @return true if non-null and non-empty */ public static boolean isNotEmpty(Collection coll) { return !Collections.isEmpty(coll); } // ----------------------------------------------------------------------- private static final int getFreq(final Object obj, final Map freqMap) { Integer count = (Integer)freqMap.get(obj); if (count != null) { return count.intValue(); } return 0; } // ----------------------------------------------------------------------- /** * Returns a collection containing all the elements in collection that are also in * retain. The cardinality of an element e in the returned collection * is the same as the cardinality of e in collection unless * retain does not contain e, in which case the cardinality is zero. * This method is useful if you do not wish to modify the collection c and thus * cannot call c.retainAll(retain);. * * @param collection the collection whose contents are the target of the #retailAll operation * @param retain the collection containing the elements to be retained in the returned * collection * @return a Collection containing all the elements of collection that * occur at least once in retain. * @throws NullPointerException if either parameter is null */ public static Collection retainAll(Collection collection, Collection retain) { List list = new ArrayList(Math.min(collection.size(), retain.size())); for (Iterator iter = collection.iterator(); iter.hasNext();) { Object obj = iter.next(); if (retain.contains(obj)) { list.add(obj); } } return list; } /** * Removes the elements in remove from collection. That is, this * method returns a collection containing all the elements in c that are not in * remove. The cardinality of an element e in the returned collection * is the same as the cardinality of e in collection unless * remove contains e, in which case the cardinality is zero. This * method is useful if you do not wish to modify the collection c and thus cannot * call collection.removeAll(remove);. * * @param collection the collection from which items are removed (in the returned collection) * @param remove the items to be removed from the returned collection * @return a Collection containing all the elements of collection * except any elements that also occur in remove. * @throws NullPointerException if either parameter is null */ public static Collection removeAll(Collection collection, Collection remove) { List list = new ArrayList(); for (Iterator iter = collection.iterator(); iter.hasNext();) { Object obj = iter.next(); if (remove.contains(obj) == false) { list.add(obj); } } return list; } /** * @param set the Set to wrap * @return a case insensitive set */ public static Set caseInsensitiveSet(Collection set) { return new CaseInsensitiveSet(set); } /** * @param map the Map to wrap * @return a case insensitive map */ public static Map caseInsensitiveMap(Map map) { return new CaseInsensitiveMap(map); } /** * @param map the Map to wrap * @return a safe map */ public static Map safeMap(Map map) { return new SafeMap(map); } /** * Return true if the supplied Map is null or empty. Otherwise, return * false. * * @param map the Map to check * @return whether the given Map is empty */ public static boolean isEmpty(Map map) { return (map == null || map.isEmpty()); } /** * Return true if the supplied Map is not null or empty. Otherwise, * return false. * * @param map the Map to check * @return whether the given Map is not empty */ public static boolean isNotEmpty(Map map) { return (map != null && !map.isEmpty()); } /** * Remove null elements in the collection. * * @param collection the collection to get the input from, may be null */ public static void removeNull(Collection collection) { if (collection != null) { for (Iterator it = collection.iterator(); it.hasNext();) { if (it.next() == null) { it.remove(); } } } } /** * Remove null elements in the map. * * @param map the map to get the input from, may be null */ public static void removeNull(Map map) { if (map != null) { for (Iterator it = map.entrySet().iterator(); it.hasNext();) { if (((Entry)it.next()).getValue() == null) { it.remove(); } } } } /** * Remove null elements in the collection. * * @param collection the collection to get the input from, may be null * @return null elements removed collection */ public static Collection copyNotNull(Collection collection) { if (collection == null) { return null; } Collection nc = Classes.born(collection.getClass()); for (Iterator it = collection.iterator(); it.hasNext();) { Object o = it.next(); if (o != null) { nc.add(o); } } return nc; } /** * Merge the given array into the given Collection. * * @param array the array to merge (may be null) * @param collection the target Collection to merge the array into */ public static void mergeArrayIntoCollection(Object array, Collection collection) { if (collection == null) { throw new IllegalArgumentException("Collection must not be null"); } Object[] arr = Arrays.toObjectArray(array); for (int i = 0; i < arr.length; i++) { collection.add(arr[i]); } } /** * Merge the given Properties instance into the given Map, copying all properties (key-value * pairs) over. *

* Uses Properties.propertyNames() to even catch default properties linked into the * original Properties instance. * * @param props the Properties instance to merge (may be null) * @param map the target Map to merge the properties into */ public static void mergePropertiesIntoMap(Properties props, Map map) { if (map == null) { throw new IllegalArgumentException("Map must not be null"); } if (props != null) { for (Enumeration en = props.propertyNames(); en.hasMoreElements();) { String key = (String)en.nextElement(); map.put(key, props.getProperty(key)); } } } /** * Check whether the given Iterator contains the given element. * * @param iterator the Iterator to check * @param element the element to look for * @return true if found, false else */ public static boolean contains(Iterator iterator, Object element) { if (iterator != null) { while (iterator.hasNext()) { Object candidate = iterator.next(); if (Objects.nullSafeEquals(candidate, element)) { return true; } } } return false; } /** * Returns true if this map contains a mapping for the specified key. More formally, * returns true if and only if this map contains a mapping for a key k such * that (key==null ? k==null : key.equals(k)). (There can be at most one such mapping.) * * @param map the map * @param key key whose presence in this map is to be tested * @return true if this map contains a mapping for the specified key * @throws ClassCastException if the key is of an inappropriate type for this map * (optional) * @throws NullPointerException if the specified key is null and this map does not permit null * keys (optional) */ public static boolean containsKey(Map map, Object key) { if (map != null) { return map.containsKey(key); } return false; } /** * Check whether the given Iterator contains the given element. * * @param source the source collection * @param element the element to look for * @return true if found, false else */ public static boolean contains(Collection source, Object element) { if (source != null) { return source.contains(element); } return false; } /** * Check whether the given Enumeration contains the given element. * * @param enumeration the Enumeration to check * @param element the element to look for * @return true if found, false else */ public static boolean contains(Enumeration enumeration, Object element) { if (enumeration != null) { while (enumeration.hasMoreElements()) { Object candidate = enumeration.nextElement(); if (Objects.nullSafeEquals(candidate, element)) { return true; } } } return false; } /** * Check whether the given Collection contains the given element instance. *

* Enforces the given instance to be present, rather than returning true for an * equal element as well. * * @param collection the Collection to check * @param element the element to look for * @return true if found, false else */ public static boolean containsInstance(Collection collection, Object element) { if (collection != null) { for (Iterator it = collection.iterator(); it.hasNext();) { Object candidate = it.next(); if (candidate == element) { return true; } } } return false; } /** * Return true if any element in 'candidates' is contained in ' * source'; otherwise returns false. * * @param source the source Collection * @param candidates the candidates to search for * @return whether any of the candidates has been found */ public static boolean containsAny(Collection source, Collection candidates) { if (isEmpty(source) || isEmpty(candidates)) { return false; } for (Iterator it = candidates.iterator(); it.hasNext();) { if (source.contains(it.next())) { return true; } } return false; } /** * Return the first element in 'candidates' that is contained in ' * source'. If no element in 'candidates' is present in ' * source' returns null. Iteration order is {@link Collection} * implementation specific. * * @param source the source Collection * @param candidates the candidates to search for * @return the first present object, or null if not found */ public static Object findFirstMatch(Collection source, Collection candidates) { if (isEmpty(source) || isEmpty(candidates)) { return null; } for (Iterator it = candidates.iterator(); it.hasNext();) { Object candidate = it.next(); if (source.contains(candidate)) { return candidate; } } return null; } /** * Find a single value of the given type in the given Collection. * * @param collection the Collection to search * @param type the type to look for * @return a value of the given type found if there is a clear match, or null if * none or more than one such value found */ public static Object findValueOfType(Collection collection, Class type) { if (isEmpty(collection)) { return null; } Object value = null; for (Iterator it = collection.iterator(); it.hasNext();) { Object obj = it.next(); if (type == null || type.isInstance(obj)) { if (value != null) { // More than one value found... no clear single value. return null; } value = obj; } } return value; } /** * Find a single value of one of the given types in the given Collection: searching the * Collection for a value of the first type, then searching for a value of the second type, etc. * * @param collection the collection to search * @param types the types to look for, in prioritized order * @return a value of one of the given types found if there is a clear match, or * null if none or more than one such value found */ public static Object findValueOfType(Collection collection, Class[] types) { if (isEmpty(collection) || Arrays.isEmpty(types)) { return null; } for (int i = 0; i < types.length; i++) { Object value = findValueOfType(collection, types[i]); if (value != null) { return value; } } return null; } /** * Determine whether the given Collection only contains a single unique object. * * @param collection the Collection to check * @return true if the collection contains a single reference or multiple * references to the same instance, false else */ public static boolean hasUniqueObject(Collection collection) { if (isEmpty(collection)) { return false; } boolean hasCandidate = false; Object candidate = null; for (Iterator it = collection.iterator(); it.hasNext();) { Object elem = it.next(); if (!hasCandidate) { hasCandidate = true; candidate = elem; } else if (candidate != elem) { return false; } } return true; } //-------------------------------------------------------- // @see java.util.Collections /** * Sorts the specified list into ascending order, according to the natural ordering of * its elements. All elements in the list must implement the Comparable interface. * Furthermore, all elements in the list must be mutually comparable (that is, * e1.compareTo(e2) must not throw a ClassCastException for any elements * e1 and e2 in the list). *

* This sort is guaranteed to be stable: equal elements will not be reordered as a result * of the sort. *

* The specified list must be modifiable, but need not be resizable. *

* The sorting algorithm is a modified mergesort (in which the merge is omitted if the highest * element in the low sublist is less than the lowest element in the high sublist). This * algorithm offers guaranteed n log(n) performance. This implementation dumps the specified * list into an array, sorts the array, and iterates over the list resetting each element from * the corresponding position in the array. This avoids the n2 log(n) performance * that would result from attempting to sort a linked list in place. * * @param list the list to be sorted. * @throws ClassCastException if the list contains elements that are not mutually * comparable (for example, strings and integers). * @throws UnsupportedOperationException if the specified list's list-iterator does not support * the set operation. * @see Comparable */ public static > void sort(List list) { java.util.Collections.sort(list); } /** * Sorts the specified list according to the order induced by the specified comparator. All * elements in the list must be mutually comparable using the specified comparator (that * is, c.compare(e1, e2) must not throw a ClassCastException for any elements * e1 and e2 in the list). *

* This sort is guaranteed to be stable: equal elements will not be reordered as a result * of the sort. *

* The sorting algorithm is a modified mergesort (in which the merge is omitted if the highest * element in the low sublist is less than the lowest element in the high sublist). This * algorithm offers guaranteed n log(n) performance. The specified list must be modifiable, but * need not be resizable. This implementation dumps the specified list into an array, sorts the * array, and iterates over the list resetting each element from the corresponding position in * the array. This avoids the n2 log(n) performance that would result from attempting * to sort a linked list in place. * * @param list the list to be sorted. * @param c the comparator to determine the order of the list. A null value indicates * that the elements' natural ordering should be used. * @throws ClassCastException if the list contains elements that are not mutually * comparable using the specified comparator. * @throws UnsupportedOperationException if the specified list's list-iterator does not support * the set operation. * @see Comparator */ public static void sort(List list, Comparator c) { java.util.Collections.sort(list, c); } /** * Searches the specified list for the specified object using the binary search algorithm. The * list must be sorted into ascending order according to the {@linkplain Comparable natural * ordering} of its elements (as by the {@link #sort(List)} method) prior to making this call. * If it is not sorted, the results are undefined. If the list contains multiple elements equal * to the specified object, there is no guarantee which one will be found. *

* This method runs in log(n) time for a "random access" list (which provides near-constant-time * positional access). If the specified list does not implement the {@link RandomAccess} * interface and is large, this method will do an iterator-based binary search that performs * O(n) link traversals and O(log n) element comparisons. * * @param list the list to be searched. * @param key the key to be searched for. * @return the index of the search key, if it is contained in the list; otherwise, * (-(insertion point) - 1). The insertion point is defined as * the point at which the key would be inserted into the list: the index of the first * element greater than the key, or list.size() if all elements in the list are * less than the specified key. Note that this guarantees that the return value will be * >= 0 if and only if the key is found. * @throws ClassCastException if the list contains elements that are not mutually * comparable (for example, strings and integers), or the search key is not * mutually comparable with the elements of the list. */ public static int binarySearch(List> list, T key) { return java.util.Collections.binarySearch(list, key); } /** * Searches the specified list for the specified object using the binary search algorithm. The * list must be sorted into ascending order according to the specified comparator (as by the * {@link #sort(List, Comparator) sort(List, Comparator)} method), prior to making this call. If * it is not sorted, the results are undefined. If the list contains multiple elements equal to * the specified object, there is no guarantee which one will be found. *

* This method runs in log(n) time for a "random access" list (which provides near-constant-time * positional access). If the specified list does not implement the {@link RandomAccess} * interface and is large, this method will do an iterator-based binary search that performs * O(n) link traversals and O(log n) element comparisons. * * @param list the list to be searched. * @param key the key to be searched for. * @param c the comparator by which the list is ordered. A null value indicates that * the elements' {@linkplain Comparable natural ordering} should be used. * @return the index of the search key, if it is contained in the list; otherwise, * (-(insertion point) - 1). The insertion point is defined as * the point at which the key would be inserted into the list: the index of the first * element greater than the key, or list.size() if all elements in the list are * less than the specified key. Note that this guarantees that the return value will be * >= 0 if and only if the key is found. * @throws ClassCastException if the list contains elements that are not mutually * comparable using the specified comparator, or the search key is not mutually * comparable with the elements of the list using this comparator. */ public static int binarySearch(List list, T key, Comparator c) { return java.util.Collections.binarySearch(list, key, c); } /** * Reverses the order of the elements in the specified list. *

* This method runs in linear time. * * @param list the list whose elements are to be reversed. * @throws UnsupportedOperationException if the specified list or its list-iterator does not * support the set operation. */ public static void reverse(List list) { java.util.Collections.reverse(list); } /** * Randomly permutes the specified list using a default source of randomness. All permutations * occur with approximately equal likelihood. *

* The hedge "approximately" is used in the foregoing description because default source of * randomness is only approximately an unbiased source of independently chosen bits. If it were * a perfect source of randomly chosen bits, then the algorithm would choose permutations with * perfect uniformity. *

* This implementation traverses the list backwards, from the last element up to the second, * repeatedly swapping a randomly selected element into the "current position". Elements are * randomly selected from the portion of the list that runs from the first element to the * current position, inclusive. *

* This method runs in linear time. If the specified list does not implement the * {@link RandomAccess} interface and is large, this implementation dumps the specified list * into an array before shuffling it, and dumps the shuffled array back into the list. This * avoids the quadratic behavior that would result from shuffling a "sequential access" list in * place. * * @param list the list to be shuffled. * @throws UnsupportedOperationException if the specified list or its list-iterator does not * support the set operation. */ public static void shuffle(List list) { java.util.Collections.shuffle(list); } /** * Randomly permute the specified list using the specified source of randomness. All * permutations occur with equal likelihood assuming that the source of randomness is fair. *

* This implementation traverses the list backwards, from the last element up to the second, * repeatedly swapping a randomly selected element into the "current position". Elements are * randomly selected from the portion of the list that runs from the first element to the * current position, inclusive. *

* This method runs in linear time. If the specified list does not implement the * {@link RandomAccess} interface and is large, this implementation dumps the specified list * into an array before shuffling it, and dumps the shuffled array back into the list. This * avoids the quadratic behavior that would result from shuffling a "sequential access" list in * place. * * @param list the list to be shuffled. * @param rnd the source of randomness to use to shuffle the list. * @throws UnsupportedOperationException if the specified list or its list-iterator does not * support the set operation. */ public static void shuffle(List list, Random rnd) { java.util.Collections.shuffle(list, rnd); } /** * Swaps the elements at the specified positions in the specified list. (If the specified * positions are equal, invoking this method leaves the list unchanged.) * * @param list The list in which to swap elements. * @param i the index of one element to be swapped. * @param j the index of the other element to be swapped. * @throws IndexOutOfBoundsException if either i or j is out of range (i < * 0 || i >= list.size() || j < 0 || j >= list.size()). */ public static void swap(List list, int i, int j) { java.util.Collections.swap(list, i, j); } /** * Swaps the key and value of the map. * Map -> Map * * @param map the map */ public static void swap(Map map) { if (isEmpty(map)) { return; } Map nm = new HashMap(); for (Entry en : map.entrySet()) { nm.put(en.getValue(), en.getKey()); } map.clear(); map.putAll(nm); } /** * Return a new key/value swapped map. * Map -> Map * * @param map the map */ public static Map swapMap(Map map) { if (map == null) { return null; } Map nm = Classes.born(map.getClass()); for (Entry en : map.entrySet()) { nm.put(en.getValue(), en.getKey()); } return nm; } /** * Replaces all of the elements of the specified list with the specified element. *

* This method runs in linear time. * * @param list the list to be filled with the specified element. * @param obj The element with which to fill the specified list. * @throws UnsupportedOperationException if the specified list or its list-iterator does not * support the set operation. */ public static void fill(List list, T obj) { java.util.Collections.fill(list, obj); } /** * Copies all of the elements from one list into another. After the operation, the index of each * copied element in the destination list will be identical to its index in the source list. The * destination list must be at least as long as the source list. If it is longer, the remaining * elements in the destination list are unaffected. *

* This method runs in linear time. * * @param dest The destination list. * @param src The source list. * @throws IndexOutOfBoundsException if the destination list is too small to contain the entire * source List. * @throws UnsupportedOperationException if the destination list's list-iterator does not * support the set operation. */ public static void copy(List dest, List src) { java.util.Collections.copy(dest, src); } private final static int COPY_THRESHOLD = 10; /** * @param src the source list. * @param srcPos starting position in the source list. * @param des the destination list. * @param desPos starting position in the destination data. * @param length the number of list elements to be copied. */ public static void copy(List src, int srcPos, List des, int desPos, int length) { Asserts.isTrue(srcPos >= 0, "The srcPos value must be greater or equal zero: %d", srcPos); Asserts.isTrue(desPos >= 0, "The desPos value must be greater or equal zero: %d", desPos); int srcSize = src.size(); int desSize = des.size(); Asserts.isTrue(srcPos + length <= srcSize && desPos + length <= desSize, "The length value is out of bounds: %d", length); if (srcSize < COPY_THRESHOLD || (src instanceof RandomAccess && des instanceof RandomAccess)) { for (int i = 0; i < length; i++) { des.set(desPos + i, src.get(srcPos + i)); } } else { ListIterator di = des.listIterator(); ListIterator si = src.listIterator(); for (int i = 0; i < srcPos; i++) { si.next(); } for (int i = 0; i < desPos; i++) { di.next(); } for (int i = 0; i < length; i++) { di.next(); di.set(si.next()); } } } /** * Returns the minimum element of the given collection, according to the natural ordering * of its elements. All elements in the collection must implement the Comparable * interface. Furthermore, all elements in the collection must be mutually comparable * (that is, e1.compareTo(e2) must not throw a ClassCastException for any * elements e1 and e2 in the collection). *

* This method iterates over the entire collection, hence it requires time proportional to the * size of the collection. * * @param coll the collection whose minimum element is to be determined. * @return the minimum element of the given collection, according to the natural ordering * of its elements. * @throws ClassCastException if the collection contains elements that are not mutually * comparable (for example, strings and integers). * @throws NoSuchElementException if the collection is empty. * @see Comparable */ public static > T min(Collection coll) { return java.util.Collections.min(coll); } /** * Returns the minimum element of the given collection, according to the order induced by the * specified comparator. All elements in the collection must be mutually comparable by * the specified comparator (that is, comp.compare(e1, e2) must not throw a * ClassCastException for any elements e1 and e2 in the collection). *

* This method iterates over the entire collection, hence it requires time proportional to the * size of the collection. * * @param coll the collection whose minimum element is to be determined. * @param comp the comparator with which to determine the minimum element. A null value * indicates that the elements' natural ordering should be used. * @return the minimum element of the given collection, according to the specified comparator. * @throws ClassCastException if the collection contains elements that are not mutually * comparable using the specified comparator. * @throws NoSuchElementException if the collection is empty. * @see Comparable */ public static T min(Collection coll, Comparator comp) { return java.util.Collections.min(coll, comp); } /** * Returns the maximum element of the given collection, according to the natural ordering * of its elements. All elements in the collection must implement the Comparable * interface. Furthermore, all elements in the collection must be mutually comparable * (that is, e1.compareTo(e2) must not throw a ClassCastException for any * elements e1 and e2 in the collection). *

* This method iterates over the entire collection, hence it requires time proportional to the * size of the collection. * * @param coll the collection whose maximum element is to be determined. * @return the maximum element of the given collection, according to the natural ordering * of its elements. * @throws ClassCastException if the collection contains elements that are not mutually * comparable (for example, strings and integers). * @throws NoSuchElementException if the collection is empty. * @see Comparable */ public static > T max(Collection coll) { return java.util.Collections.max(coll); } /** * Returns the maximum element of the given collection, according to the order induced by the * specified comparator. All elements in the collection must be mutually comparable by * the specified comparator (that is, comp.compare(e1, e2) must not throw a * ClassCastException for any elements e1 and e2 in the collection). *

* This method iterates over the entire collection, hence it requires time proportional to the * size of the collection. * * @param coll the collection whose maximum element is to be determined. * @param comp the comparator with which to determine the maximum element. A null value * indicates that the elements' natural ordering should be used. * @return the maximum element of the given collection, according to the specified comparator. * @throws ClassCastException if the collection contains elements that are not mutually * comparable using the specified comparator. * @throws NoSuchElementException if the collection is empty. * @see Comparable */ public static T max(Collection coll, Comparator comp) { return java.util.Collections.max(coll, comp); } /** * Rotates the elements in the specified list by the specified distance. After calling this * method, the element at index i will be the element previously at index * (i - distance) mod list.size(), for all values of i between * 0 and list.size()-1, inclusive. (This method has no effect on the size of * the list.) *

* For example, suppose list comprises [t, a, n, k, s]. After invoking * Collections.rotate(list, 1) (or Collections.rotate(list, -4)), * list will comprise [s, t, a, n, k]. *

* Note that this method can usefully be applied to sublists to move one or more elements within * a list while preserving the order of the remaining elements. For example, the following idiom * moves the element at index j forward to position k (which must be greater * than or equal to j): * *

	 * Collections.rotate(list.subList(j, k + 1), -1);
	 * 
* * To make this concrete, suppose list comprises [a, b, c, d, e]. To move the * element at index 1 (b) forward two positions, perform the following * invocation: * *
	 * Collections.rotate(l.subList(1, 4), -1);
	 * 
* * The resulting list is [a, c, d, b, e]. *

* To move more than one element forward, increase the absolute value of the rotation distance. * To move elements backward, use a positive shift distance. *

* If the specified list is small or implements the {@link RandomAccess} interface, this * implementation exchanges the first element into the location it should go, and then * repeatedly exchanges the displaced element into the location it should go until a displaced * element is swapped into the first element. If necessary, the process is repeated on the * second and successive elements, until the rotation is complete. If the specified list is * large and doesn't implement the RandomAccess interface, this implementation breaks * the list into two sublist views around index -distance mod size. Then the * {@link #reverse(List)} method is invoked on each sublist view, and finally it is invoked on * the entire list. For a more complete description of both algorithms, see Section 2.3 of Jon * Bentley's Programming Pearls (Addison-Wesley, 1986). * * @param list the list to be rotated. * @param distance the distance to rotate the list. There are no constraints on this value; it * may be zero, negative, or greater than list.size(). * @throws UnsupportedOperationException if the specified list or its list-iterator does not * support the set operation. */ public static void rotate(List list, int distance) { java.util.Collections.rotate(list, distance); } /** * Replaces all occurrences of one specified value in a list with another. More formally, * replaces with newVal each element e in list such that * (oldVal==null ? e==null : oldVal.equals(e)). (This method has no effect on the size * of the list.) * * @param list the list in which replacement is to occur. * @param oldVal the old value to be replaced. * @param newVal the new value with which oldVal is to be replaced. * @return true if list contained one or more elements e such that * (oldVal==null ? e==null : oldVal.equals(e)). * @throws UnsupportedOperationException if the specified list or its list-iterator does not * support the set operation. */ public static boolean replaceAll(List list, T oldVal, T newVal) { return java.util.Collections.replaceAll(list, oldVal, newVal); } /** * Returns the starting position of the first occurrence of the specified target list within the * specified source list, or -1 if there is no such occurrence. More formally, returns the * lowest index i such that source.subList(i, i+target.size()).equals(target), * or -1 if there is no such index. (Returns -1 if target.size() > source.size().) *

* This implementation uses the "brute force" technique of scanning over the source list, * looking for a match with the target at each location in turn. * * @param source the list in which to search for the first occurrence of target. * @param target the list to search for as a subList of source. * @return the starting position of the first occurrence of the specified target list within the * specified source list, or -1 if there is no such occurrence. */ public static int indexOfSubList(List source, List target) { return java.util.Collections.indexOfSubList(source, target); } /** * Returns the starting position of the last occurrence of the specified target list within the * specified source list, or -1 if there is no such occurrence. More formally, returns the * highest index i such that source.subList(i, i+target.size()).equals(target) * , or -1 if there is no such index. (Returns -1 if target.size() > source.size().) *

* This implementation uses the "brute force" technique of iterating over the source list, * looking for a match with the target at each location in turn. * * @param source the list in which to search for the last occurrence of target. * @param target the list to search for as a subList of source. * @return the starting position of the last occurrence of the specified target list within the * specified source list, or -1 if there is no such occurrence. */ public static int lastIndexOfSubList(List source, List target) { return java.util.Collections.lastIndexOfSubList(source, target); } // Unmodifiable Wrappers /** * Returns an unmodifiable view of the specified collection. This method allows modules to * provide users with "read-only" access to internal collections. Query operations on the * returned collection "read through" to the specified collection, and attempts to modify the * returned collection, whether direct or via its iterator, result in an * UnsupportedOperationException. *

* The returned collection does not pass the hashCode and equals operations through to * the backing collection, but relies on Object's equals and hashCode * methods. This is necessary to preserve the contracts of these operations in the case that the * backing collection is a set or a list. *

* The returned collection will be serializable if the specified collection is serializable. * * @param c the collection for which an unmodifiable view is to be returned. * @return an unmodifiable view of the specified collection. */ public static Collection unmodifiableCollection(Collection c) { if (c == null) { return null; } return java.util.Collections.unmodifiableCollection(c); } /** * Returns an unmodifiable view of the specified set. This method allows modules to provide * users with "read-only" access to internal sets. Query operations on the returned set * "read through" to the specified set, and attempts to modify the returned set, whether direct * or via its iterator, result in an UnsupportedOperationException. *

* The returned set will be serializable if the specified set is serializable. * * @param s the set for which an unmodifiable view is to be returned. * @return an unmodifiable view of the specified set. */ public static Set unmodifiableSet(Set s) { if (s == null) { return null; } return java.util.Collections.unmodifiableSet(s); } /** * Returns an unmodifiable view of the specified sorted set. This method allows modules to * provide users with "read-only" access to internal sorted sets. Query operations on the * returned sorted set "read through" to the specified sorted set. Attempts to modify the * returned sorted set, whether direct, via its iterator, or via its subSet, * headSet, or tailSet views, result in an * UnsupportedOperationException. *

* The returned sorted set will be serializable if the specified sorted set is serializable. * * @param s the sorted set for which an unmodifiable view is to be returned. * @return an unmodifiable view of the specified sorted set. */ public static SortedSet unmodifiableSortedSet(SortedSet s) { if (s == null) { return null; } return java.util.Collections.unmodifiableSortedSet(s); } /** * Returns an unmodifiable view of the specified list. This method allows modules to provide * users with "read-only" access to internal lists. Query operations on the returned list * "read through" to the specified list, and attempts to modify the returned list, whether * direct or via its iterator, result in an UnsupportedOperationException. *

* The returned list will be serializable if the specified list is serializable. Similarly, the * returned list will implement {@link RandomAccess} if the specified list does. * * @param list the list for which an unmodifiable view is to be returned. * @return an unmodifiable view of the specified list. */ public static List unmodifiableList(List list) { if (list == null) { return null; } return java.util.Collections.unmodifiableList(list); } /** * Returns an unmodifiable view of the specified map. This method allows modules to provide * users with "read-only" access to internal maps. Query operations on the returned map * "read through" to the specified map, and attempts to modify the returned map, whether direct * or via its collection views, result in an UnsupportedOperationException. *

* The returned map will be serializable if the specified map is serializable. * * @param m the map for which an unmodifiable view is to be returned. * @return an unmodifiable view of the specified map. */ public static Map unmodifiableMap(Map m) { if (m == null) { return null; } return java.util.Collections.unmodifiableMap(m); } /** * Returns an unmodifiable view of the specified sorted map. This method allows modules to * provide users with "read-only" access to internal sorted maps. Query operations on the * returned sorted map "read through" to the specified sorted map. Attempts to modify the * returned sorted map, whether direct, via its collection views, or via its subMap, * headMap, or tailMap views, result in an * UnsupportedOperationException. *

* The returned sorted map will be serializable if the specified sorted map is serializable. * * @param m the sorted map for which an unmodifiable view is to be returned. * @return an unmodifiable view of the specified sorted map. */ public static SortedMap unmodifiableSortedMap(SortedMap m) { if (m == null) { return null; } return java.util.Collections.unmodifiableSortedMap(m); } /** * Returns a synchronized (thread-safe) collection backed by the specified collection. In order * to guarantee serial access, it is critical that all access to the backing * collection is accomplished through the returned collection. *

* It is imperative that the user manually synchronize on the returned collection when iterating * over it: * *

	 *  Collection c = java.util.Collections.synchronizedCollection(myCollection);
	 *     ...
	 *  synchronized(c) {
	 *      Iterator i = c.iterator(); // Must be in the synchronized block
	 *      while (i.hasNext())
	 *         foo(i.next());
	 *  }
	 * 
* * Failure to follow this advice may result in non-deterministic behavior. *

* The returned collection does not pass the hashCode and equals * operations through to the backing collection, but relies on Object's equals and * hashCode methods. This is necessary to preserve the contracts of these operations in the case * that the backing collection is a set or a list. *

* The returned collection will be serializable if the specified collection is serializable. * * @param c the collection to be "wrapped" in a synchronized collection. * @return a synchronized view of the specified collection. */ public static Collection synchronizedCollection(Collection c) { if (c == null) { return null; } return java.util.Collections.synchronizedCollection(c); } /** * Returns a synchronized (thread-safe) set backed by the specified set. In order to guarantee * serial access, it is critical that all access to the backing set is * accomplished through the returned set. *

* It is imperative that the user manually synchronize on the returned set when iterating over * it: * *

	 *  Set s = java.util.Collections.synchronizedSet(new HashSet());
	 *      ...
	 *  synchronized(s) {
	 *      Iterator i = s.iterator(); // Must be in the synchronized block
	 *      while (i.hasNext())
	 *          foo(i.next());
	 *  }
	 * 
* * Failure to follow this advice may result in non-deterministic behavior. *

* The returned set will be serializable if the specified set is serializable. * * @param s the set to be "wrapped" in a synchronized set. * @return a synchronized view of the specified set. */ public static Set synchronizedSet(Set s) { if (s == null) { return null; } return java.util.Collections.synchronizedSet(s); } /** * Returns a synchronized (thread-safe) sorted set backed by the specified sorted set. In order * to guarantee serial access, it is critical that all access to the backing * sorted set is accomplished through the returned sorted set (or its views). *

* It is imperative that the user manually synchronize on the returned sorted set when iterating * over it or any of its subSet, headSet, or tailSet views. * *

	 *  SortedSet s = java.util.Collections.synchronizedSortedSet(new TreeSet());
	 *      ...
	 *  synchronized(s) {
	 *      Iterator i = s.iterator(); // Must be in the synchronized block
	 *      while (i.hasNext())
	 *          foo(i.next());
	 *  }
	 * 
* * or: * *
	 *  SortedSet s = java.util.Collections.synchronizedSortedSet(new TreeSet());
	 *  SortedSet s2 = s.headSet(foo);
	 *      ...
	 *  synchronized(s) {  // Note: s, not s2!!!
	 *      Iterator i = s2.iterator(); // Must be in the synchronized block
	 *      while (i.hasNext())
	 *          foo(i.next());
	 *  }
	 * 
* * Failure to follow this advice may result in non-deterministic behavior. *

* The returned sorted set will be serializable if the specified sorted set is serializable. * * @param s the sorted set to be "wrapped" in a synchronized sorted set. * @return a synchronized view of the specified sorted set. */ public static SortedSet synchronizedSortedSet(SortedSet s) { if (s == null) { return null; } return java.util.Collections.synchronizedSortedSet(s); } /** * Returns a synchronized (thread-safe) list backed by the specified list. In order to guarantee * serial access, it is critical that all access to the backing list is * accomplished through the returned list. *

* It is imperative that the user manually synchronize on the returned list when iterating over * it: * *

	 *  List list = java.util.Collections.synchronizedList(new ArrayList());
	 *      ...
	 *  synchronized(list) {
	 *      Iterator i = list.iterator(); // Must be in synchronized block
	 *      while (i.hasNext())
	 *          foo(i.next());
	 *  }
	 * 
* * Failure to follow this advice may result in non-deterministic behavior. *

* The returned list will be serializable if the specified list is serializable. * * @param list the list to be "wrapped" in a synchronized list. * @return a synchronized view of the specified list. */ public static List synchronizedList(List list) { if (list == null) { return null; } return java.util.Collections.synchronizedList(list); } /** * Returns a synchronized (thread-safe) map backed by the specified map. In order to guarantee * serial access, it is critical that all access to the backing map is * accomplished through the returned map. *

* It is imperative that the user manually synchronize on the returned map when iterating over * any of its collection views: * *

	 *  Map m = java.util.Collections.synchronizedMap(new HashMap());
	 *      ...
	 *  Set s = m.keySet();  // Needn't be in synchronized block
	 *      ...
	 *  synchronized(m) {  // Synchronizing on m, not s!
	 *      Iterator i = s.iterator(); // Must be in synchronized block
	 *      while (i.hasNext())
	 *          foo(i.next());
	 *  }
	 * 
* * Failure to follow this advice may result in non-deterministic behavior. *

* The returned map will be serializable if the specified map is serializable. * * @param m the map to be "wrapped" in a synchronized map. * @return a synchronized view of the specified map. */ public static Map synchronizedMap(Map m) { if (m == null) { return null; } return java.util.Collections.synchronizedMap(m); } /** * Returns a synchronized (thread-safe) sorted map backed by the specified sorted map. In order * to guarantee serial access, it is critical that all access to the backing * sorted map is accomplished through the returned sorted map (or its views). *

* It is imperative that the user manually synchronize on the returned sorted map when iterating * over any of its collection views, or the collections views of any of its subMap, * headMap or tailMap views. * *

	 *  SortedMap m = java.util.Collections.synchronizedSortedMap(new TreeMap());
	 *      ...
	 *  Set s = m.keySet();  // Needn't be in synchronized block
	 *      ...
	 *  synchronized(m) {  // Synchronizing on m, not s!
	 *      Iterator i = s.iterator(); // Must be in synchronized block
	 *      while (i.hasNext())
	 *          foo(i.next());
	 *  }
	 * 
* * or: * *
	 *  SortedMap m = java.util.Collections.synchronizedSortedMap(new TreeMap());
	 *  SortedMap m2 = m.subMap(foo, bar);
	 *      ...
	 *  Set s2 = m2.keySet();  // Needn't be in synchronized block
	 *      ...
	 *  synchronized(m) {  // Synchronizing on m, not m2 or s2!
	 *      Iterator i = s.iterator(); // Must be in synchronized block
	 *      while (i.hasNext())
	 *          foo(i.next());
	 *  }
	 * 
* * Failure to follow this advice may result in non-deterministic behavior. *

* The returned sorted map will be serializable if the specified sorted map is serializable. * * @param m the sorted map to be "wrapped" in a synchronized sorted map. * @return a synchronized view of the specified sorted map. */ public static SortedMap synchronizedSortedMap(SortedMap m) { if (m == null) { return null; } return java.util.Collections.synchronizedSortedMap(m); } /** * Returns a dynamically typesafe view of the specified collection. Any attempt to insert an * element of the wrong type will result in an immediate ClassCastException. Assuming a * collection contains no incorrectly typed elements prior to the time a dynamically typesafe * view is generated, and that all subsequent access to the collection takes place through the * view, it is guaranteed that the collection cannot contain an incorrectly typed * element. *

* The generics mechanism in the language provides compile-time (static) type checking, but it * is possible to defeat this mechanism with unchecked casts. Usually this is not a problem, as * the compiler issues warnings on all such unchecked operations. There are, however, times when * static type checking alone is not sufficient. For example, suppose a collection is passed to * a third-party library and it is imperative that the library code not corrupt the collection * by inserting an element of the wrong type. *

* Another use of dynamically typesafe views is debugging. Suppose a program fails with a * ClassCastException, indicating that an incorrectly typed element was put into a * parameterized collection. Unfortunately, the exception can occur at any time after the * erroneous element is inserted, so it typically provides little or no information as to the * real source of the problem. If the problem is reproducible, one can quickly determine its * source by temporarily modifying the program to wrap the collection with a dynamically * typesafe view. For example, this declaration: * *

	 * Collection<String> c = new HashSet<String>();
	 * 
* * may be replaced temporarily by this one: * *
	 * Collection<String> c = java.util.Collections.checkedCollection(new HashSet<String>(), String.class);
	 * 
* * Running the program again will cause it to fail at the point where an incorrectly typed * element is inserted into the collection, clearly identifying the source of the problem. Once * the problem is fixed, the modified declaration may be reverted back to the original. *

* The returned collection does not pass the hashCode and equals operations through to * the backing collection, but relies on Object's equals and hashCode * methods. This is necessary to preserve the contracts of these operations in the case that the * backing collection is a set or a list. *

* The returned collection will be serializable if the specified collection is serializable. * * @param c the collection for which a dynamically typesafe view is to be returned * @param type the type of element that c is permitted to hold * @return a dynamically typesafe view of the specified collection */ public static Collection checkedCollection(Collection c, Class type) { return java.util.Collections.checkedCollection(c, type); } /** * Returns a dynamically typesafe view of the specified set. Any attempt to insert an element of * the wrong type will result in an immediate ClassCastException. Assuming a set * contains no incorrectly typed elements prior to the time a dynamically typesafe view is * generated, and that all subsequent access to the set takes place through the view, it is * guaranteed that the set cannot contain an incorrectly typed element. *

* A discussion of the use of dynamically typesafe views may be found in the documentation for * the {@link #checkedCollection checkedCollection} method. *

* The returned set will be serializable if the specified set is serializable. * * @param s the set for which a dynamically typesafe view is to be returned * @param type the type of element that s is permitted to hold * @return a dynamically typesafe view of the specified set */ public static Set checkedSet(Set s, Class type) { return java.util.Collections.checkedSet(s, type); } /** * Returns a dynamically typesafe view of the specified sorted set. Any attempt to insert an * element of the wrong type will result in an immediate ClassCastException. Assuming a * sorted set contains no incorrectly typed elements prior to the time a dynamically typesafe * view is generated, and that all subsequent access to the sorted set takes place through the * view, it is guaranteed that the sorted set cannot contain an incorrectly typed * element. *

* A discussion of the use of dynamically typesafe views may be found in the documentation for * the {@link #checkedCollection checkedCollection} method. *

* The returned sorted set will be serializable if the specified sorted set is serializable. * * @param s the sorted set for which a dynamically typesafe view is to be returned * @param type the type of element that s is permitted to hold * @return a dynamically typesafe view of the specified sorted set */ public static SortedSet checkedSortedSet(SortedSet s, Class type) { return java.util.Collections.checkedSortedSet(s, type); } /** * Returns a dynamically typesafe view of the specified list. Any attempt to insert an element * of the wrong type will result in an immediate ClassCastException. Assuming a list * contains no incorrectly typed elements prior to the time a dynamically typesafe view is * generated, and that all subsequent access to the list takes place through the view, it is * guaranteed that the list cannot contain an incorrectly typed element. *

* A discussion of the use of dynamically typesafe views may be found in the documentation for * the {@link #checkedCollection checkedCollection} method. *

* The returned list will be serializable if the specified list is serializable. * * @param list the list for which a dynamically typesafe view is to be returned * @param type the type of element that list is permitted to hold * @return a dynamically typesafe view of the specified list */ public static List checkedList(List list, Class type) { return java.util.Collections.checkedList(list, type); } /** * Returns a dynamically typesafe view of the specified map. Any attempt to insert a mapping * whose key or value have the wrong type will result in an immediate * ClassCastException. Similarly, any attempt to modify the value currently associated * with a key will result in an immediate ClassCastException, whether the modification * is attempted directly through the map itself, or through a {@link java.util.Map.Entry} instance * obtained from the map's {@link Map#entrySet() entry set} view. *

* Assuming a map contains no incorrectly typed keys or values prior to the time a dynamically * typesafe view is generated, and that all subsequent access to the map takes place through the * view (or one of its collection views), it is guaranteed that the map cannot contain an * incorrectly typed key or value. *

* A discussion of the use of dynamically typesafe views may be found in the documentation for * the {@link #checkedCollection checkedCollection} method. *

* The returned map will be serializable if the specified map is serializable. * * @param m the map for which a dynamically typesafe view is to be returned * @param keyType the type of key that m is permitted to hold * @param valueType the type of value that m is permitted to hold * @return a dynamically typesafe view of the specified map */ public static Map checkedMap(Map m, Class keyType, Class valueType) { return java.util.Collections.checkedMap(m, keyType, valueType); } /** * Returns a dynamically typesafe view of the specified sorted map. Any attempt to insert a * mapping whose key or value have the wrong type will result in an immediate * ClassCastException. Similarly, any attempt to modify the value currently associated * with a key will result in an immediate ClassCastException, whether the modification * is attempted directly through the map itself, or through a {@link java.util.Map.Entry} instance * obtained from the map's {@link Map#entrySet() entry set} view. *

* Assuming a map contains no incorrectly typed keys or values prior to the time a dynamically * typesafe view is generated, and that all subsequent access to the map takes place through the * view (or one of its collection views), it is guaranteed that the map cannot contain an * incorrectly typed key or value. *

* A discussion of the use of dynamically typesafe views may be found in the documentation for * the {@link #checkedCollection checkedCollection} method. *

* The returned map will be serializable if the specified map is serializable. * * @param m the map for which a dynamically typesafe view is to be returned * @param keyType the type of key that m is permitted to hold * @param valueType the type of value that m is permitted to hold * @return a dynamically typesafe view of the specified map */ public static SortedMap checkedSortedMap(SortedMap m, Class keyType, Class valueType) { return java.util.Collections.checkedSortedMap(m, keyType, valueType); } // Miscellaneous /** * The empty set (immutable). This set is serializable. * * @see #emptySet() */ public static final Set EMPTY_SET = java.util.Collections.EMPTY_SET; /** * Returns the empty set (immutable). This set is serializable. Unlike the like-named field, * this method is parameterized. *

* This example illustrates the type-safe way to obtain an empty set: * *

	 * Set<String> s = java.util.Collections.emptySet();
	 * 
* * Implementation note: Implementations of this method need not create a separate Set * object for each call. Using this method is likely to have comparable cost to using the * like-named field. (Unlike this method, the field does not provide type safety.) * @return the empty set * * @see #EMPTY_SET */ public static final Set emptySet() { return (Set) EMPTY_SET; } /** * The empty list (immutable). This list is serializable. * * @see #emptyList() */ public static final List EMPTY_LIST = java.util.Collections.EMPTY_LIST; /** * Returns the empty list (immutable). This list is serializable. *

* This example illustrates the type-safe way to obtain an empty list: * *

	 * List<String> s = java.util.Collections.emptyList();
	 * 
* * Implementation note: Implementations of this method need not create a separate List * object for each call. Using this method is likely to have comparable cost to using the * like-named field. (Unlike this method, the field does not provide type safety.) * * @return the empty list * @see #EMPTY_LIST */ public static final List emptyList() { return (List) EMPTY_LIST; } /** * The empty map (immutable). This map is serializable. * * @see #emptyMap() */ public static final Map EMPTY_MAP = java.util.Collections.EMPTY_MAP; /** * Returns the empty map (immutable). This map is serializable. *

* This example illustrates the type-safe way to obtain an empty set: * *

	 * Map<String, Date> s = java.util.Collections.emptyMap();
	 * 
* * Implementation note: Implementations of this method need not create a separate Map * object for each call. Using this method is likely to have comparable cost to using the * like-named field. (Unlike this method, the field does not provide type safety.) * @return the empty map * @see #EMPTY_MAP */ public static final Map emptyMap() { return (Map) EMPTY_MAP; } /** * Returns an immutable list containing only the specified object. The returned list is * serializable. * * @param o the sole object to be stored in the returned list. * @return an immutable list containing only the specified object. */ public static Set singleton(T o) { return java.util.Collections.singleton(o); } /** * Returns an immutable list containing only the specified object. The returned list is * serializable. * * @param o the sole object to be stored in the returned list. * @return an immutable list containing only the specified object. */ public static List singletonList(T o) { return java.util.Collections.singletonList(o); } /** * Returns an immutable map, mapping only the specified key to the specified value. The returned * map is serializable. * * @param key the sole key to be stored in the returned map. * @param value the value to which the returned map maps key. * @return an immutable map containing only the specified key-value mapping. */ public static Map singletonMap(K key, V value) { return java.util.Collections.singletonMap(key, value); } /** * Returns an immutable list consisting of n copies of the specified object. The newly * allocated data object is tiny (it contains a single reference to the data object). This * method is useful in combination with the List.addAll method to grow lists. The * returned list is serializable. * * @param n the number of elements in the returned list. * @param o the element to appear repeatedly in the returned list. * @return an immutable list consisting of n copies of the specified object. * @throws IllegalArgumentException if n < 0. * @see List#addAll(Collection) * @see List#addAll(int, Collection) */ public static List nCopies(int n, T o) { return java.util.Collections.nCopies(n, o); } /** * Returns a comparator that imposes the reverse of the natural ordering on a collection * of objects that implement the Comparable interface. (The natural ordering is the * ordering imposed by the objects' own compareTo method.) This enables a simple idiom * for sorting (or maintaining) collections (or arrays) of objects that implement the * Comparable interface in reverse-natural-order. For example, suppose a is an array of * strings. Then: * *
	 * Arrays.sort(a, java.util.Collections.reverseOrder());
	 * 
* * sorts the array in reverse-lexicographic (alphabetical) order. *

* The returned comparator is serializable. * * @return a comparator that imposes the reverse of the natural ordering on a collection * of objects that implement the Comparable interface. * @see Comparable */ public static Comparator reverseOrder() { return java.util.Collections.reverseOrder(); } /** * Returns a comparator that imposes the reverse ordering of the specified comparator. If the * specified comparator is null, this method is equivalent to {@link #reverseOrder()} (in other * words, it returns a comparator that imposes the reverse of the natural ordering on a * collection of objects that implement the Comparable interface). *

* The returned comparator is serializable (assuming the specified comparator is also * serializable or null). * * @param cmp a comparator who's ordering is to be reversed by the returned * comparator or {@code null} * @return a comparator that imposes the reverse ordering of the specified comparator. */ public static Comparator reverseOrder(Comparator cmp) { return java.util.Collections.reverseOrder(cmp); } /** * Returns an enumeration over the specified collection. This provides interoperability with * legacy APIs that require an enumeration as input. * * @param c the collection for which an enumeration is to be returned. * @return an enumeration over the specified collection. * @see Enumeration */ public static Enumeration enumeration(final Collection c) { return java.util.Collections.enumeration(c); } /** * Returns an array list containing the elements returned by the specified enumeration in the * order they are returned by the enumeration. This method provides interoperability between * legacy APIs that return enumerations and new APIs that require collections. * * @param e enumeration providing elements for the returned array list * @return an array list containing the elements returned by the specified enumeration. * @see Enumeration * @see ArrayList */ public static ArrayList list(Enumeration e) { return java.util.Collections.list(e); } /** * Returns the number of elements in the specified collection equal to the specified object. * More formally, returns the number of elements e in the collection such that * (o == null ? e == null : o.equals(e)). * * @param c the collection in which to determine the frequency of o * @param o the object whose frequency is to be determined * @return the number of elements in the specified collection equal to the specified object. * @throws NullPointerException if c is null */ public static int frequency(Collection c, Object o) { return java.util.Collections.frequency(c, o); } /** * Returns true if the two specified collections have no elements in common. *

* Care must be exercised if this method is used on collections that do not comply with the * general contract for Collection. Implementations may elect to iterate over either * collection and test for containment in the other collection (or to perform any equivalent * computation). If either collection uses a nonstandard equality test (as does a * {@link SortedSet} whose ordering is not compatible with equals, or the key set of an * {@link IdentityHashMap}), both collections must use the same nonstandard equality test, or * the result of this method is undefined. *

* Note that it is permissible to pass the same collection in both parameters, in which case the * method will return true if and only if the collection is empty. * * @param c1 a collection * @param c2 a collection * @return true if the two specified collections have no elements in common. * @throws NullPointerException if either collection is null */ public static boolean disjoint(Collection c1, Collection c2) { return java.util.Collections.disjoint(c1, c2); } /** * Adds all of the specified elements to the specified collection. Elements to be added may be * specified individually or as an array. The behavior of this convenience method is identical * to that of c.addAll(Arrays.asList(elements)), but this method is likely to run * significantly faster under most implementations. *

* When elements are specified individually, this method provides a convenient way to add a few * elements to an existing collection: * *

	 * java.util.Collections.addAll(flavors, "Peaches 'n Plutonium", "Rocky Racoon");
	 * 
* * @param c the collection into which elements are to be inserted * @param elements the elements to insert into c * @return true if the collection changed as a result of the call * @throws UnsupportedOperationException if c does not support the add * operation * @throws NullPointerException if elements contains one or more null values and * c does not permit null elements, or if c or elements * are null * @throws IllegalArgumentException if some property of a value in elements prevents it * from being added to c * @see Collection#addAll(Collection) */ public static boolean addAll(Collection c, T... elements) { return java.util.Collections.addAll(c, elements); } /** * Returns a set backed by the specified map. The resulting set displays the same ordering, * concurrency, and performance characteristics as the backing map. In essence, this factory * method provides a {@link Set} implementation corresponding to any {@link Map} implementation. * There is no need to use this method on a {@link Map} implementation that already has a * corresponding {@link Set} implementation (such as {@link HashMap} or {@link TreeMap}). *

* Each method invocation on the set returned by this method results in exactly one method * invocation on the backing map or its keySet view, with one exception. The * addAll method is implemented as a sequence of put invocations on the * backing map. *

* The specified map must be empty at the time this method is invoked, and should not be * accessed directly after this method returns. These conditions are ensured if the map is * created empty, passed directly to this method, and no reference to the map is retained, as * illustrated in the following code fragment: * *

	 * Set<Object> weakHashSet = java.util.Collections.newSetFromMap(new WeakHashMap<Object, Boolean>());
	 * 
* * @param map the backing map * @return the set backed by the map * @throws IllegalArgumentException if map is not empty */ public static Set newSetFromMap(Map map) { return java.util.Collections.newSetFromMap(map); } /** * Returns a view of a {@link Deque} as a Last-in-first-out (Lifo) {@link Queue}. Method * add is mapped to push, remove is mapped to pop and so on. * This view can be useful when you would like to use a method requiring a Queue but * you need Lifo ordering. *

* Each method invocation on the queue returned by this method results in exactly one method * invocation on the backing deque, with one exception. The {@link Queue#addAll addAll} method * is implemented as a sequence of {@link Deque#addFirst addFirst} invocations on the backing * deque. * * @param deque the deque * @return the queue */ public static Queue asLifoQueue(Deque deque) { return java.util.Collections.asLifoQueue(deque); } /** * invert copy map, the key/value pair is inverted. * @param des destination map * @param src source map array * @return the destination map (des) */ public static Map invertAddAll(Map des, Map ... src) { if (src == null || src.length == 0) { return des; } Asserts.notNull(des); for (Map m : src) { for (Entry en : (Set)m.entrySet()) { des.put(en.getValue(), en.getKey()); } } return des; } /** * copy source maps to des map * @param des destination map * @param src source map array * @return the destination map (des) */ public static Map addAll(Map des, Map ... src) { if (src == null || src.length == 0) { return des; } Asserts.notNull(des); for (Map m : src) { des.putAll(m); } return des; } /** * subtract a map which key starts with the prefix, and remove prefix of key * * @param map the original map * @param prefix the key prefix * @return the subtracted map */ public static Map subMap(Map map, String prefix) { return subMap(map, prefix, true); } /** * subtract a map which key starts with the prefix * * @param map the original map * @param prefix the key prefix * @param remove remove prefix of key * @return the subtracted map */ public static Map subMap(Map map, String prefix, boolean remove) { if (isEmpty(map) || Strings.isEmpty(prefix)) { return map; } Map nm = new LinkedHashMap(); int len = prefix.length(); for (Entry en : map.entrySet()) { String k = en.getKey(); if (k != null && k.startsWith(prefix)) { if (remove) { k = k.substring(len); } nm.put(k, en.getValue()); } } return nm; } /** * remove empty elements from collection * * @param coll the collection * @return the stripped collection (coll) */ public static Collection stripToNull(Collection coll) { if (isEmpty(coll)) { return null; } for (Iterator it = coll.iterator(); it.hasNext();) { if (Objects.isEmpty(it.next())) { it.remove(); } } return isEmpty(coll) ? null : coll; } /** * remove empty elements from list * * @param list the list * @return the stripped list (list) */ public static List stripToNull(List list) { if (isEmpty(list)) { return null; } for (Iterator it = list.iterator(); it.hasNext();) { if (Objects.isEmpty(it.next())) { it.remove(); } } return isEmpty(list) ? null : list; } /** * remove empty elements from set * * @param set the set * @return the stripped set (set) */ public static Set stripToNull(Set set) { if (isEmpty(set)) { return null; } for (Iterator it = set.iterator(); it.hasNext();) { if (Objects.isEmpty(it.next())) { it.remove(); } } return isEmpty(set) ? null : set; } /** * remove empty elements from collection * * @param coll the collection * @return the stripped collection (coll) */ public static Collection stripToEmpty(Collection coll) { if (coll == null) { return new ArrayList(); } for (Iterator it = coll.iterator(); it.hasNext();) { if (Objects.isEmpty(it.next())) { it.remove(); } } return coll; } /** * remove empty elements from list * * @param list the list * @return the stripped list (list) */ public static List stripToEmpty(List list) { if (list == null) { return new ArrayList(); } for (Iterator it = list.iterator(); it.hasNext();) { if (Objects.isEmpty(it.next())) { it.remove(); } } return list; } /** * remove empty elements from set * * @param set the set * @return the stripped set (set) */ public static Set stripToEmpty(Set set) { if (set == null) { return new HashSet(); } for (Iterator it = set.iterator(); it.hasNext();) { if (Objects.isEmpty(it.next())) { it.remove(); } } return set; } /** * @param col collection * @return true if all items is empty */ public static boolean isItemsEmpty(Collection col) { if (isEmpty(col)) { return true; } for (Object o : col) { if (Objects.isNotEmpty(o)) { return false; } } return true; } //-------------------------------------------------------------------------- private static class ListSet implements Set { private final List list; /** * @param list the list */ public ListSet(List list) { this.list = list; } @Override public int size() { return list.size(); } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public boolean contains(Object o) { return list.contains(o); } @Override public Iterator iterator() { return list.iterator(); } @Override public Object[] toArray() { return list.toArray(); } @Override public T[] toArray(T[] a) { return list.toArray(a); } @Override public boolean add(E e) { return list.add(e); } @Override public boolean remove(Object o) { return list.remove(o); } @Override public boolean containsAll(Collection c) { return list.containsAll(c); } @Override public boolean addAll(Collection c) { return list.addAll(c); } @Override public boolean retainAll(Collection c) { return list.retainAll(c); } @Override public boolean removeAll(Collection c) { return list.removeAll(c); } @Override public void clear() { list.clear(); } } /** * Returns a set backed by the specified list. (Changes to the returned list * "write through" to the list.) *

* This method also provides a convenient way to convert list to set * * @param list the list by which the set will be backed * @return a set of the specified list */ public static Set asSet(List list) { if (list == null) { return null; } return new ListSet(list); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy