org.eclipse.xtext.xbase.lib.IterableExtensions.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.xtext.xbase.lib.IterableExtensions.java

Source

/*******************************************************************************
 * Copyright (c) 2011 itemis AG (http://www.itemis.eu) and others.
 * 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
 *******************************************************************************/
package org.eclipse.xtext.xbase.lib;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedSet;

import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.Functions.Function2;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure2;
import org.eclipse.xtext.xbase.lib.internal.BooleanFunctionDelegate;
import org.eclipse.xtext.xbase.lib.internal.FunctionDelegate;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

/**
 * This is an extension library for {@link Iterable iterables}.
 * 
 * @author Sven Efftinge - Initial contribution and API
 * @author Sebastian Zarnekow
 */
@GwtCompatible
public class IterableExtensions {

    /**
     * <p>
     * Concatenates two iterables into a single iterable. The returned iterable has an iterator that traverses the
     * elements in {@code a}, followed by the elements in {@code b}. The resulting iterable is effectivly a view on the
     * source iterables. That is, the source iterators are not polled until necessary and the result will reflect
     * changes in the sources.
     * </p>
     * <p>
     * The returned iterable's iterator supports {@code remove()} when the corresponding input iterator supports it.
     * </p>
     * 
     * @param a
     *            the first iterable. May not be <code>null</code>.
     * @param b
     *            the second iterable. May not be <code>null</code>.
     * @return a combined iterable. Never <code>null</code>.
     */
    @Pure
    @Inline(value = "$3.$4concat($1, $2)", imported = Iterables.class)
    public static <T> Iterable<T> operator_plus(Iterable<? extends T> a, Iterable<? extends T> b) {
        return Iterables.concat(a, b);
    }

    /**
     * Finds the first element in the given iterable that fulfills the predicate. If none is found or the iterable is
     * empty, <code>null</code> is returned.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @param predicate
     *            the predicate. May not be <code>null</code>.
     * @return the first element in the iterable for which the given predicate returns <code>true</code>, returns
     *         <code>null</code> if no element matches the predicate or the iterable is empty.
     */
    public static <T> T findFirst(Iterable<T> iterable, Function1<? super T, Boolean> predicate) {
        return IteratorExtensions.findFirst(iterable.iterator(), predicate);
    }

    /**
     * Finds the last element in the given iterable that fulfills the predicate. If none is found or the iterable is
     * empty, <code>null</code> is returned.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @param predicate
     *            the predicate. May not be <code>null</code>.
     * @return the last element in the iterable for which the given predicate returns <code>true</code>, returns
     *         <code>null</code> if no element matches the predicate or the iterable is empty.
     */
    public static <T> T findLast(Iterable<T> iterable, Functions.Function1<? super T, Boolean> predicate) {
        if (predicate == null)
            throw new NullPointerException("predicate");
        if (iterable instanceof List<?>) {
            List<T> list = (List<T>) iterable;
            ListIterator<T> iterator = list.listIterator(list.size());
            while (iterator.hasPrevious()) {
                T t = iterator.previous();
                if (predicate.apply(t))
                    return t;
            }
            return null;
        } else {
            return IteratorExtensions.findLast(iterable.iterator(), predicate);
        }
    }

    /**
     * Returns the first element in the given iterable or <code>null</code> if empty.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @return the first element in the iterable or <code>null</code>.
     */
    public static <T> T head(Iterable<T> iterable) {
        return IteratorExtensions.head(iterable.iterator());
    }

    /**
     * Returns a view on this iterable that contains all the elements except the first.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @return an iterable with all elements except the first. Never <code>null</code>.
     * @see #drop(Iterable, int)
     */
    public static <T> Iterable<T> tail(final Iterable<T> iterable) {
        return drop(iterable, 1);
    }

    /**
     * Returns the last element in the given iterable or <code>null</code> if empty.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @return the last element in the iterable or <code>null</code>.
     */
    public static <T> T last(Iterable<T> iterable) {
        if (iterable instanceof List<?>) {
            List<T> list = (List<T>) iterable;
            if (list.isEmpty())
                return null;
            return list.get(list.size() - 1);
        } else if (iterable instanceof SortedSet) {
            SortedSet<T> sortedSet = (SortedSet<T>) iterable;
            if (sortedSet.isEmpty())
                return null;
            return sortedSet.last();
        } else {
            return IteratorExtensions.last(iterable.iterator());
        }
    }

