/*******************************************************************************
 * Copyright (c) 2005, 2010 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0, which accompanies this distribution
 * and is available at http://www.eclipse.org/legal/epl-v10.html.
 * 
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.utility.internal;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Random;
import java.util.RandomAccess;
import java.util.TreeSet;
import java.util.Vector;

import org.eclipse.jpt.utility.internal.iterables.ArrayIterable;
import org.eclipse.jpt.utility.internal.iterators.ArrayIterator;
import org.eclipse.jpt.utility.internal.iterators.ArrayListIterator;
import org.eclipse.jpt.utility.internal.iterators.SingleElementIterator;
import org.eclipse.jpt.utility.internal.iterators.SingleElementListIterator;
import org.eclipse.jpt.utility.internal.iterators.SuperIteratorWrapper;

/**
 * {@link Collection}-related utility methods.
 */
public final class CollectionTools {

	// ********** add all **********

	/**
	 * Add all the elements returned by the specified iterable
	 * to the specified collection.
	 * Return whether the collection changed as a result.
	 * <p>
	 * <code>Collection.addAll(Iterable iterable)</code>
	 */
	public static <E> boolean addAll(Collection<? super E> collection, Iterable<? extends E> iterable) {
		return addAll(collection, iterable.iterator());
	}

	/**
	 * Add all the elements returned by the specified iterable
	 * to the specified collection.
	 * Return whether the collection changed as a result.
	 * <p>
	 * <code>Collection.addAll(Iterable iterable)</code>
	 */
	public static <E> boolean addAll(Collection<? super E> collection, Iterable<? extends E> iterable, int size) {
		return addAll(collection, iterable.iterator(), size);
	}

	/**
	 * Add all the elements returned by the specified iterator
	 * to the specified collection.
	 * Return whether the collection changed as a result.
	 * <p>
	 * <code>Collection.addAll(Iterator iterator)</code>
	 */
	public static <E> boolean addAll(Collection<? super E> collection, Iterator<? extends E> iterator) {
		return iterator.hasNext() ? addAll_(collection, iterator) : false;
	}

	/**
	 * assume the iterator is not empty
	 */
	private static <E> boolean addAll_(Collection<? super E> collection, Iterator<? extends E> iterator) {
		boolean modified = false;
		while (iterator.hasNext()) {
			modified |= collection.add(iterator.next());
		}
		return modified;
	}

	/**
	 * Add all the elements returned by the specified iterator
	 * to the specified collection.
	 * Return whether the collection changed as a result.
	 * <p>
	 * <code>Collection.addAll(Iterator iterator)</code>
	 */
	public static <E> boolean addAll(Collection<? super E> collection, Iterator<? extends E> iterator, int size) {
		return iterator.hasNext() ? collection.addAll(list(iterator, size)) : false;
	}

	/**
	 * Add all the elements in the specified array
	 * to the specified collection.
	 * Return whether the collection changed as a result.
	 * <p>
	 * <code>Collection.addAll(Object[] array)</code>
	 */
	public static <E> boolean addAll(Collection<? super E> collection, E... array) {
		return (array.length == 0) ? false : addAll_(collection, array);
	}

	/**
	 * assume the array is not empty
	 */
	private static <E> boolean addAll_(Collection<? super E> collection, E... array) {
		boolean modified = false;
		for (E element : array) {
			modified |= collection.add(element);
		}
		return modified;
	}

	/**
	 * Add all the elements returned by the specified iterable
	 * to the specified list at the specified index.
	 * Return whether the list changed as a result.
	 * <p>
	 * <code>List.addAll(Iterable iterable)</code>
	 */
	public static <E> boolean addAll(List<? super E> list, int index, Iterable<E> iterable) {
		return addAll(list, index, iterable.iterator());
	}

	/**
	 * Add all the elements returned by the specified iterable
	 * to the specified list at the specified index.
	 * Return whether the list changed as a result.
	 * <p>
	 * <code>List.addAll(Iterable iterable)</code>
	 */
	public static <E> boolean addAll(List<? super E> list, int index, Iterable<E> iterable, int size) {
		return addAll(list, index, iterable.iterator(), size);
	}

	/**
	 * Add all the elements returned by the specified iterator
	 * to the specified list at the specified index.
	 * Return whether the list changed as a result.
	 * <p>
	 * <code>List.addAll(Iterator iterator)</code>
	 */
	public static <E> boolean addAll(List<? super E> list, int index, Iterator<? extends E> iterator) {
		return iterator.hasNext() ? list.addAll(index, list(iterator)) : false;
	}

	/**
	 * Add all the elements returned by the specified iterator
	 * to the specified list at the specified index.
	 * Return whether the list changed as a result.
	 * <p>
	 * <code>List.addAll(Iterator iterator)</code>
	 */
	public static <E> boolean addAll(List<? super E> list, int index, Iterator<? extends E> iterator, int size) {
		return iterator.hasNext() ? list.addAll(index, list(iterator, size)) : false;
	}

	/**
	 * Add all the elements in the specified array
	 * to the specified list at the specified index.
	 * Return whether the list changed as a result.
	 * <p>
	 * <code>List.addAll(Object[] array)</code>
	 */
	public static <E> boolean addAll(List<? super E> list, int index, E... array) {
		return (array.length == 0) ? false : list.addAll(index, Arrays.asList(array));
	}


	// ********** bag **********

	/**
	 * Return a bag corresponding to the specified enumeration.
	 * <p>
	 * <code>HashBag(Enumeration enumeration)</code>
	 */
	public static <E> HashBag<E> bag(Enumeration<? extends E> enumeration) {
		return bag(enumeration, new HashBag<E>());
	}

	/**
	 * Return a bag corresponding to the specified enumeration.
	 * The specified enumeration size is a performance hint.
	 * <p>
	 * <code>HashBag(Enumeration enumeration)</code>
	 */
	public static <E> HashBag<E> bag(Enumeration<? extends E> enumeration, int enumerationSize) {
		return bag(enumeration, new HashBag<E>(enumerationSize));
	}

	private static <E> HashBag<E> bag(Enumeration<? extends E> enumeration, HashBag<E> bag) {
		while (enumeration.hasMoreElements()) {
			bag.add(enumeration.nextElement());
		}
		return bag;
	}

	/**
	 * Return a bag corresponding to the specified iterable.
	 * <p>
	 * <code>HashBag(Iterable iterable)</code>
	 */
	public static <E> HashBag<E> bag(Iterable<? extends E> iterable) {
		return bag(iterable.iterator());
	}

	/**
	 * Return a bag corresponding to the specified iterable.
	 * The specified iterable size is a performance hint.
	 * <p>
	 * <code>HashBag(Iterable iterable)</code>
	 */
	public static <E> HashBag<E> bag(Iterable<? extends E> iterable, int iterableSize) {
		return bag(iterable.iterator(), iterableSize);
	}

	/**
	 * Return a bag corresponding to the specified iterator.
	 * <p>
	 * <code>HashBag(Iterator iterator)</code>
	 */
	public static <E> HashBag<E> bag(Iterator<? extends E> iterator) {
		return bag(iterator, new HashBag<E>());
	}

