blob: 33eafb09d68a98cdbdd913bbbdb49a09d3f4c7fb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2017 itemis AG (http://www.itemis.eu) and others.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
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 the elements of {@code unfiltered} that do not 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 do not fulfill the predicate. Never <code>null</code>.
*
* @since 2.11
*/
@Pure
public static <T> Iterable<T> reject(Iterable<T> unfiltered, Function1<? super T, Boolean> predicate) {
return Iterables.filter(unfiltered, Predicates.not(new BooleanFunctionDelegate<T>(predicate)));
}
/**
* Returns the elements of {@code unfiltered} that are not instanceof {@code type}. 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 type
* the type of elements undesired. May not be <code>null</code>.
* @return an iterable that contains only the elements that are not instances of {@code type}. Never <code>null</code>.
* Note that the elements of the iterable can be null as null is an instance of nothing.
*
* @since 2.15
*/
@GwtIncompatible("Class.isInstance")
@Pure
public static <T> Iterable<T> reject(Iterable<T> unfiltered, Class<?> type) {
return filter(unfiltered, (t) -> !type.isInstance(t));
}
/**
* 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.
* <p>
* 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.
* </p>
*
* @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));
}
/**
* 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.
* <p>
* The transformation maps each element to an iterable, and all resulting iterables are combined to a single iterable.
* Effectively a combination of {@link #map(Iterable, Functions.Function1)} and {@link #flatten(Iterable)} is performed.
* </p>
* <p>
* The returned iterable's iterator <i>does not support {@code remove()}</i> in contrast to {@link #map(Iterable, Functions.Function1)}.
* </p>
*
* @param original
* the original iterable. May not be <code>null</code>.
* @param transformation
* the transformation. May not be <code>null</code> and must not yield <code>null</code>.
* @return an iterable that provides the result of the transformation. Never <code>null</code>.
*
* @since 2.13
*/
@Pure
public static <T, R> Iterable<R> flatMap(Iterable<T> original, Function1<? super T, ? extends Iterable<R>> transformation) {
return flatten(map(original, 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.
* </p>
*
* @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} are the product of invoking supplied function {@code computeValues}
* on input iterable elements, and each key is the product of invoking a supplied function {@code computeKeys} on same elements.
* If the function produces the same key for different values, the last one will be contained in the map.
*
* @param inputs
* the elements 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>.
* @param computeValues
* the function used to produce the values for each key. May not be <code>null</code>.
* @return a map mapping the result of evaluating the functions {@code keyFunction} and {@code computeValues} on each value in the input
* iterator to that value
*/
public static <T, K, V> Map<K, V> toMap(Iterable<? extends T> inputs, Function1<? super T, K> computeKeys, Function1<? super T, V> computeValues) {
return IteratorExtensions.toMap(inputs.iterator(),computeKeys,computeValues);
}
/**
* 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);
}
/**
* Returns <tt>true</tt> if this Iterable contains the specified element.
* More formally, returns <tt>true</tt> if and only if this Iterable contains
* at least one element <tt>e</tt> such that
* <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
*
* @param iterable
* the elements to test
* @param o
* element whose presence in the Iterable is to be tested
* @return <tt>true</tt> if this Iterable contains the specified element
*/
public static boolean contains(Iterable<?> iterable, Object o) {
if (iterable instanceof Collection<?>) {
return ((Collection<?>) iterable).contains(o);
}
return IteratorExtensions.contains(iterable.iterator(), o);
}
}