    /**
     * Returns a view on this iterable that provides at most the first <code>count</code> entries.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @param count
     *            the number of elements that should be returned at most.
     * @return an iterable with <code>count</code> elements. Never <code>null</code>.
     * @throws IllegalArgumentException
     *             if <code>count</code> is negative.
     */
    public static <T> Iterable<T> take(final Iterable<T> iterable, final int count) {
        if (iterable == null)
            throw new NullPointerException("iterable");
        if (count < 0)
            throw new IllegalArgumentException(
                    "Cannot take a negative number of elements. Argument 'count' was: " + count);
        if (count == 0)
            return Collections.emptyList();
        return new Iterable<T>() {
            @Override
            public Iterator<T> iterator() {
                return IteratorExtensions.take(iterable.iterator(), count);
            }
        };
    }

    /**
     * Returns a view on this iterable that provides all elements except the first <code>count</code> entries.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @param count
     *            the number of elements that should be dropped.
     * @return an iterable without the first <code>count</code> elements. Never <code>null</code>.
     * @throws IllegalArgumentException
     *             if <code>count</code> is negative.
     */
    @Pure
    public static <T> Iterable<T> drop(final Iterable<T> iterable, final int count) {
        if (iterable == null)
            throw new NullPointerException("iterable");
        if (count == 0)
            return iterable;
        if (count < 0)
            throw new IllegalArgumentException(
                    "Cannot drop a negative number of elements. Argument 'count' was: " + count);
        return new Iterable<T>() {
            @Override
            public Iterator<T> iterator() {
                return IteratorExtensions.drop(iterable.iterator(), count);
            }
        };
    }

    /**
     * Returns {@code true} if one or more elements in {@code iterable} satisfy the predicate.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @param predicate
     *            the predicate. May not be <code>null</code>.
     * @return <code>true</code> if one or more elements in {@code iterable} satisfy the predicate.
     */
    public static <T> boolean exists(Iterable<T> iterable, Function1<? super T, Boolean> predicate) {
        return IteratorExtensions.exists(iterable.iterator(), predicate);
    }

    /**
     * Returns {@code true} if every element in {@code iterable} satisfies the predicate. If {@code iterable} is empty,
     * {@code true} is returned. In other words, <code>false</code> is returned if at least one element fails to fulfill
     * the predicate.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @param predicate
     *            the predicate. May not be <code>null</code>.
     * @return <code>true</code> if every element in {@code iterable} satisfies the predicate and also if there is no element.
     */
    public static <T> boolean forall(Iterable<T> iterable, Function1<? super T, Boolean> predicate) {
        return IteratorExtensions.forall(iterable.iterator(), predicate);
    }

    /**
     * Returns the elements of {@code unfiltered} that satisfy a predicate. The resulting iterable's iterator does not
     * support {@code remove()}. The returned iterable is a view on the original elements. Changes in the unfiltered
     * original are reflected in the view.
     * 
     * @param unfiltered
     *            the unfiltered iterable. May not be <code>null</code>.
     * @param predicate
     *            the predicate. May not be <code>null</code>.
     * @return an iterable that contains only the elements that fulfill the predicate. Never <code>null</code>.
     */
    @Pure
    public static <T> Iterable<T> filter(Iterable<T> unfiltered, Function1<? super T, Boolean> predicate) {
        return Iterables.filter(unfiltered, new BooleanFunctionDelegate<T>(predicate));
    }

    /**
     * Returns all instances of class {@code type} in {@code unfiltered}. The returned iterable has elements whose class
     * is {@code type} or a subclass of {@code type}. The returned iterable's iterator does not support {@code remove()}
     * . The returned iterable is a view on the original elements. Changes in the unfiltered original are reflected in
     * the view.
     * 
     * @param unfiltered
     *            the unfiltered iterable. May not be <code>null</code>.
     * @param type
     *            the type of elements desired
     * @return an unmodifiable iterable containing all elements of the original iterable that were of the requested
     *         type. Never <code>null</code>.
     */
    @GwtIncompatible("Class.isInstance")
    @Pure
    @Inline(value = "$3.$4filter($1, $2)", imported = Iterables.class)
    public static <T> Iterable<T> filter(Iterable<?> unfiltered, Class<T> type) {
        return Iterables.filter(unfiltered, type);
    }