	/**
	 * Return a bag corresponding to the specified iterator.
	 * The specified iterator size is a performance hint.
	 * <p>
	 * <code>HashBag(Iterator iterator)</code>
	 */
	public static <E> HashBag<E> bag(Iterator<? extends E> iterator, int iteratorSize) {
		return bag(iterator, new HashBag<E>(iteratorSize));
	}

	private static <E> HashBag<E> bag(Iterator<? extends E> iterator, HashBag<E> bag) {
		while (iterator.hasNext()) {
			bag.add(iterator.next());
		}
		return bag;
	}

	/**
	 * Return a bag corresponding to the specified array.
	 * <p>
	 * <code>HashBag(Object[] array)</code>
	 */
	public static <E> HashBag<E> bag(E... array) {
		int len = array.length;
		HashBag<E> bag = new HashBag<E>(len);
		for (E item : array) {
			bag.add(item);
		}
		return bag;
	}


	// ********** collection **********

	/**
	 * Return a collection corresponding to the specified enumeration.
	 */
	public static <E> HashBag<E> collection(Enumeration<? extends E> enumeration) {
		return bag(enumeration);
	}

	/**
	 * Return a collection corresponding to the specified enumeration.
	 * The specified enumeration size is a performance hint.
	 */
	public static <E> HashBag<E> collection(Enumeration<? extends E> enumeration, int enumerationSize) {
		return bag(enumeration, enumerationSize);
	}

	/**
	 * Return a collection corresponding to the specified iterable.
	 */
	public static <E> HashBag<E> collection(Iterable<? extends E> iterable) {
		return collection(iterable.iterator());
	}

	/**
	 * Return a collection corresponding to the specified iterable.
	 * The specified iterable size is a performance hint.
	 */
	public static <E> HashBag<E> collection(Iterable<? extends E> iterable, int iterableSize) {
		return collection(iterable.iterator(), iterableSize);
	}

	/**
	 * Return a collection corresponding to the specified iterator.
	 */
	public static <E> HashBag<E> collection(Iterator<? extends E> iterator) {
		return bag(iterator);
	}

	/**
	 * Return a collection corresponding to the specified iterator.
	 * The specified iterator size is a performance hint.
	 */
	public static <E> HashBag<E> collection(Iterator<? extends E> iterator, int iteratorSize) {
		return bag(iterator, iteratorSize);
	}

	/**
	 * Return a collection corresponding to the specified array.
	 */
	public static <E> HashBag<E> collection(E... array) {
		return bag(array);
	}


	// ********** contains **********