    /**
     * Returns a new iterable filtering any null references.
     * 
     * @param unfiltered
     *            the unfiltered iterable. May not be <code>null</code>.
     * @return an unmodifiable iterable containing all elements of the original iterable without any <code>null</code> references. Never <code>null</code>.
     */
    @Pure
    public static <T> Iterable<T> filterNull(Iterable<T> unfiltered) {
        return Iterables.filter(unfiltered, Predicates.notNull());
    }

    /**
     * Returns an iterable that performs the given {@code transformation} for each element of {@code original} when
     * requested. The mapping is done lazily. That is, subsequent iterations of the elements in the iterable will
     * repeatedly apply the transformation.
     * 
     * The returned iterable's iterator supports {@code remove()} if the provided iterator does. After a successful
     * {@code remove()} call, {@code original} no longer contains the corresponding element.
     * 
     * @param original
     *            the original iterable. May not be <code>null</code>.
     * @param transformation
     *            the transformation. May not be <code>null</code>.
     * @return an iterable that provides the result of the transformation. Never <code>null</code>.
     */
    @Pure
    public static <T, R> Iterable<R> map(Iterable<T> original, Function1<? super T, ? extends R> transformation) {
        return Iterables.transform(original, new FunctionDelegate<T, R>(transformation));
    }

    /**
     * Combines multiple iterables into a single iterable. The returned iterable has an iterator that traverses the
     * elements of each iterable in {@code inputs}. The input iterators are not polled until necessary.
     * 
     * <p>
     * The returned iterable's iterator supports {@code remove()} when the corresponding input iterator supports it. The
     * methods of the returned iterable may throw {@code NullPointerException} if any of the input iterators are null.
     * 
     * @param inputs
     *            the to be flattened iterables. May not be <code>null</code>.
     * @return an iterable that provides the concatenated values of the input elements. Never <code>null</code>.
     */
    @Inline(value = "$2.$3concat($1)", imported = Iterables.class)
    public static <T> Iterable<T> flatten(Iterable<? extends Iterable<? extends T>> inputs) {
        return Iterables.concat(inputs);
    }

    /**
     * Applies {@code procedure} for each element of the given iterable.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @param procedure
     *            the procedure. May not be <code>null</code>.
     */
    public static <T> void forEach(Iterable<T> iterable, Procedure1<? super T> procedure) {
        IteratorExtensions.forEach(iterable.iterator(), procedure);
    }

    /**
     * Applies {@code procedure} for each element of the given iterable.
     * The procedure takes the element and a loop counter. If the counter would overflow, {@link Integer#MAX_VALUE}
     * is returned for all subsequent elements. The first element is at index zero.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @param procedure
     *            the procedure. May not be <code>null</code>.
     * @since 2.3
     */
    public static <T> void forEach(Iterable<T> iterable, Procedure2<? super T, ? super Integer> procedure) {
        IteratorExtensions.forEach(iterable.iterator(), procedure);
    }

    /**
     * Returns the concatenated string representation of the elements in the given iterable. No delimiter is used.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @return the string representation of the iterable's elements. Never <code>null</code>.
     * @see #join(Iterable, CharSequence, org.eclipse.xtext.xbase.lib.Functions.Function1)
     */
    public static String join(Iterable<?> iterable) {
        return IteratorExtensions.join(iterable.iterator());
    }

    /**
     * Returns the concatenated string representation of the elements in the given iterable. The {@code separator} is
     * used to between each pair of entries in the input. The string <code>null</code> is used for <code>null</code>
     * entries in the input.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @param separator
     *            the separator. May not be <code>null</code>.
     * @return the string representation of the iterable's elements. Never <code>null</code>.
     * @see #join(Iterable, CharSequence, org.eclipse.xtext.xbase.lib.Functions.Function1)
     */
    public static String join(Iterable<?> iterable, CharSequence separator) {
        return IteratorExtensions.join(iterable.iterator(), separator);
    }

    /**
     * Returns the concatenated string representation of the elements in the given iterable. The {@code function} is
     * used to compute the string for each element. The {@code separator} is used to between each pair of entries in the
     * input. The string <code>null</code> is used if the function yields <code>null</code> as the string representation
     * for an entry.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @param separator
     *            the separator. May not be <code>null</code>.
     * @param function
     *            the function that is used to compute the string representation of a single element. May not be
     *            <code>null</code>.
     * @return the string representation of the iterable's elements. Never <code>null</code>.
     */
    public static <T> String join(Iterable<T> iterable, CharSequence separator,
            Functions.Function1<? super T, ? extends CharSequence> function) {
        return IteratorExtensions.join(iterable.iterator(), separator, function);
    }

    /**
     * Returns the concatenated string representation of the elements in the given iterable. The {@code function} is
     * used to compute the string for each element. The {@code separator} is used to between each pair of entries in the
     * input. The string <code>null</code> is used if the function yields <code>null</code> as the string representation
     * for an entry.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @param before
     *            prepends the resulting string if the iterable contains at least one element. May be <code>null</code> which is equivalent to passing an empty string.
     * @param separator
     *            the separator. May be <code>null</code> which is equivalent to passing an empty string.
     * @param after
     *            appended to the resulting string if the iterable contain at least one element. May be <code>null</code> which is equivalent to passing an empty string.
     * @param function
     *            the function that is used to compute the string representation of a single element. May not be
     *            <code>null</code>.
     * @return the string representation of the iterable's elements. Never <code>null</code>.
     */
    public static <T> String join(Iterable<T> iterable, CharSequence before, CharSequence separator,
            CharSequence after, Functions.Function1<? super T, ? extends CharSequence> function) {
        return IteratorExtensions.join(iterable.iterator(), before, separator, after, function);
    }

    /**
     * Determines whether two iterables contain equal elements in the same order. More specifically, this method returns
     * {@code true} if {@code iterable} and {@code other} contain the same number of elements and every element of
     * {@code iterable} is equal to the corresponding element of {@code other}.
     * 
     * @param iterable
     *            an iterable. May not be <code>null</code>.
     * @param other
     *            an iterable. May not be <code>null</code>.
     * @return <code>true</code> if the two iterables contain equal elements in the same order.
     */
    public static boolean elementsEqual(Iterable<?> iterable, Iterable<?> other) {
        return Iterables.elementsEqual(iterable, other);
    }

    /**
     * Determines if the given iterable is <code>null</code> or contains no elements.
     * 
     * @param iterable
     *            the to-be-queried iterable. May be <code>null</code>.
     * @return {@code true} if the iterable is <code>null</code> or contains no elements
     */
    public static boolean isNullOrEmpty(Iterable<?> iterable) {
        return iterable == null || isEmpty(iterable);
    }

    /**
     * Determines if the given iterable contains no elements.
     * 
     * @param iterable
     *            the to-be-queried iterable. May not be <code>null</code>.
     * @return {@code true} if the iterable contains no elements
     * @see #isNullOrEmpty(Iterable)
     */
    public static boolean isEmpty(Iterable<?> iterable) {
        if (iterable instanceof Collection<?>)
            return ((Collection<?>) iterable).isEmpty();
        return !iterable.iterator().hasNext();
    }

    /**
     * Returns the number of elements in {@code iterable}.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @return the number of elements in {@code iterable}.
     */
    public static int size(Iterable<?> iterable) {
        return Iterables.size(iterable);
    }

    /**
     * <p>
     * Applies the combinator {@code function} to all elements of the iterable in turn.
     * </p>
     * <p>
     * One of the function parameters is an element of the iterable, and the other is the result of previous application
     * of the function. The seed of the operation is the first element in the iterable. The second value is computed by
     * applying the function to the seed together with the second element of the iterable. The third value is computed
     * from the previous result together with the third element and so on. In other words, the previous result of each
     * step is taken and passed together with the next element to the combinator function.
     * </p>
     * <p>
     * If the iterable is empty, <code>null</code> is returned.
     * </p>
     * <p>
     * More formally, given an iterable {@code [a, b, c, d]} and a function {@code f}, the result of {@code reduce} is
     * <code>f(f(f(a, b), c), d)</code>
     * </p>
     * 
     * @param iterable
     *            the to-be-reduced iterable. May not be <code>null</code>.
     * @param function
     *            the combinator function. May not be <code>null</code>.
     * @return the last result of the applied combinator function or <code>null</code> for the empty input.
     */
    public static <T> T reduce(Iterable<? extends T> iterable,
            Function2<? super T, ? super T, ? extends T> function) {
        return IteratorExtensions.reduce(iterable.iterator(), function);
    }