	/**
	 * Return whether the specified enumeration contains the
	 * specified element.
	 * <p>
	 * <code>Enumeration.contains(Object o)</code>
	 */
	public static boolean contains(Enumeration<?> enumeration, Object value) {
		if (value == null) {
			while (enumeration.hasMoreElements()) {
				if (enumeration.nextElement() == null) {
					return true;
				}
			}
		} else {
			while (enumeration.hasMoreElements()) {
				if (value.equals(enumeration.nextElement())) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Return whether the specified iterable contains the
	 * specified element.
	 * <p>
	 * <code>Iterable.contains(Object o)</code>
	 */
	public static boolean contains(Iterable<?> iterable, Object value) {
		return contains(iterable.iterator(), value);
	}

	/**
	 * Return whether the specified iterator contains the
	 * specified element.
	 * <p>
	 * <code>Iterator.contains(Object o)</code>
	 */
	public static boolean contains(Iterator<?> iterator, Object value) {
		if (value == null) {
			while (iterator.hasNext()) {
				if (iterator.next() == null) {
					return true;
				}
			}
		} else {
			while (iterator.hasNext()) {
				if (value.equals(iterator.next())) {
					return true;
				}
			}
		}
		return false;
	}


	// ********** contains all **********

	/**
	 * Return whether the specified collection contains all of the
	 * elements in the specified iterable.
	 * <p>
	 * <code>Collection.containsAll(Iterable iterable)</code>
	 */
	public static boolean containsAll(Collection<?> collection, Iterable<?> iterable) {
		return containsAll(collection, iterable.iterator());
	}

	/**
	 * Return whether the specified collection contains all of the
	 * elements in the specified iterator.
	 * <p>
	 * <code>Collection.containsAll(Iterator iterator)</code>
	 */
	public static boolean containsAll(Collection<?> collection, Iterator<?> iterator) {
		while (iterator.hasNext()) {
			if ( ! collection.contains(iterator.next())) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Return whether the specified collection contains all of the
	 * elements in the specified array.
	 * <p>
	 * <code>Collection.containsAll(Object[] array)</code>
	 */
	public static boolean containsAll(Collection<?> collection, Object... array) {
		for (int i = array.length; i-- > 0; ) {
			if ( ! collection.contains(array[i])) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Return whether the specified iterable contains all of the
	 * elements in the specified collection.
	 * <p>
	 * <code>Iterable.containsAll(Collection collection)</code>
	 */
	public static boolean containsAll(Iterable<?> iterable, Collection<?> collection) {
		return containsAll(iterable.iterator(), collection);
	}

	/**
	 * Return whether the specified iterable contains all of the
	 * elements in the specified collection.
	 * The specified iterable size is a performance hint.
	 * <p>
	 * <code>Iterable.containsAll(Collection collection)</code>
	 */
	public static boolean containsAll(Iterable<?> iterable, int iterableSize, Collection<?> collection) {
		return containsAll(iterable.iterator(), iterableSize, collection);
	}

	/**
	 * Return whether the specified iterable 1 contains all of the
	 * elements in the specified iterable 2.
	 * <p>
	 * <code>Iterable.containsAll(Iterable iterable)</code>
	 */
	public static boolean containsAll(Iterable<?> iterable1, Iterable<?> iterable2) {
		return containsAll(iterable1.iterator(), iterable2.iterator());
	}

	/**
	 * Return whether the specified iterable 1 contains all of the
	 * elements in the specified iterable 2.
	 * The specified iterable 1 size is a performance hint.
	 * <p>
	 * <code>Iterable.containsAll(Iterable iterable)</code>
	 */
	public static boolean containsAll(Iterable<?> iterable1, int iterable1Size, Iterable<?> iterable2) {
		return containsAll(iterable1.iterator(), iterable1Size, iterable2.iterator());
	}

	/**
	 * Return whether the specified iterable contains all of the
	 * elements in the specified iterator.
	 * <p>
	 * <code>Iterable.containsAll(Iterator iterator)</code>
	 */
	public static boolean containsAll(Iterable<?> iterable, Iterator<?> iterator) {
		return containsAll(iterable.iterator(), iterator);
	}

	/**
	 * Return whether the specified iterable contains all of the
	 * elements in the specified iterator.
	 * The specified iterable size is a performance hint.
	 * <p>
	 * <code>Iterable.containsAll(Iterator iterator)</code>
	 */
	public static boolean containsAll(Iterable<?> iterable, int iterableSize, Iterator<?> iterator) {
		return containsAll(iterable.iterator(), iterableSize, iterator);
	}

	/**
	 * Return whether the specified iterable contains all of the
	 * elements in the specified array.
	 * <p>
	 * <code>Iterable.containsAll(Object[] array)</code>
	 */
	public static boolean containsAll(Iterable<?> iterable, Object... array) {
		return containsAll(iterable.iterator(), array);
	}

	/**
	 * Return whether the specified iterable contains all of the
	 * elements in the specified array.
	 * The specified iterable size is a performance hint.
	 * <p>
	 * <code>Iterable.containsAll(Object[] array)</code>
	 */
	public static boolean containsAll(Iterable<?> iterable, int iterableSize, Object... array) {
		return containsAll(iterable.iterator(), iterableSize, array);
	}

	/**
	 * Return whether the specified iterator contains all of the
	 * elements in the specified collection.
	 * <p>
	 * <code>Iterator.containsAll(Collection collection)</code>
	 */
	public static boolean containsAll(Iterator<?> iterator, Collection<?> collection) {
		return set(iterator).containsAll(collection);
	}

	/**
	 * Return whether the specified iterator contains all of the
	 * elements in the specified collection.
	 * The specified iterator size is a performance hint.
	 * <p>
	 * <code>Iterator.containsAll(Collection collection)</code>
	 */
	public static boolean containsAll(Iterator<?> iterator, int iteratorSize, Collection<?> collection) {
		return set(iterator, iteratorSize).containsAll(collection);
	}

	/**
	 * Return whether the specified iterator contains all of the
	 * elements in the specified iterable.
	 * <p>
	 * <code>Iterator.containsAll(Iterable iterable)</code>
	 */
	public static boolean containsAll(Iterator<?> iterator, Iterable<?> iterable) {
		return containsAll(set(iterator), iterable);
	}

	/**
	 * Return whether the specified iterator contains all of the
	 * elements in the specified iterable.
	 * The specified iterator size is a performance hint.
	 * <p>
	 * <code>Iterator.containsAll(Iterable iterable)</code>
	 */
	public static boolean containsAll(Iterator<?> iterator, int iteratorSize, Iterable<?> iterable) {
		return containsAll(set(iterator, iteratorSize), iterable);
	}

	/**
	 * Return whether the specified iterator 1 contains all of the
	 * elements in the specified iterator 2.
	 * <p>
	 * <code>Iterator.containsAll(Iterator iterator)</code>
	 */
	public static boolean containsAll(Iterator<?> iterator1, Iterator<?> iterator2) {
		return containsAll(set(iterator1), iterator2);
	}

	/**
	 * Return whether the specified iterator 1 contains all of the
	 * elements in the specified iterator 2.
	 * The specified iterator 1 size is a performance hint.
	 * <p>
	 * <code>Iterator.containsAll(Iterator iterator)</code>
	 */
	public static boolean containsAll(Iterator<?> iterator1, int iterator1Size, Iterator<?> iterator2) {
		return containsAll(set(iterator1, iterator1Size), iterator2);
	}

	/**
	 * Return whether the specified iterator contains all of the
	 * elements in the specified array.
	 * <p>
	 * <code>Iterator.containsAll(Object[] array)</code>
	 */
	public static boolean containsAll(Iterator<?> iterator, Object... array) {
		return containsAll(set(iterator), array);
	}

	/**
	 * Return whether the specified iterator contains all of the
	 * elements in the specified array.
	 * The specified iterator size is a performance hint.
	 * <p>
	 * <code>Iterator.containsAll(Object[] array)</code>
	 */
	public static boolean containsAll(Iterator<?> iterator, int iteratorSize, Object... array) {
		return containsAll(set(iterator, iteratorSize), array);
	}


	// ********** diff **********

	/**
	 * Return the index of the first elements in the specified
	 * lists that are different, beginning at the end.
	 * If the lists are identical, return -1.
	 * If the lists are different sizes, return the index of the
	 * last element in the longer list.
	 * Use the elements' {@link Object#equals()} method to compare the
	 * elements.
	 * <p>
	 * <code>Collections.diffEnd(List list1, List list2)</code>
	 */
	public static int diffEnd(List<?> list1, List<?> list2) {
		return ArrayTools.diffEnd(list1.toArray(), list2.toArray());
	}

	/**
	 * Return the range of elements in the specified
	 * arrays that are different.
	 * If the arrays are identical, return [size, -1].
	 * Use the elements' {@link Object#equals()} method to compare the
	 * elements.
	 * <p>
	 * <code>Collections.diffRange(List list1, List list2)</code>
	 * @see #diffStart(List, List)
	 * @see #diffEnd(List, List)
	 */
	public static Range diffRange(List<?> list1, List<?> list2) {
		return ArrayTools.diffRange(list1.toArray(), list2.toArray());
	}

	/**
	 * Return the index of the first elements in the specified
	 * lists that are different. If the lists are identical, return
	 * the size of the two lists (i.e. one past the last index).
	 * If the lists are different sizes and all the elements in
	 * the shorter list match their corresponding elements in
	 * the longer list, return the size of the shorter list
	 * (i.e. one past the last index of the shorter list).
	 * Use the elements' {@link Object#equals()} method to compare the
	 * elements.
	 * <p>
	 * <code>Collections.diffStart(List list1, List list2)</code>
	 */
	public static int diffStart(List<?> list1, List<?> list2) {
		return ArrayTools.diffStart(list1.toArray(), list2.toArray());
	}


	// ********** identity diff **********

	/**
	 * Return the index of the first elements in the specified
	 * lists that are different, beginning at the end.
	 * If the lists are identical, return -1.
	 * If the lists are different sizes, return the index of the
	 * last element in the longer list.
	 * Use object identity to compare the elements.
	 * <p>
	 * <code>Collections.identityDiffEnd(List list1, List list2)</code>
	 */
	public static int identityDiffEnd(List<?> list1, List<?> list2) {
		return ArrayTools.identityDiffEnd(list1.toArray(), list2.toArray());
	}

	/**
	 * Return the range of elements in the specified
	 * arrays that are different.
	 * If the arrays are identical, return [size, -1].
	 * Use object identity to compare the elements.
	 * <p>
	 * <code>Collections.identityDiffStart(List list1, List list2)</code>
	 * @see #identityDiffStart(List, List)
	 * @see #identityDiffEnd(List, List)
	 */
	public static Range identityDiffRange(List<?> list1, List<?> list2) {
		return ArrayTools.identityDiffRange(list1.toArray(), list2.toArray());
	}

	/**
	 * Return the index of the first elements in the specified
	 * lists that are different. If the lists are identical, return
	 * the size of the two lists (i.e. one past the last index).
	 * If the lists are different sizes and all the elements in
	 * the shorter list match their corresponding elements in
	 * the longer list, return the size of the shorter list
	 * (i.e. one past the last index of the shorter list).
	 * Use object identity to compare the elements.
	 * <p>
	 * <code>Collections.identityDiffStart(List list1, List list2)</code>
	 */
	public static int identityDiffStart(List<?> list1, List<?> list2) {
		return ArrayTools.identityDiffStart(list1.toArray(), list2.toArray());
	}


	// ********** elements are equal **********

	/**
	 * Return whether the specified iterables do not return the same elements
	 * in the same order.
	 */
	public static boolean elementsAreDifferent(Iterable<?> iterable1, Iterable<?> iterable2) {
		return elementsAreDifferent(iterable1.iterator(), iterable2.iterator());
	}

	/**
	 * Return whether the specified iterators do not return the same elements
	 * in the same order.
	 */
	public static boolean elementsAreDifferent(Iterator<?> iterator1, Iterator<?> iterator2) {
		return ! elementsAreEqual(iterator1, iterator2);
	}

	/**
	 * Return whether the specified iterables return equal elements.
	 * <p>
	 * <code>Iterable.elementsAreEqual(Iterable iterable)</code>
	 */
	public static boolean elementsAreEqual(Iterable<?> iterable1, Iterable<?> iterable2) {
		return elementsAreEqual(iterable1.iterator(), iterable2.iterator());
	}

	/**
	 * Return whether the specified iterators return equal elements.
	 * <p>
	 * <code>Iterator.elementsAreEqual(Iterator iterator)</code>
	 */
	public static boolean elementsAreEqual(Iterator<?> iterator1, Iterator<?> iterator2) {
		while (iterator1.hasNext() && iterator2.hasNext()) {
			if (Tools.valuesAreDifferent(iterator1.next(), iterator2.next())) {
				return false;
			}
		}
		return ! (iterator1.hasNext() || iterator2.hasNext());
	}


	// ********** elements are identical **********

	/**
	 * Return whether the specified iterables return the same elements.
	 * <p>
	 * <code>Iterable.identical(Iterable iterable)</code>
	 */
	public static boolean elementsAreIdentical(Iterable<?> iterable1, Iterable<?> iterable2) {
		return elementsAreIdentical(iterable1.iterator(), iterable2.iterator());
	}

	/**
	 * Return whether the specified iterators return the same elements.
	 * <p>
	 * <code>Iterator.identical(Iterator iterator)</code>
	 */
	public static boolean elementsAreIdentical(Iterator<?> iterator1, Iterator<?> iterator2) {
		while (iterator1.hasNext() && iterator2.hasNext()) {
			if (iterator1.next() != iterator2.next()) {
				return false;
			}
		}
		return ! (iterator1.hasNext() || iterator2.hasNext());
	}


	// ********** get **********

	/**
	 * Return the element corresponding to the specified index
	 * in the specified iterable.
	 * <p>
	 * <code>Iterable.get(int index)</code>
	 */
	public static <E> E get(Iterable<? extends E> iterable, int index) {
		return get(iterable.iterator(), index);
	}

	/**
	 * Return the element corresponding to the specified index
	 * in the specified iterator.
	 * <p>
	 * <code>Iterator.get(int index)</code>
	 */
	public static <E> E get(Iterator<? extends E> iterator, int index) {
		int i = 0;
		while (iterator.hasNext()) {
			E next = iterator.next();
			if (i++ == index) {
				return next;
			}
		}
		throw new IndexOutOfBoundsException(String.valueOf(index) + ':' + String.valueOf(i));
	}


	// ********** hash code **********

	public static int hashCode(Iterable<?> iterable) {
		if (iterable == null) {
			return 0;
		}
		int hash = 1;
		for (Object element : iterable) {
			hash = 31 * hash + (element == null ? 0 : element.hashCode());
		}
		return hash;
	}


	// ********** index of **********

	/**
	 * Return the index of the first occurrence of the
	 * specified element in the specified iterable;
	 * return -1 if there is no such index.
	 * <p>
	 * <code>Iterable.indexOf(Object o)</code>
	 */
	public static int indexOf(Iterable<?> iterable, Object value) {
		return indexOf(iterable.iterator(), value);
	}

	/**
	 * Return the index of the first occurrence of the
	 * specified element in the specified iterator;
	 * return -1 if there is no such index.
	 * <p>
	 * <code>Iterator.indexOf(Object o)</code>
	 */
	public static int indexOf(Iterator<?> iterator, Object value) {
		if (value == null) {
			for (int i = 0; iterator.hasNext(); i++) {
				if (iterator.next() == null) {
					return i;
				}
			}
		} else {
			for (int i = 0; iterator.hasNext(); i++) {
				if (value.equals(iterator.next())) {
					return i;
				}
			}
		}
		return -1;
	}


	// ********** insertion index of **********

	/**
	 * Return the maximum index of where the specified comparable object
	 * should be inserted into the specified sorted list and still keep
	 * the list sorted.
	 */
	public static <E extends Comparable<? super E>> int insertionIndexOf(List<E> sortedList, Comparable<E> value) {
		int len = sortedList.size();
		for (int i = 0; i < len; i++) {
			if (value.compareTo(sortedList.get(i)) < 0) {
				return i;
			}
		}
		return len;
	}

	/**
	 * Return the maximum index of where the specified object
	 * should be inserted into the specified sorted list and still keep
	 * the list sorted.
	 */
	public static <E> int insertionIndexOf(List<E> sortedList, E value, Comparator<? super E> comparator) {
		int len = sortedList.size();
		for (int i = 0; i < len; i++) {
			if (comparator.compare(value, sortedList.get(i)) < 0) {
				return i;
			}
		}
		return len;
	}


	// ********** iterable/iterator **********

	/**
	 * Return an iterable on the elements in the specified array.
	 * <p>
	 * <code>Arrays.iterable(Object[] array)</code>
	 */
	public static <E> Iterable<E> iterable(E... array) {
		return new ArrayIterable<E>(array);
	}

	/**
	 * Return an iterator on the elements in the specified array.
	 * <p>
	 * <code>Arrays.iterator(Object[] array)</code>
	 */
	public static <E> Iterator<E> iterator(E... array) {
		return new ArrayIterator<E>(array);
	}


	// ********** last **********

	/**
	 * Return the specified iterable's last element.
	 * <p>
	 * <code>Iterable.last()</code>
	 * 
     * @exception NoSuchElementException iterable is empty.
	 */
	public static <E> E last(Iterable<E> iterable) {
		return last(iterable.iterator());
	}

	/**
	 * Return the specified iterator's last element.
	 * <p>
	 * <code>Iterator.last()</code>
	 * 
     * @exception NoSuchElementException iterator is empty.
	 */
	public static <E> E last(Iterator<E> iterator) {
		E last;
		do {
			last = iterator.next();
		} while (iterator.hasNext());
		return last;
	}


	// ********** last index of **********

	/**
	 * Return the index of the last occurrence of the
	 * specified element in the specified iterable;
	 * return -1 if there is no such index.
	 * <p>
	 * <code>Iterable.lastIndexOf(Object o)
	 */
	public static int lastIndexOf(Iterable<?> iterable, Object value) {
		return lastIndexOf(iterable.iterator(), value);
	}

	/**
	 * Return the index of the last occurrence of the
	 * specified element in the specified iterable;
	 * return -1 if there is no such index.
	 * The specified iterable size is a performance hint.
	 * <p>
	 * <code>Iterable.lastIndexOf(Object o)
	 */
	public static int lastIndexOf(Iterable<?> iterable, int iterableSize, Object value) {
		return lastIndexOf(iterable.iterator(), iterableSize, value);
	}

	/**
	 * Return the index of the last occurrence of the
	 * specified element in the specified iterator;
	 * return -1 if there is no such index.
	 * <p>
	 * <code>Iterator.lastIndexOf(Object o)
	 */
	public static int lastIndexOf(Iterator<?> iterator, Object value) {
		return iterator.hasNext() ? list(iterator).lastIndexOf(value) : -1;
	}

	/**
	 * Return the index of the last occurrence of the
	 * specified element in the specified iterator;
	 * return -1 if there is no such index.
	 * The specified iterator size is a performance hint.
	 * <p>
	 * <code>Iterator.lastIndexOf(Object o)
	 */
	public static int lastIndexOf(Iterator<?> iterator, int iteratorSize, Object value) {
		return iterator.hasNext() ? list(iterator, iteratorSize).lastIndexOf(value) : -1;
	}


	// ********** list **********

	/**
	 * Return a list corresponding to the specified iterable.
	 * <p>
	 * <code>Iterable.toList()</code>
	 */
	public static <E> ArrayList<E> list(Iterable<? extends E> iterable) {
		return list(iterable.iterator());
	}

	/**
	 * Return a list corresponding to the specified iterable.
	 * The specified iterable size is a performance hint.
	 * <p>
	 * <code>Iterable.toList()</code>
	 */
	public static <E> ArrayList<E> list(Iterable<? extends E> iterable, int iterableSize) {
		return list(iterable.iterator(), iterableSize);
	}

	/**
	 * Return a list corresponding to the specified iterator.
	 * <p>
	 * <code>Iterator.toList()</code>
	 */
	public static <E> ArrayList<E> list(Iterator<? extends E> iterator) {
		return list(iterator, new ArrayList<E>());
	}

	/**
	 * Return a list corresponding to the specified iterator.
	 * The specified iterator size is a performance hint.
	 * <p>
	 * <code>Iterator.toList()</code>
	 */
	public static <E> ArrayList<E> list(Iterator<? extends E> iterator, int iteratorSize) {
		return list(iterator, new ArrayList<E>(iteratorSize));
	}

	private static <E> ArrayList<E> list(Iterator<? extends E> iterator, ArrayList<E> list) {
		while (iterator.hasNext()) {
			list.add(iterator.next());
		}
		return list;
	}

	/**
	 * Return a list corresponding to the specified array.
	 * Unlike {@link Arrays#asList(Object[])}, the list
	 * is modifiable and is not backed by the array.
	 */
	public static <E> ArrayList<E> list(E... array) {
		return new ArrayList<E>(Arrays.asList(array));
	}

	/**
	 * Return a list iterator for the specified array.
	 * <p>
	 * <code>Arrays.listIterator(Object[] array)</code>
	 */
	public static <E> ListIterator<E> listIterator(E... array) {
		return listIterator(array, 0);
	}

	/**
	 * Return a list iterator for the specified array
	 * starting at the specified position in the array.
	 * <p>
	 * <code>Arrays.listIterator(Object[] array, int index)</code>
	 */
	public static <E> ListIterator<E> listIterator(E[] array, int start) {
		return listIterator(array, start, array.length - start);
	}

	/**
	 * Return a list iterator for the specified array
	 * starting at the specified position in the array.
	 * <p>
	 * <code>Arrays.listIterator(Object[] array, int index, int length)</code>
	 */
	public static <E> ListIterator<E> listIterator(E[] array, int start, int length) {
		return new ArrayListIterator<E>(array, start, length);
	}


	// ********** move **********

	/**
	 * Move an element from the specified source index to the specified target
	 * index. Return the altered list.
	 * <p>
	 * <code>List.move(int targetIndex, int sourceIndex)</code>
	 */
	public static <E> List<E> move(List<E> list, int targetIndex, int sourceIndex) {
		return (targetIndex == sourceIndex) ? list : move_(list, targetIndex, sourceIndex);
	}

	/**
	 * assume targetIndex != sourceIndex
	 */
	private static <E> List<E> move_(List<E> list, int targetIndex, int sourceIndex) {
		if (list instanceof RandomAccess) {
			// move elements, leaving the list in place
			E temp = list.get(sourceIndex);
			if (targetIndex < sourceIndex) {
				for (int i = sourceIndex; i-- > targetIndex; ) {
					list.set(i + 1, list.get(i));
				}
			} else {
				for (int i = sourceIndex; i < targetIndex; i++) {
					list.set(i, list.get(i + 1));
				}
			}
			list.set(targetIndex, temp);
		} else {
			// remove the element and re-add it at the target index
			list.add(targetIndex, list.remove(sourceIndex));
		}
		return list;
	}

	/**
	 * Move elements from the specified source index to the specified target
	 * index. Return the altered list.
	 * <p>
	 * <code>List.move(int targetIndex, int sourceIndex, int length)</code>
	 */
	public static <E> List<E> move(List<E> list, int targetIndex, int sourceIndex, int length) {
		if ((targetIndex == sourceIndex) || (length == 0)) {
			return list;
		}
		if (length == 1) {
			return move_(list, targetIndex, sourceIndex);
		}
		if (list instanceof RandomAccess) {
			// move elements, leaving the list in place
			ArrayList<E> temp = new ArrayList<E>(list.subList(sourceIndex, sourceIndex + length));
			if (targetIndex < sourceIndex) {
				for (int i = sourceIndex; i-- > targetIndex; ) {
					list.set(i + length, list.get(i));
				}
			} else {
				for (int i = sourceIndex; i < targetIndex; i++) {
					list.set(i, list.get(i + length));
				}
			}
			for (int i = 0; i < length; i++) {
				list.set(targetIndex + i, temp.get(i));
			}
		} else {
			// remove the elements and re-add them at the target index
			list.addAll(targetIndex, removeElementsAtIndex(list, sourceIndex, length));
		}
		return list;
	}


	// ********** remove all **********

	/**
	 * Remove all the elements returned by the specified iterable
	 * from the specified collection.
	 * Return whether the collection changed as a result.
	 * <p>
	 * <code>Collection.removeAll(Iterable iterable)</code>
	 */
	public static boolean removeAll(Collection<?> collection, Iterable<?> iterable) {
		return removeAll(collection, iterable.iterator());
	}

	/**
	 * Remove all the elements returned by the specified iterable
	 * from the specified collection.
	 * Return whether the collection changed as a result.
	 * The specified iterable size is a performance hint.
	 * <p>
	 * <code>Collection.removeAll(Iterable iterable)</code>
	 */
	public static boolean removeAll(Collection<?> collection, Iterable<?> iterable, int iterableSize) {
		return removeAll(collection, iterable.iterator(), iterableSize);
	}

	/**
	 * Remove all the elements returned by the specified iterator
	 * from the specified collection.
	 * Return whether the collection changed as a result.
	 * <p>
	 * <code>Collection.removeAll(Iterator iterator)</code>
	 */
	public static boolean removeAll(Collection<?> collection, Iterator<?> iterator) {
		return iterator.hasNext() ? collection.removeAll(set(iterator)) : false;
	}

	/**
	 * Remove all the elements returned by the specified iterator
	 * from the specified collection.
	 * Return whether the collection changed as a result.
	 * The specified iterator size is a performance hint.
	 * <p>
	 * <code>Collection.removeAll(Iterator iterator)</code>
	 */
	public static boolean removeAll(Collection<?> collection, Iterator<?> iterator, int iteratorSize) {
		return iterator.hasNext() ? collection.removeAll(set(iterator, iteratorSize)) : false;
	}

	/**
	 * Remove all the elements in the specified array
	 * from the specified collection.
	 * Return whether the collection changed as a result.
	 * <p>
	 * <code>Collection.removeAll(Object[] array)</code>
	 */
	public static boolean removeAll(Collection<?> collection, Object... array) {
		return (array.length == 0) ? false : collection.removeAll(set(array));
	}


	// ********** remove all occurrences **********

	/**
	 * Remove all occurrences of the specified element
	 * from the specified collection.
	 * Return whether the collection changed as a result.
	 * <p>
	 * <code>Collection.removeAllOccurrences(Object value)</code>
	 */
	public static boolean removeAllOccurrences(Collection<?> collection, Object value) {
		boolean modified = false;
		Iterator<?> stream = collection.iterator();
		if (value == null) {
			while (stream.hasNext()) {
				if (stream.next() == null) {
					stream.remove();
					modified = true;
				}
			}
		} else {
			while (stream.hasNext()) {
				if (value.equals(stream.next())) {
					stream.remove();
					modified = true;
				}
			}
		}
		return modified;
	}


	// ********** remove elements at index **********

	/**
	 * Remove the elements at the specified index.
	 * Return the removed elements.
	 * <p>
	 * <code>List.remove(int index, int length)</code>
	 */
	public static <E> ArrayList<E> removeElementsAtIndex(List<E> list, int index, int length) {
		List<E> subList = list.subList(index, index + length);
		ArrayList<E> result = new ArrayList<E>(subList);
		subList.clear();
		return result;
	}


	// ********** remove duplicate elements **********

	/**
	 * Remove any duplicate elements from the specified list,
	 * while maintaining the order.
	 * Return whether the list changed as a result.
	 */
	public static <E> boolean removeDuplicateElements(List<E> list) {
		int size = list.size();
		if ((size == 0) || (size == 1)) {
			return false;
		}
		return removeDuplicateElements(list, size);
	}

	/**
	 * assume list is non-empty
	 */
	static <E> boolean removeDuplicateElements(List<E> list, int size) {
		LinkedHashSet<E> temp = new LinkedHashSet<E>(size);		// take advantage of hashed look-up
		boolean modified = false;
		for (E item : list) {
			if ( ! temp.add(item)) {
				modified = true;  // duplicate item
			}
		}
		if (modified) {
			int i = 0;
			for (E e : temp) {
				list.set(i, e);
				i++;
			}
			int tempSize = temp.size();
			for (i = list.size(); i-- > tempSize; ) {
				list.remove(i);  // pull off the end
			}
		}
		return modified;
	}


	// ********** retain all **********

	/**
	 * Retain only the elements in the specified iterable
	 * in the specified collection.
	 * Return whether the collection changed as a result.
	 * <p>
	 * <code>Collection.retainAll(Iterable iterable)</code>
	 */
	public static boolean retainAll(Collection<?> collection, Iterable<?> iterable) {
		return retainAll(collection, iterable.iterator());
	}

	/**
	 * Retain only the elements in the specified iterable
	 * in the specified collection.
	 * Return whether the collection changed as a result.
	 * The specified iterable size is a performance hint.
	 * <p>
	 * <code>Collection.retainAll(Iterable iterable)</code>
	 */
	public static boolean retainAll(Collection<?> collection, Iterable<?> iterable, int iterableSize) {
		return retainAll(collection, iterable.iterator(), iterableSize);
	}

	/**
	 * Retain only the elements in the specified iterator
	 * in the specified collection.
	 * Return whether the collection changed as a result.
	 * <p>
	 * <code>Collection.retainAll(Iterator iterator)</code>
	 */
	public static boolean retainAll(Collection<?> collection, Iterator<?> iterator) {
		if (iterator.hasNext()) {
			return collection.retainAll(set(iterator));
		}
		if (collection.isEmpty()) {
			return false;
		}
		collection.clear();
		return true;
	}

	/**
	 * Retain only the elements in the specified iterator
	 * in the specified collection.
	 * Return whether the collection changed as a result.
	 * The specified iterator size is a performance hint.
	 * <p>
	 * <code>Collection.retainAll(Iterator iterator)</code>
	 */
	public static boolean retainAll(Collection<?> collection, Iterator<?> iterator, int iteratorSize) {
		if (iterator.hasNext()) {
			return collection.retainAll(set(iterator, iteratorSize));
		}
		if (collection.isEmpty()) {
			return false;
		}
		collection.clear();
		return true;
	}

	/**
	 * Retain only the elements in the specified array
	 * in the specified collection.
	 * Return whether the collection changed as a result.
	 * <p>
	 * <code>Collection.retainAll(Object[] array)</code>
	 */
	public static boolean retainAll(Collection<?> collection, Object... array) {
		if (array.length > 0) {
			return collection.retainAll(set(array));
		}
		if (collection.isEmpty()) {
			return false;
		}
		collection.clear();
		return true;
	}


	// ********** reverse list **********

	/**
	 * Return a list with entries in reverse order from those
	 * returned by the specified iterable.
	 * <p>
	 * <code>Iterable.reverseList()</code>
	 */
	public static <E> List<E> reverseList(Iterable<? extends E> iterable) {
		return reverseList(iterable.iterator());
	}

	/**
	 * Return a list with entries in reverse order from those
	 * returned by the specified iterable.
	 * The specified iterable size is a performance hint.
	 * <p>
	 * <code>Iterable.reverseList()</code>
	 */
	public static <E> List<E> reverseList(Iterable<? extends E> iterable, int iterableSize) {
		return reverseList(iterable.iterator(), iterableSize);
	}

	/**
	 * Return a list with entries in reverse order from those
	 * returned by the specified iterator.
	 * <p>
	 * <code>Iterator.reverseList()</code>
	 */
	public static <E> List<E> reverseList(Iterator<? extends E> iterator) {
		return reverse(list(iterator));
	}

	/**
	 * Return a list with entries in reverse order from those
	 * returned by the specified iterator.
	 * The specified iterator size is a performance hint.
	 * <p>
	 * <code>Iterator.reverseList()</code>
	 */
	public static <E> List<E> reverseList(Iterator<? extends E> iterator, int size) {
		return reverse(list(iterator, size));
	}


	// ********** rotate **********

	/**
	 * Return the list after it has been "rotated" by one position.
	 * <p>
	 * <code>List.rotate()</code>
	 */
	public static <E> List<E> rotate(List<E> list) {
		return rotate(list, 1);
	}


	// ********** set **********

	/**
	 * Return a set corresponding to the specified iterable.
	 * <p>
	 * <code>HashSet(Iterable iterable)</code>
	 */
	public static <E> HashSet<E> set(Iterable<? extends E> iterable) {
		return set(iterable.iterator());
	}

	/**
	 * Return a set corresponding to the specified iterable.
	 * The specified iterable size is a performance hint.
	 * <p>
	 * <code>HashSet(Iterable iterable)</code>
	 */
	public static <E> HashSet<E> set(Iterable<? extends E> iterable, int iterableSize) {
		return set(iterable.iterator(), iterableSize);
	}

	/**
	 * Return a set corresponding to the specified iterator.
	 * <p>
	 * <code>HashSet(Iterator iterator)</code>
	 */
	public static <E> HashSet<E> set(Iterator<? extends E> iterator) {
		return set(iterator, new HashSet<E>());
	}

	/**
	 * Return a set corresponding to the specified iterator.
	 * The specified iterator size is a performance hint.
	 * <p>
	 * <code>HashSet(Iterator iterator)</code>
	 */
	public static <E> HashSet<E> set(Iterator<? extends E> iterator, int iteratorSize) {
		return set(iterator, new HashSet<E>(iteratorSize));
	}

	private static <E> HashSet<E> set(Iterator<? extends E> iterator, HashSet<E> set) {
		while (iterator.hasNext()) {
			set.add(iterator.next());
		}
		return set;
	}

	/**
	 * Return a set corresponding to the specified array.
	 * <p>
	 * <code>HashSet(Object[] array)</code>
	 */
	public static <E> HashSet<E> set(E... array) {
		HashSet<E> set = new HashSet<E>(array.length);
		for (int i = array.length; i-- > 0;) {
			set.add(array[i]);
		}
		return set;
	}


	// ********** singleton iterator **********

	/**
	 * Return an iterator that returns only the single,
	 * specified object.
	 * <p>
	 * <code>Object.toIterator()</code>
	 */
	public static <E> Iterator<E> singletonIterator(E value) {
		return new SingleElementIterator<E>(value);
	}

	/**
	 * Return a list iterator that returns only the single,
	 * specified object.
	 * <p>
	 * <code>Object.toListIterator()</code>
	 */
	public static <E> ListIterator<E> singletonListIterator(E value) {
		return new SingleElementListIterator<E>(value);
	}


	// ********** size **********

	/**
	 * Return the number of elements returned by the specified iterable.
	 * <p>
	 * <code>Iterable.size()</code>
	 */
	public static int size(Iterable<?> iterable) {
		return size(iterable.iterator());
	}

	/**
	 * Return the number of elements returned by the specified iterator.
	 * <p>
	 * <code>Iterator.size()</code>
	 */
	public static int size(Iterator<?> iterator) {
		int size = 0;
		while (iterator.hasNext()) {
			iterator.next();
			size++;
		}
		return size;
	}
	
	/**
	 * Return whether the specified iterable is empty
	 * (Shortcuts the iterator rather than calculating the entire size)
	 */
	public static boolean isEmpty(Iterable<?> iterable) {
		return isEmpty(iterable.iterator());
	}
	
	/**
	 * Return whether the specified iterator is empty
	 * (Shortcuts the iterator rather than calculating the entire size)
	 */
	public static boolean isEmpty(Iterator<?> iterator) {
		return ! iterator.hasNext();
	}
	
	
	// ********** sort **********

	/**
	 * Return an iterable containing the sorted elements of the specified iterable.
	 * <p>
	 * <code>Iterable.sort()</code>
	 */
	public static <E extends Comparable<? super E>> Iterable<E> sort(Iterable<E> iterable) {
		return sort(iterable, null);
	}

	/**
	 * Return an iterable containing the sorted elements of the specified iterable.
	 * The specified iterable size is a performance hint.
	 * <p>
	 * <code>Iterable.sort()</code>
	 */
	public static <E extends Comparable<? super E>> Iterable<E> sort(Iterable<E> iterable, int iterableSize) {
		return sort(iterable, null, iterableSize);
	}

	/**
	 * Return an iterable containing the sorted elements of the specified iterable.
	 * <p>
	 * <code>Iterable.sort(Comparator comparator)</code>
	 */
	public static <E> Iterable<E> sort(Iterable<E> iterable, Comparator<? super E> comparator) {
		return sort(list(iterable), comparator);
	}

	/**
	 * Return an iterable containing the sorted elements of the specified iterable.
	 * The specified iterable size is a performance hint.
	 * <p>
	 * <code>Iterable.sort(Comparator comparator)</code>
	 */
	public static <E> Iterable<E> sort(Iterable<E> iterable, Comparator<? super E> comparator, int iterableSize) {
		return sort(list(iterable, iterableSize), comparator);
	}

	/**
	 * Return the iterator after it has been "sorted".
	 * <p>
	 * <code>Iterator.sort()</code>
	 */
	public static <E extends Comparable<? super E>> ListIterator<E> sort(Iterator<? extends E> iterator) {
		return sort(iterator, null);
	}

	/**
	 * Return the iterator after it has been "sorted".
	 * The specified iterator size is a performance hint.
	 * <p>
	 * <code>Iterator.sort()</code>
	 */
	public static <E extends Comparable<? super E>> ListIterator<E> sort(Iterator<? extends E> iterator, int iteratorSize) {
		return sort(iterator, null, iteratorSize);
	}

	/**
	 * Return the iterator after it has been "sorted".
	 * <p>
	 * <code>Iterator.sort(Comparator comparator)</code>
	 */
	public static <E> ListIterator<E> sort(Iterator<? extends E> iterator, Comparator<? super E> comparator) {
		return sort(list(iterator), comparator).listIterator();
	}

	/**
	 * Return the iterator after it has been "sorted".
	 * The specified iterator size is a performance hint.
	 * <p>
	 * <code>Iterator.sort(Comparator comparator)</code>
	 */
	public static <E> ListIterator<E> sort(Iterator<? extends E> iterator, Comparator<? super E> comparator, int iteratorSize) {
		return sort(list(iterator, iteratorSize), comparator).listIterator();
	}


	// ********** sorted set **********

	/**
	 * Return a sorted set corresponding to the specified iterable.
	 * <p>
	 * <code>TreeSet(Iterable iterable)</code>
	 */
	public static <E extends Comparable<? super E>> TreeSet<E> sortedSet(Iterable<? extends E> iterable) {
		return sortedSet(iterable.iterator());
	}

	/**
	 * Return a sorted set corresponding to the specified iterable.
	 * The specified iterable size is a performance hint.
	 * <p>
	 * <code>TreeSet(Iterable iterable)</code>
	 */
	public static <E extends Comparable<? super E>> TreeSet<E> sortedSet(Iterable<? extends E> iterable, int iterableSize) {
		return sortedSet(iterable.iterator(), iterableSize);
	}

	/**
	 * Return a sorted set corresponding to the specified iterable
	 * and comparator.
	 * <p>
	 * <code>TreeSet(Iterable iterable, Comparator c)</code>
	 */
	public static <E> TreeSet<E> sortedSet(Iterable<? extends E> iterable, Comparator<? super E> comparator) {
		return sortedSet(iterable.iterator(), comparator);
	}

	/**
	 * Return a sorted set corresponding to the specified iterable
	 * and comparator.
	 * The specified iterable size is a performance hint.
	 * <p>
	 * <code>TreeSet(Iterable iterable, Comparator c)</code>
	 */
	public static <E> TreeSet<E> sortedSet(Iterable<? extends E> iterable, Comparator<? super E> comparator, int iterableSize) {
		return sortedSet(iterable.iterator(), comparator, iterableSize);
	}

	/**
	 * Return a sorted set corresponding to the specified iterator.
	 * <p>
	 * <code>TreeSet(Iterator iterator)</code>
	 */
	public static <E extends Comparable<? super E>> TreeSet<E> sortedSet(Iterator<? extends E> iterator) {
		return sortedSet(iterator, null);
	}

	/**
	 * Return a sorted set corresponding to the specified iterator.
	 * The specified iterator size is a performance hint.
	 * <p>
	 * <code>TreeSet(Iterator iterator)</code>
	 */
	public static <E extends Comparable<? super E>> TreeSet<E> sortedSet(Iterator<? extends E> iterator, int iteratorSize) {
		return sortedSet(iterator, null, iteratorSize);
	}

	/**
	 * Return a sorted set corresponding to the specified iterator
	 * and comparator.
	 * <p>
	 * <code>TreeSet(Iterator iterator, Comparator c)</code>
	 */
	public static <E> TreeSet<E> sortedSet(Iterator<? extends E> iterator, Comparator<? super E> comparator) {
		return sortedSet(list(iterator), comparator);
	}

	/**
	 * Return a sorted set corresponding to the specified iterator
	 * and comparator.
	 * The specified iterator size is a performance hint.
	 * <p>
	 * <code>TreeSet(Iterator iterator, Comparator c)</code>
	 */
	public static <E> TreeSet<E> sortedSet(Iterator<? extends E> iterator, Comparator<? super E> comparator, int iteratorSize) {
		return sortedSet(list(iterator, iteratorSize), comparator);
	}

	private static <E> TreeSet<E> sortedSet(List<E> list, Comparator<? super E> comparator) {
		TreeSet<E> sortedSet = new TreeSet<E>(comparator);
		sortedSet.addAll(list);
		return sortedSet;
	}

	/**
	 * Return a sorted set corresponding to the specified array.
	 * <p>
	 * <code>TreeSet(Object[] array)</code>
	 */
	public static <E extends Comparable<? super E>> TreeSet<E> sortedSet(E... array) {
		return sortedSet(array, null);
	}

	/**
	 * Return a sorted set corresponding to the specified array
	 * and comparator.
	 * <p>
	 * <code>TreeSet(Object[] array, Comparator c)</code>
	 */
	public static <E> TreeSet<E> sortedSet(E[] array, Comparator<? super E> comparator) {
		TreeSet<E> sortedSet = new TreeSet<E>(comparator);
		sortedSet.addAll(Arrays.asList(array));
		return sortedSet;
	}


	// ********** Old School Vector **********

	/**
	 * Return a vector corresponding to the specified iterable.
	 * This is useful for legacy code that requires a {@link Vector}.
	 * <p>
	 * <code>Vector(Iterable iterable)</code>
	 */
	public static <E> Vector<E> vector(Iterable<? extends E> iterable) {
		return vector(iterable.iterator());
	}

	/**
	 * Return a vector corresponding to the specified iterable.
	 * This is useful for legacy code that requires a {@link Vector}.
	 * <p>
	 * <code>Vector(Iterable iterable, int size)</code>
	 */
	public static <E> Vector<E> vector(Iterable<? extends E> iterable, int size) {
		return vector(iterable.iterator(), size);
	}

	/**
	 * Return a vector corresponding to the specified iterator.
	 * This is useful for legacy code that requires a {@link Vector}.
	 * <p>
	 * <code>Vector(Iterator iterator)</code>
	 */
	public static <E> Vector<E> vector(Iterator<? extends E> iterator) {
		return vector(iterator, new Vector<E>());
	}

	/**
	 * Return a vector corresponding to the specified iterator.
	 * This is useful for legacy code that requires a {@link Vector}.
	 * <p>
	 * <code>Vector(Iterator iterator, int size)</code>
	 */
	public static <E> Vector<E> vector(Iterator<? extends E> iterator, int size) {
		return vector(iterator, new Vector<E>(size));
	}

	private static <E> Vector<E> vector(Iterator<? extends E> iterator, Vector<E> v) {
		while (iterator.hasNext()) {
			v.addElement(iterator.next());
		}
		return v;
	}

	/**
	 * Return a vector corresponding to the specified array.
	 * This is useful for legacy code that requires a {@link Vector}.
	 * <p>
	 * <code>Vector(Object... array)</code>
	 */
	public static <E> Vector<E> vector(E... array) {
		Vector<E> v = new Vector<E>(array.length);
		for (E item : array) {
			v.addElement(item);
		}
		return v;
	}


	// ********** single-use Iterable **********

	/**
	 * Return a one-use {@link Iterable} for the specified {@link Iterator}.
	 * Throw an {@link IllegalStateException} if {@link Iterable#iterator()}
	 * is called more than once.
	 * As such, this utility should only be used in one-use situations, such as
	 * a foreach loop.
	 */
	public static <E> Iterable<E> iterable(Iterator<? extends E> iterator) {
		return new SingleUseIterable<E>(iterator);
	}

	/**
	 * This is a one-time use iterable that can return a single iterator.
	 * Once the iterator is returned the iterable is no longer valid.
	 * As such, this utility should only be used in one-time use situations,
	 * such as a 'for-each' loop.
	 */
	public static class SingleUseIterable<E> implements Iterable<E> {
		private Iterator<E> iterator;

		public SingleUseIterable(Iterator<? extends E> iterator) {
			super();
			if (iterator == null) {
				throw new NullPointerException();
			}
			this.iterator = new SuperIteratorWrapper<E>(iterator);
		}

		public Iterator<E> iterator() {
			if (this.iterator == null) {
				throw new IllegalStateException("This method has already been called."); //$NON-NLS-1$
			}
			Iterator<E> result = this.iterator;
			this.iterator = null;
			return result;
		}

		@Override
		public String toString() {
			return StringTools.buildToStringFor(this, this.iterator);
		}

	}


	// ********** java.util.Collections enhancements **********

	/**
	 * Return the destination list after the source list has been copied into it.
	 * @see Collections#copy(List, List)
	 */
	public static <E> List<E> copy(List<E> dest, List<? extends E> src) {
		Collections.copy(dest, src);
		return dest;
	}

	/**
	 * Return the list after it has been "filled".
	 * @see Collections#fill(List, Object)
	 */
	public static <E> List<E> fill(List<E> list, E value) {
		Collections.fill(list, value);
		return list;
	}

	/**
	 * Return the list after it has been "reversed".
	 * @see Collections#reverse(List)
	 */
	public static <E> List<E> reverse(List<E> list) {
		Collections.reverse(list);
		return list;
	}

	/**
	 * Return the list after it has been "rotated".
	 * @see Collections#rotate(List, int)
	 */
	public static <E> List<E> rotate(List<E> list, int distance) {
		Collections.rotate(list, distance);
		return list;
	}

	/**
	 * Return the list after it has been "shuffled".
	 * @see Collections#shuffle(List)
	 */
	public static <E> List<E> shuffle(List<E> list) {
		Collections.shuffle(list);
		return list;
	}

	/**
	 * Return the list after it has been "shuffled".
	 * @see Collections#shuffle(List, Random)
	 */
	public static <E> List<E> shuffle(List<E> list, Random random) {
		Collections.shuffle(list, random);
		return list;
	}

	/**
	 * Return the list after it has been "sorted".
	 * NB: The list is sorted in place as a side-effect.
	 * @see Collections#sort(List)
	 */
	public static <E extends Comparable<? super E>> List<E> sort(List<E> list) {
		Collections.sort(list);
		return list;
	}

	/**
	 * Return the list after it has been "sorted".
	 * NB: The list is sorted in place as a side-effect.
	 * @see Collections#sort(List, Comparator)
	 */
	public static <E> List<E> sort(List<E> list, Comparator<? super E> comparator) {
		Collections.sort(list, comparator);
		return list;
	}

	/**
	 * Return the list after the specified elements have been "swapped".
	 * @see Collections#swap(List, int, int)
	 */
	public static <E> List<E> swap(List<E> list, int i, int j) {
		Collections.swap(list, i, j);
		return list;
	}


	// ********** constructor **********

	/**
	 * Suppress default constructor, ensuring non-instantiability.
	 */
	private CollectionTools() {
		super();
		throw new UnsupportedOperationException();
	}

}