    /**
     * <p>
     * Applies the combinator {@code function} to all elements of the iterable in turn and uses {@code seed} as the
     * start value.
     * </p>
     * <p>
     * One of the function parameters is an element of the iterable, and the other is the result of previous application
     * of the function. The seed of the operation is explicitly passed to
     * {@link #fold(Iterable, Object, org.eclipse.xtext.xbase.lib.Functions.Function2) fold}. The first computed value
     * is the result of the applied function for {@code seed} and the first element of the iterable. This intermediate
     * result together with the second element of the iterable produced the next result and so on.
     * </p>
     * <p>
     * {@link #fold(Iterable, Object, org.eclipse.xtext.xbase.lib.Functions.Function2) fold} is similar to
     * {@link #reduce(Iterable, org.eclipse.xtext.xbase.lib.Functions.Function2) reduce} but allows a {@code seed} value
     * and the combinator {@code function} may be asymmetric. It takes {@code T and R} and returns {@code R}.
     * <p>
     * If the iterable is empty, <code>seed</code> is returned.
     * </p>
     * <p>
     * More formally, given an iterable {@code [a, b, c, d]}, a seed {@code initial} and a function {@code f}, the
     * result of {@code fold} is <code>f(f(f(f(initial, a), b), c), d)</code>
     * </p>
     * 
     * @param iterable
     *            the to-be-folded iterable. May not be <code>null</code>.
     * @param seed
     *            the initial value. May be <code>null</code>.
     * @param function
     *            the combinator function. May not be <code>null</code>.
     * @return the last result of the applied combinator function or <code>seed</code> for the empty input.
     */
    public static <T, R> R fold(Iterable<T> iterable, R seed,
            Function2<? super R, ? super T, ? extends R> function) {
        return IteratorExtensions.fold(iterable.iterator(), seed, function);
    }

    /**
     * Returns a list that contains all the entries of the given iterable in the same order. If the iterable is of type
     * {@link List}, itself is returned. Therefore an unchecked cast is performed. 
     * In all other cases, the result list is a copy of the iterable.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @return a list with the same entries as the given iterable. May be the same as the given iterable iff it
     *         implements {@link List}, otherwise a copy is returned. Never <code>null</code>.
     */
    @Beta
    public static <T> List<T> toList(Iterable<T> iterable) {
        if (iterable instanceof List<?>) {
            List<T> result = (List<T>) iterable;
            return result;
        }
        return Lists.newArrayList(iterable);
    }

    /**
     * Returns a set that contains all the unique entries of the given iterable in the order of their appearance. If the
     * iterable is of type {@link Set}, itself is returned. Therefore an unchecked cast is performed.
     * In all other cases, the result set is a copy of the iterable with stable order.
     * 
     * @param iterable
     *            the iterable. May not be <code>null</code>.
     * @return a set with the unique entries of the given iterable. May be the same as the given iterable iff it
     *         implements {@link Set}, otherwise a copy is returned. Never <code>null</code>.
     */
    @Beta
    public static <T> Set<T> toSet(Iterable<T> iterable) {
        if (iterable instanceof Set<?>) {
            Set<T> result = (Set<T>) iterable;
            return result;
        }
        return Sets.newLinkedHashSet(iterable);
    }

    /**
     * Returns a map for which the {@link Map#values} are computed by the given function, and each key is an element in
     * the given {@code keys}. If the iterable contains equal keys more than once, the last one will be contained in the
     * map. The map is computed eagerly. That is, subsequent changes in the keys are not reflected by the map.
     * 
     * @param keys
     *            the keys to use when constructing the {@code Map}. May not be <code>null</code>.
     * @param computeValues
     *            the function used to produce the values for each key. May not be <code>null</code>.
     * @return a map mapping each entry in the given iterable to the corresponding result when evaluating the function
     *         {@code computeValues}.
     */
    public static <K, V> Map<K, V> toInvertedMap(Iterable<? extends K> keys,
            Function1<? super K, V> computeValues) {
        return IteratorExtensions.toInvertedMap(keys.iterator(), computeValues);
    }

    /**
     * Returns a map for which the {@link Map#values} are the given elements in the given order, and each key is the
     * product of invoking a supplied function {@code computeKeys} on its corresponding value. If the function produces
     * the same key for different values, the last one will be contained in the map.
     * 
     * @param values
     *            the values to use when constructing the {@code Map}. May not be <code>null</code>.
     * @param computeKeys
     *            the function used to produce the key for each value. May not be <code>null</code>.
     * @return a map mapping the result of evaluating the function {@code keyFunction} on each value in the input
     *         collection to that value
     */
    public static <K, V> Map<K, V> toMap(Iterable<? extends V> values, Function1<? super V, K> computeKeys) {
        return IteratorExtensions.toMap(values.iterator(), computeKeys);
    }

    /**
     * Returns a map for which the {@link Map#values} is a collection of lists, where the elements in the list will 
     * appear in the order as they appeared in the iterable. Each key is the product of invoking the supplied 
     * function {@code computeKeys} on its corresponding value. So a key of that map groups a list of values for 
     * which the function produced exactly that key.  
     * 
     * @param values
     *            the values to use when constructing the {@code Map}. May not be <code>null</code>.
     * @param computeKeys
     *            the function used to produce the key for each value. May not be <code>null</code>.
     * @return a map mapping the result of evaluating the function {@code keyFunction} on each value in the input
     *         iterable to that value. As there can be more than one value mapped by a key, the mapping result is is a
     *         list of values.
     * @since 2.7
     */
    public static <K, V> Map<K, List<V>> groupBy(Iterable<? extends V> values,
            Function1<? super V, ? extends K> computeKeys) {
        return IteratorExtensions.groupBy(values.iterator(), computeKeys);
    }

    /**
     * Creates a sorted list that contains the items of the given iterable. The resulting list is in ascending order,
     * according to the natural ordering of the elements in the iterable.
     * 
     * @param iterable
     *            the items to be sorted. May not be <code>null</code>.
     * @return a sorted list as a shallow copy of the given iterable.
     * @see Collections#sort(List)
     * @see #sort(Iterable, Comparator)
     * @see #sortBy(Iterable, org.eclipse.xtext.xbase.lib.Functions.Function1)
     * @see ListExtensions#sortInplace(List)
     */
    public static <T extends Comparable<? super T>> List<T> sort(Iterable<T> iterable) {
        List<T> asList = Lists.newArrayList(iterable);
        if (iterable instanceof SortedSet<?>) {
            if (((SortedSet<T>) iterable).comparator() == null) {
                return asList;
            }
        }
        return ListExtensions.sortInplace(asList);
    }

    /**
     * This method is deprecated in favor of {@link #sortWith(Iterable, Comparator)}.
     * 
     * Creates a sorted list that contains the items of the given iterable. The resulting list is sorted according to
     * the order induced by the specified comparator.
     * 
     * @param iterable
     *            the items to be sorted. May not be <code>null</code>.
     * @param comparator
     *            the comparator to be used. May be <code>null</code> to indicate that the natural ordering of the
     *            elements should be used.
     * @return a sorted list as a shallow copy of the given iterable.
     * @see IterableExtensions#sortWith(Iterable, Comparator)
     * @deprecated Use {@link #sortWith(Iterable, Comparator)} instead.
     */
    @Deprecated
    @Inline(value = "$3.$4sortWith($1, $2)", imported = IterableExtensions.class)
    public static <T> List<T> sort(Iterable<T> iterable, Comparator<? super T> comparator) {
        return sortWith(iterable, comparator);
    }

    /**
     * Creates a sorted list that contains the items of the given iterable. The resulting list is sorted according to
     * the order induced by the specified comparator.
     * 
     * @param iterable
     *            the items to be sorted. May not be <code>null</code>.
     * @param comparator
     *            the comparator to be used. May be <code>null</code> to indicate that the natural ordering of the
     *            elements should be used.
     * @return a sorted list as a shallow copy of the given iterable.
     * @see Collections#sort(List, Comparator)
     * @see #sort(Iterable)
     * @see #sortBy(Iterable, org.eclipse.xtext.xbase.lib.Functions.Function1)
     * @see ListExtensions#sortInplace(List, Comparator)
     * @since 2.7
     */
    public static <T> List<T> sortWith(Iterable<T> iterable, Comparator<? super T> comparator) {
        return ListExtensions.sortInplace(Lists.newArrayList(iterable), comparator);
    }

    /**
     * Creates a sorted list that contains the items of the given iterable. The resulting list is sorted according to
     * the order induced by applying a key function to each element which yields a comparable criteria.
     * 
     * @param iterable
     *            the elements to be sorted. May not be <code>null</code>.
     * @param key
     *            the key function to-be-used. May not be <code>null</code>.
     * @return a sorted list as a shallow copy of the given iterable.
     * @see #sort(Iterable)
     * @see #sort(Iterable, Comparator)
     * @see ListExtensions#sortInplaceBy(List, org.eclipse.xtext.xbase.lib.Functions.Function1)
     */
    public static <T, C extends Comparable<? super C>> List<T> sortBy(Iterable<T> iterable,
            final Functions.Function1<? super T, C> key) {
        return ListExtensions.sortInplaceBy(Lists.newArrayList(iterable), key);
    }

    /**
     * Returns an Iterable containing all elements starting from the head of the source up to and excluding the first
     * element that violates the predicate The resulting Iterable is a lazily computed view, so any modifications to the
     * underlying Iterables will be reflected on subsequent iterations. The result's Iterator does not support
     * {@link Iterator#remove()}
     * 
     * @param iterable
     *            the elements from which to take. May not be <code>null</code>.
     * @param predicate
     *            the predicate which decides whether to keep taking elements. May not be <code>null</code>.
     * @return the taken elements
     * @since 2.7
     */
    public static <T> Iterable<T> takeWhile(final Iterable<? extends T> iterable,
            final Function1<? super T, Boolean> predicate) {
        if (iterable == null)
            throw new NullPointerException("iterable");
        if (predicate == null)
            throw new NullPointerException("predicate");
        return new Iterable<T>() {
            @Override
            public Iterator<T> iterator() {
                return IteratorExtensions.takeWhile(iterable.iterator(), predicate);
            }
        };
    }

    /**
     * Returns an Iterable containing all elements starting from the first element for which the drop-predicate returned
     * false. The resulting Iterable is a lazily computed view, so any modifications to the underlying Iterables will be
     * reflected on subsequent iterations. The result's Iterator does not support {@link Iterator#remove()}
     * 
     * @param iterable
     *            the elements from which to drop. May not be <code>null</code>.
     * @param predicate
     *            the predicate which decides whether to keep dropping elements. May not be <code>null</code>.
     * @return the remaining elements after dropping
     * @since 2.7
     */
    public static <T> Iterable<T> dropWhile(final Iterable<? extends T> iterable,
            final Function1<? super T, Boolean> predicate) {
        if (iterable == null)
            throw new NullPointerException("iterable");
        if (predicate == null)
            throw new NullPointerException("predicate");
        return new Iterable<T>() {
            @Override
            public Iterator<T> iterator() {
                return IteratorExtensions.dropWhile(iterable.iterator(), predicate);
            }
        };
    }

    /**
     * Returns an Iterable of Pairs where the nth pair is created by taking the nth element of the source as the value
     * its 0-based index as the key. E.g. <code>zipWitIndex(#["a", "b", "c"]) == #[(0, "a"), (1, "b"), (2, "c")]</code>
     * 
     * If the index would overflow, {@link Integer#MAX_VALUE} is returned for all subsequent elements.
     * 
     * The resulting Iterable is a lazily computed view, so any modifications to the underlying Iterable will be
     * reflected on iteration. The result's Iterator does not support {@link Iterator#remove()}
     * 
     * @param iterable
     *            the elements. May not be <code>null</code>.
     * @return the zipped result
     * @since 2.7
     */
    public static <A> Iterable<Pair<Integer, A>> indexed(final Iterable<? extends A> iterable) {
        if (iterable == null)
            throw new NullPointerException("iterable");
        return new Iterable<Pair<Integer, A>>() {
            @Override
            public Iterator<Pair<Integer, A>> iterator() {
                return IteratorExtensions.indexed(iterable.iterator());
            }
        };
    }

    /**
     * Finds the minimum of the given elements according to their natural ordering. If there are several mimina, the
     * first one will be returned.
     * 
     * @param iterable
     *            the mutually comparable elements. May not be <code>null</code>.
     * @return the minimum
     * @throws NoSuchElementException
     *             if the iterable is empty
     * @since 2.7
     */
    public static <T extends Comparable<? super T>> T min(final Iterable<T> iterable) {
        if (iterable instanceof SortedSet<?>) {
            SortedSet<T> asSet = (SortedSet<T>) iterable;
            // only use the set-semantic if we can be absolutely sure that the set uses the natural order
            if (asSet.comparator() == null)
                return asSet.first();
        }
        return IteratorExtensions.min(iterable.iterator());
    }

    /**
     * Finds the element that yields the minimum value when passed to <code>compareBy</code>. If there are several
     * minima, the first one will be returned.
     * 
     * @param iterable
     *            the elements to find the minimum of. May not be <code>null</code>.
     * @param compareBy
     *            a function that returns a comparable characteristic to compare the elements by. May not be <code>null</code>.
     * @return the minimum
     * @throws NoSuchElementException
     *             if the iterable is empty
     * @since 2.7
     */
    public static <T, C extends Comparable<? super C>> T minBy(final Iterable<T> iterable,
            final Function1<? super T, C> compareBy) {
        return IteratorExtensions.minBy(iterable.iterator(), compareBy);
    }

    /**
     * Finds the mininmum element according to <code>comparator</code>. If there are several minima, the first one will
     * be returned.
     * 
     * @param iterable
     *            the elements to find the minimum of. May not be <code>null</code>.
     * @param comparator
     *            the comparison function. May not be <code>null</code>.
     * @return the minimum
     * @throws NoSuchElementException
     *             if the iterable is empty
     * @since 2.7
     */
    public static <T> T min(final Iterable<T> iterable, Comparator<? super T> comparator) {
        return IteratorExtensions.min(iterable.iterator(), comparator);
    }

    /**
     * Finds the maximum of the elements according to their natural ordering. If there are several maxima, the first one
     * will be returned.
     * 
     * @param iterable
     *            the mutually comparable elements. May not be <code>null</code>.
     * @return the maximum
     * @throws NoSuchElementException
     *             if the iterable is empty
     * @since 2.7
     */
    public static <T extends Comparable<? super T>> T max(final Iterable<T> iterable) {
        // cannot special-case for SortedSet since we want to find the first one that is a maximum
        // where Set.last would return the last of the seemingly equal maximum elements
        return IteratorExtensions.max(iterable.iterator());
    }

    /**
     * Finds the element that yields the maximum value when passed to <code>compareBy</code> If there are several
     * maxima, the first one will be returned.
     * 
     * @param iterable
     *            the elements to find the maximum of. May not be <code>null</code>.
     * @param compareBy
     *            a function that returns a comparable characteristic to compare the elements by. May not be <code>null</code>.
     * @return the maximum
     * @throws NoSuchElementException
     *             if the iterable is empty
     * @since 2.7
     */
    public static <T, C extends Comparable<? super C>> T maxBy(final Iterable<T> iterable,
            final Function1<? super T, C> compareBy) {
        return IteratorExtensions.maxBy(iterable.iterator(), compareBy);
    }

    /**
     * Finds the maximum element according to <code>comparator</code>. If there are several maxima, the first one will
     * be returned.
     * 
     * @param iterable
     *            the elements to find the maximum of. May not be <code>null</code>.
     * @param comparator
     *            the comparison function. May not be <code>null</code>.
     * @return the maximum
     * @throws NoSuchElementException
     *             if the iterable is empty
     * @since 2.7
     */
    public static <T> T max(final Iterable<T> iterable, Comparator<? super T> comparator) {
        return IteratorExtensions.max(iterable.iterator(), comparator);
    }
}