| /******************************************************************************* |
| * Copyright (c) 2011, 2020 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.ArrayList; |
| import java.util.Comparator; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.NoSuchElementException; |
| import java.util.Objects; |
| import java.util.Set; |
| |
| 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 org.eclipse.xtext.xbase.lib.internal.KeyComparator; |
| |
| import com.google.common.annotations.GwtCompatible; |
| import com.google.common.annotations.GwtIncompatible; |
| import com.google.common.base.Joiner; |
| import com.google.common.base.Predicates; |
| import com.google.common.collect.AbstractIterator; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.common.collect.Iterators; |
| import com.google.common.collect.Lists; |
| import com.google.common.collect.Maps; |
| import com.google.common.collect.Ordering; |
| import com.google.common.collect.Sets; |
| |
| /** |
| * This is an extension library for {@link Iterator iterators}. |
| * |
| * @author Sven Efftinge - Initial contribution and API |
| * @author Sebastian Zarnekow |
| */ |
| @GwtCompatible public class IteratorExtensions { |
| |
| /** |
| * Wraps an {@link Iterator} in an {@link Iterable}. WARNING: The resulting |
| * {@link Iterable} may be used (e.g. calling |
| * {@link IterableExtensions#isEmpty(Iterable)}) / iterated (e.g. in a for |
| * loop) only once. If you want to create a reusable {@link Iterable} call |
| * {@link IterableExtensions#toList(Iterable)} or |
| * {@link IterableExtensions#toSet(Iterable)} on the result and reuse the |
| * resulting {@link List} / {@link Set} |
| * @param iterator the {@link Iterator} to wrap in an {@link Iterable}. May not be <code>null</code>. |
| * @return an {@link Iterable} providing the given {@link Iterator}. Never <code>null</code>. |
| */ |
| @Pure |
| public static <T> Iterable<T> toIterable(final Iterator<T> iterator) { |
| if (iterator == null) |
| throw new NullPointerException("iterator"); |
| return new Iterable<T>() { |
| @Override |
| public Iterator<T> iterator() { |
| return iterator; |
| } |
| }; |
| } |
| |
| /** |
| * <p> |
| * Concatenates two iterators into a single iterator. The returned iterator traverses the |
| * elements in {@code a}, followed by the elements in {@code b}. The resulting iterator is effectivly a view on the |
| * source iterators. That is, the source iterators are not polled until necessary and the result will reflect |
| * changes in the sources. |
| * </p> |
| * <p> |
| * The returned iterator supports {@code remove()} when the corresponding input iterator supports it. |
| * </p> |
| * |
| * @param a |
| * the first iterator. May not be <code>null</code>. |
| * @param b |
| * the second iterator. May not be <code>null</code>. |
| * @return a combined iterator. Never <code>null</code>. |
| */ |
| @Pure |
| @Inline(value="$3.$4concat($1, $2)", imported=Iterators.class) |
| public static <T> Iterator<T> operator_plus(Iterator<? extends T> a, Iterator<? extends T> b) { |
| return Iterators.concat(a, b); |
| } |
| |
| /** |
| * Finds the first element in the given iterator that fulfills the predicate. If none is found or the iterator is |
| * empty, <code>null</code> is returned. |
| * |
| * @param iterator |
| * the iterator. May not be <code>null</code>. |
| * @param predicate |
| * the predicate. May not be <code>null</code>. |
| * @return the first element in the iterator for which the given predicate returns <code>true</code>, returns |
| * <code>null</code> if no element matches the predicate or the iterator is empty. |
| */ |
| public static <T> T findFirst(Iterator<T> iterator, Function1<? super T, Boolean> predicate) { |
| if (predicate == null) |
| throw new NullPointerException("predicate"); |
| while(iterator.hasNext()) { |
| T t = iterator.next(); |
| if (predicate.apply(t)) |
| return t; |
| } |
| return null; |
| } |
| |
| /** |
| * Finds the last element in the given iterator that fulfills the predicate. If none is found or the iterator is |
| * empty, <code>null</code> is returned. |
| * |
| * @param iterator |
| * the iterator. May not be <code>null</code>. |
| * @param predicate |
| * the predicate. May not be <code>null</code>. |
| * @return the last element in the iterator for which the given predicate returns <code>true</code>, returns |
| * <code>null</code> if no element matches the predicate or the iterator is empty. |
| */ |
| public static <T> T findLast(Iterator<T> iterator, Functions.Function1<? super T, Boolean> predicate) { |
| if (predicate == null) |
| throw new NullPointerException("predicate"); |
| T result = null; |
| while(iterator.hasNext()) { |
| T t = iterator.next(); |
| if (predicate.apply(t)) |
| result = t; |
| } |
| return result; |
| } |
| |
| /** |
| * Returns the first element in the given iterator or <code>null</code> if empty. |
| * |
| * @param iterator |
| * the iterator. May not be <code>null</code>. |
| * @return the first element in the iterator or <code>null</code>. |
| */ |
| public static <T> T head(Iterator<T> iterator) { |
| if (iterator.hasNext()) |
| return iterator.next(); |
| return null; |
| } |
| |
| /** |
| * Returns a view on this iterator that contains all the elements except the first. |
| * |
| * @param iterator |
| * the iterator. May not be <code>null</code>. |
| * @return an iterator with all elements except the first. Never <code>null</code>. |
| * @see #drop(Iterator, int) |
| */ |
| public static <T> Iterator<T> tail(final Iterator<T> iterator) { |
| return drop(iterator, 1); |
| } |
| |
| /** |
| * Returns the last element in the given iterator or <code>null</code> if empty. |
| * |
| * @param iterator |
| * the iterator. May not be <code>null</code>. |
| * @return the last element in the iterator or <code>null</code>. |
| */ |
| public static <T> T last(Iterator<T> iterator) { |
| T result = null; |
| while(iterator.hasNext()) { |
| result = iterator.next(); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a view on this iterator that provides at most the first <code>count</code> entries. |
| * |
| * @param iterator |
| * the iterator. May not be <code>null</code>. |
| * @param count |
| * the number of elements that should be returned at most. |
| * @return an iterator with <code>count</code> elements. Never <code>null</code>. |
| * @throws IllegalArgumentException |
| * if <code>count</code> is negative. |
| */ |
| @Pure |
| public static <T> Iterator<T> take(final Iterator<T> iterator, final int count) { |
| if (iterator == null) |
| throw new NullPointerException("iterator"); |
| if (count < 0) |
| throw new IllegalArgumentException("Cannot take a negative number of elements. Argument 'count' was: " |
| + count); |
| if (count == 0) |
| return ImmutableSet.<T>of().iterator(); |
| return new AbstractIterator<T>() { |
| |
| private int remaining = count; |
| |
| @Override |
| protected T computeNext() { |
| if (remaining <= 0) |
| return endOfData(); |
| if (!iterator.hasNext()) |
| return endOfData(); |
| remaining--; |
| return iterator.next(); |
| } |
| }; |
| } |
| |
| /** |
| * Returns a view on this iterator that provides all elements except the first <code>count</code> entries. |
| * |
| * @param iterator |
| * the iterator. May not be <code>null</code>. |
| * @param count |
| * the number of elements that should be dropped. |
| * @return an iterator without the first <code>count</code> elements. Never <code>null</code>. |
| * @throws IllegalArgumentException |
| * if <code>count</code> is negative. |
| */ |
| public static <T> Iterator<T> drop(final Iterator<T> iterator, final int count) { |
| if (iterator == null) |
| throw new NullPointerException("iterator"); |
| if (count == 0) |
| return iterator; |
| if (count < 0) |
| throw new IllegalArgumentException("Cannot drop a negative number of elements. Argument 'count' was: " |
| + count); |
| return new AbstractIterator<T>() { |
| { |
| int i = count; |
| while (i > 0 && iterator.hasNext()) { |
| iterator.next(); |
| i--; |
| } |
| } |
| |
| @Override |
| protected T computeNext() { |
| if (!iterator.hasNext()) |
| return endOfData(); |
| return iterator.next(); |
| } |
| }; |
| } |
| |
| /** |
| * Returns {@code true} if one or more elements in {@code iterator} satisfy the predicate. |
| * |
| * <p>Note that this will advance or even exhaust the given iterator.</p> |
| * |
| * @param iterator |
| * the iterator. 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 iterator} satisfy the predicate. |
| */ |
| public static <T> boolean exists(Iterator<T> iterator, Function1<? super T, Boolean> predicate) { |
| if (predicate == null) |
| throw new NullPointerException("predicate"); |
| while(iterator.hasNext()) { |
| if (predicate.apply(iterator.next())) |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Returns {@code true} if every element in {@code iterator} satisfies the predicate. If {@code iterator} 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 iterator |
| * the iterator. 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 iterator} satisfies the predicate and also if there is no element. |
| */ |
| public static <T> boolean forall(Iterator<T> iterator, Function1<? super T, Boolean> predicate) { |
| if (predicate == null) |
| throw new NullPointerException("predicate"); |
| while(iterator.hasNext()) { |
| if (!predicate.apply(iterator.next())) |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Returns the elements of {@code unfiltered} that satisfy a predicate. The resulting iterator does not |
| * support {@code remove()}. The returned iterator is a view on the original elements. Changes in the unfiltered |
| * original are reflected in the view. |
| * |
| * @param unfiltered |
| * the unfiltered iterator. May not be <code>null</code>. |
| * @param predicate |
| * the predicate. May not be <code>null</code>. |
| * @return an iterator that contains only the elements that fulfill the predicate. Never <code>null</code>. |
| */ |
| @Pure |
| public static <T> Iterator<T> filter(Iterator<T> unfiltered, Function1<? super T, Boolean> predicate) { |
| return Iterators.filter(unfiltered, new BooleanFunctionDelegate<T>(predicate)); |
| } |
| |
| /** |
| * Returns the elements of {@code unfiltered} that do not satisfy a predicate. The resulting iterator does not |
| * support {@code remove()}. The returned iterator is a view on the original elements. Changes in the unfiltered |
| * original are reflected in the view. |
| * |
| * @param unfiltered |
| * the unfiltered iterator. May not be <code>null</code>. |
| * @param predicate |
| * the predicate. May not be <code>null</code>. |
| * @return an iterator that contains only the elements that do not fulfill the predicate. Never <code>null</code>. |
| */ |
| @Pure |
| public static <T> Iterator<T> reject(Iterator<T> unfiltered, Function1<? super T, Boolean> predicate) { |
| return Iterators.filter(unfiltered, Predicates.not(new BooleanFunctionDelegate<T>(predicate))); |
| } |
| |
| /** |
| * Returns all instances of class {@code type} in {@code unfiltered}. The returned iterator has elements whose class |
| * is {@code type} or a subclass of {@code type}. The returned iterator does not support {@code remove()}. |
| * The returned iterator is a view on the original elements. Changes in the unfiltered original are reflected in |
| * the view. |
| * |
| * @param unfiltered |
| * the unfiltered iterator. May not be <code>null</code>. |
| * @param type |
| * the type of elements desired |
| * @return an unmodifiable iterator containing all elements of the original iterator that were of the requested |
| * type. Never <code>null</code>. |
| */ |
| @Pure |
| @GwtIncompatible("Class.isInstance") |
| @Inline(value="$3.$4filter($1, $2)", imported=Iterators.class) |
| public static <T> Iterator<T> filter(Iterator<?> unfiltered, Class<T> type) { |
| return Iterators.filter(unfiltered, type); |
| } |
| |
| /** |
| * Returns a new iterator filtering any null references. |
| * |
| * @param unfiltered |
| * the unfiltered iterator. May not be <code>null</code>. |
| * @return an unmodifiable iterator containing all elements of the original iterator without any <code>null</code> |
| * references. Never <code>null</code>. |
| */ |
| @Pure |
| public static <T> Iterator<T> filterNull(Iterator<T> unfiltered) { |
| return Iterators.filter(unfiltered, Predicates.notNull()); |
| } |
| |
| /** |
| * Returns an iterator that performs the given {@code transformation} for each element of {@code original} when |
| * requested. The mapping is done lazily. |
| * |
| * The returned iterator'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 iterator. May not be <code>null</code>. |
| * @param transformation |
| * the transformation. May not be <code>null</code>. |
| * @return an iterator that provides the result of the transformation. Never <code>null</code>. |
| */ |
| @Pure |
| public static <T, R> Iterator<R> map(Iterator<T> original, Function1<? super T, ? extends R> transformation) { |
| return Iterators.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(Iterator, Functions.Function1)} and {@link #flatten(Iterator)} is performed. |
| * </p> |
| * <p> |
| * The returned iterable's iterator <i>does not support {@code remove()}</i> in contrast to {@link #map(Iterator, 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> Iterator<R> flatMap(Iterator<T> original, Function1<? super T, ? extends Iterator<R>> transformation) { |
| return flatten(map(original, transformation)); |
| } |
| |
| |
| /** |
| * Combines multiple iterators into a single iterator. The returned iterator traverses the |
| * elements of each iterator in {@code inputs}. The input iterators are not polled until necessary. |
| * |
| * @param inputs |
| * the to be flattened iterators. May not be <code>null</code>. |
| * @return an iterator that provides the concatenated values of the input elements. Never <code>null</code>. |
| * |
| * @since 2.13 |
| */ |
| @Inline(value="$2.$3concat($1)", imported=Iterators.class) |
| public static <T> Iterator<T> flatten(Iterator<? extends Iterator<? extends T>> inputs) { |
| return Iterators.concat(inputs); |
| } |
| |
| /** |
| * Applies {@code procedure} for each element of the given iterator. |
| * |
| * @param iterator |
| * the iterator. May not be <code>null</code>. |
| * @param procedure |
| * the procedure. May not be <code>null</code>. |
| */ |
| public static <T> void forEach(Iterator<T> iterator, Procedure1<? super T> procedure) { |
| if (procedure == null) |
| throw new NullPointerException("procedure"); |
| while(iterator.hasNext()) { |
| procedure.apply(iterator.next()); |
| } |
| } |
| |
| /** |
| * Applies {@code procedure} for each element of the given iterator. |
| * 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 iterator |
| * the iterator. May not be <code>null</code>. |
| * @param procedure |
| * the procedure. May not be <code>null</code>. |
| */ |
| public static <T> void forEach(Iterator<T> iterator, Procedure2<? super T, ? super Integer> procedure) { |
| if (procedure == null) |
| throw new NullPointerException("procedure"); |
| int i = 0; |
| while(iterator.hasNext()) { |
| procedure.apply(iterator.next(), i); |
| if (i != Integer.MAX_VALUE) |
| i++; |
| } |
| } |
| |
| /** |
| * Returns the concatenated string representation of the elements in the given iterator. No delimiter is used. |
| * The given iterator is left exhausted. |
| * |
| * @param iterator |
| * the iterator. May not be <code>null</code>. |
| * @return the string representation of the iterator's elements. Never <code>null</code>. |
| * @see #join(Iterator, CharSequence, org.eclipse.xtext.xbase.lib.Functions.Function1) |
| */ |
| public static String join(Iterator<?> iterator) { |
| return join(iterator, ""); |
| } |
| |
| /** |
| * Returns the concatenated string representation of the elements in the given iterator. 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. The given iterator is left exhausted. |
| * |
| * @param iterator |
| * the iterator. May not be <code>null</code>. |
| * @param separator |
| * the separator. May not be <code>null</code>. |
| * @return the string representation of the iterator's elements. Never <code>null</code>. |
| * @see #join(Iterator, CharSequence, org.eclipse.xtext.xbase.lib.Functions.Function1) |
| */ |
| public static String join(Iterator<?> iterator, CharSequence separator) { |
| return Joiner.on(separator.toString()).useForNull("null").join(toIterable(iterator)); |
| } |
| |
| /** |
| * Returns the concatenated string representation of the elements in the given iterator. 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. The given iterator is left exhausted. |
| * |
| * @param iterator |
| * the iterator. 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 iterator's elements. Never <code>null</code>. |
| */ |
| public static <T> String join(Iterator<T> iterator, CharSequence separator, |
| Functions.Function1<? super T, ? extends CharSequence> function) { |
| if (separator == null) |
| throw new NullPointerException("separator"); |
| if (function == null) |
| throw new NullPointerException("function"); |
| StringBuilder result = new StringBuilder(); |
| while (iterator.hasNext()) { |
| T next = iterator.next(); |
| CharSequence elementToString = function.apply(next); |
| result.append(elementToString); |
| if (iterator.hasNext()) |
| result.append(separator); |
| } |
| return result.toString(); |
| } |
| |
| /** |
| * Returns the concatenated string representation of the elements in the given iterator. 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. The given iterator is left exhausted. |
| * |
| * @param iterator |
| * the iterator. May not be <code>null</code>. |
| * @param before |
| * prepends the resulting string if the iterator 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 iterator 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 iterator's elements. Never <code>null</code>. |
| */ |
| public static <T> String join(Iterator<T> iterator, CharSequence before, CharSequence separator, CharSequence after, |
| Functions.Function1<? super T, ? extends CharSequence> function) { |
| if (function == null) |
| throw new NullPointerException("function"); |
| StringBuilder result = new StringBuilder(); |
| boolean notEmpty = iterator.hasNext(); |
| if (notEmpty && before != null) |
| result.append(before); |
| while (iterator.hasNext()) { |
| T next = iterator.next(); |
| CharSequence elementToString = function.apply(next); |
| result.append(elementToString); |
| if (iterator.hasNext() && separator != null) |
| result.append(separator); |
| } |
| if (notEmpty && after != null) |
| result.append(after); |
| return result.toString(); |
| } |
| |
| /** |
| * Determines whether two iterators contain equal elements in the same order. More specifically, this method returns |
| * {@code true} if {@code iterator} and {@code other} contain the same number of elements and every element of |
| * {@code iterator} is equal to the corresponding element of {@code other}. |
| * |
| * <p>Note that this will advance or even exhaust the given iterators.</p> |
| * |
| * @param iterator |
| * an iterator. May not be <code>null</code>. |
| * @param other |
| * an iterator. May not be <code>null</code>. |
| * @return <code>true</code> if the two iterators contain equal elements in the same order. |
| */ |
| public static boolean elementsEqual(Iterator<?> iterator, Iterator<?> other) { |
| return Iterators.elementsEqual(iterator, other); |
| } |
| |
| /** |
| * Determines whether two iterators contain equal elements in the same order. More specifically, this method returns |
| * {@code true} if {@code iterator} and {@code iterable} contain the same number of elements and every element of |
| * {@code iterator} is equal to the corresponding element of {@code iterable}. |
| * |
| * <p>Note that this will advance or even exhaust the given iterators.</p> |
| * |
| * @param iterator |
| * an iterator. May not be <code>null</code>. |
| * @param iterable |
| * an iterable. May not be <code>null</code>. |
| * @return <code>true</code> if the two iterators contain equal elements in the same order. |
| */ |
| public static boolean elementsEqual(Iterator<?> iterator, Iterable<?> iterable) { |
| return Iterators.elementsEqual(iterator, iterable.iterator()); |
| } |
| |
| /** |
| * Determines if the given iterator is <code>null</code> or contains no elements. |
| * |
| * @param iterator |
| * the to-be-queried iterator. May be <code>null</code>. |
| * @return {@code true} if the iterator is <code>null</code> or contains no elements |
| */ |
| public static boolean isNullOrEmpty(Iterator<?> iterator) { |
| return iterator == null || isEmpty(iterator); |
| } |
| |
| /** |
| * Determines if the given iterator contains no elements. |
| * |
| * @param iterator |
| * the to-be-queried iterator. May not be <code>null</code>. |
| * @return {@code true} if the iterator contains no elements |
| * @see #isNullOrEmpty(Iterator) |
| */ |
| public static boolean isEmpty(Iterator<?> iterator) { |
| return !iterator.hasNext(); |
| } |
| |
| /** |
| * Returns the number of elements in {@code iterator}. |
| * The given iterator is left exhausted. |
| * |
| * @param iterator |
| * the iterator. May not be <code>null</code>. |
| * @return the number of elements in {@code iterator}. |
| */ |
| public static int size(Iterator<?> iterator) { |
| return Iterators.size(iterator); |
| } |
| |
| /** |
| * <p> |
| * Applies the combinator {@code function} to all elements of the iterator in turn. |
| * </p> |
| * <p> |
| * One of the function parameters is an element of the iterator, and the other is the result of previous application |
| * of the function. The seed of the operation is the first element in the iterator. The second value is computed by |
| * applying the function to the seed together with the second element of the iterator. 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 iterator is empty, <code>null</code> is returned. |
| * </p> |
| * <p> |
| * More formally, given an iterator {@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 iterator |
| * the to-be-reduced iterator. 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(Iterator<? extends T> iterator, Function2<? super T, ? super T, ? extends T> function) { |
| if (function == null) |
| throw new NullPointerException("function"); |
| if (iterator.hasNext()) { |
| T result = iterator.next(); |
| while (iterator.hasNext()) { |
| result = function.apply(result, iterator.next()); |
| } |
| return result; |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * <p> |
| * Applies the combinator {@code function} to all elements of the iterator in turn and uses {@code seed} as the |
| * start value. |
| * </p> |
| * <p> |
| * One of the function parameters is an element of the iterator, and the other is the result of previous application |
| * of the function. The seed of the operation is explicitly passed to {@link #fold(Iterator, 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 iterator. This intermediate result together with the second element of the iterator produced the next result |
| * and so on. |
| * </p> |
| * <p> |
| * {@link #fold(Iterator, Object, org.eclipse.xtext.xbase.lib.Functions.Function2) fold} is similar to {@link #reduce(Iterator, 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 iterator is empty, <code>seed</code> is returned. |
| * </p> |
| * <p> |
| * More formally, given an iterator {@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 iterator |
| * the to-be-folded iterator. 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(Iterator<T> iterator, R seed, Function2<? super R, ? super T, ? extends R> function) { |
| R result = seed; |
| while (iterator.hasNext()) { |
| result = function.apply(result, iterator.next()); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns a list that contains all the entries of the given iterator in the same order. |
| * |
| * @param iterator |
| * the iterator. May not be <code>null</code>. |
| * @return a list with the same entries as the given iterator. Never <code>null</code>. |
| */ |
| public static <T> List<T> toList(Iterator<? extends T> iterator) { |
| return Lists.newArrayList(iterator); |
| } |
| |
| /** |
| * Returns a set that contains all the unique entries of the given iterator in the order of their appearance. |
| * The result set is a copy of the iterator with stable order. |
| * |
| * @param iterator |
| * the iterator. May not be <code>null</code>. |
| * @return a set with the unique entries of the given iterator. Never <code>null</code>. |
| */ |
| public static <T> Set<T> toSet(Iterator<? extends T> iterator) { |
| return Sets.newLinkedHashSet(toIterable(iterator)); |
| } |
| |
| /** |
| * 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 iterator 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. |
| * The key iterator is left exhausted. |
| * |
| * @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 iterator to the corresponding result when evaluating the function |
| * {@code computeValues}. |
| */ |
| public static <K, V> Map<K, V> toInvertedMap(Iterator<? extends K> keys, Function1<? super K, V> computeValues) { |
| Map<K, V> result = Maps.newLinkedHashMap(); |
| while(keys.hasNext()) { |
| K k = keys.next(); |
| result.put(k, computeValues.apply(k)); |
| } |
| return result; |
| } |
| |
| /** |
| * 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. The value iterator is left exhausted. |
| * |
| * @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 |
| * iterator to that value |
| */ |
| public static <K, V> Map<K, V> toMap(Iterator<? extends V> values, Function1<? super V, K> computeKeys) { |
| if (computeKeys == null) |
| throw new NullPointerException("computeKeys"); |
| Map<K, V> result = Maps.newLinkedHashMap(); |
| while(values.hasNext()) { |
| V v = values.next(); |
| result.put(computeKeys.apply(v), v); |
| } |
| return result; |
| } |
| |
| /** |
| * 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. The input iterator is left exhausted. |
| * |
| * @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(Iterator<? extends T> inputs, Function1<? super T, K> computeKeys, Function1<? super T, V> computeValues) { |
| if (computeKeys == null) |
| throw new NullPointerException("computeKeys"); |
| if (computeValues == null) |
| throw new NullPointerException("computeValues"); |
| Map<K, V> result = Maps.newLinkedHashMap(); |
| while(inputs.hasNext()) { |
| T t = inputs.next(); |
| result.put(computeKeys.apply(t), computeValues.apply(t)); |
| } |
| return result; |
| } |
| |
| |
| |
| /** |
| * 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 iterator. 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. The value iterator is left exhausted. |
| * |
| * @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 |
| * iterator 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(Iterator<? extends V> values, |
| Function1<? super V, ? extends K> computeKeys) { |
| if (computeKeys == null) |
| throw new NullPointerException("computeKeys"); |
| Map<K, List<V>> result = Maps.newLinkedHashMap(); |
| while(values.hasNext()) { |
| V v = values.next(); |
| K key = computeKeys.apply(v); |
| List<V> grouped = result.get(key); |
| if (grouped == null) { |
| grouped = new ArrayList<V>(); |
| result.put(key, grouped); |
| } |
| grouped.add(v); |
| } |
| return result; |
| } |
| |
| /** |
| * Returns an Iterator containing all elements starting from the head of the source up to and excluding the first |
| * element that violates the predicate. The resulting Iterator is a lazily computed view, so any modifications to the |
| * underlying Iterators will be reflected on iteration. The result does not support {@link Iterator#remove()} |
| * |
| * @param iterator |
| * 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> Iterator<T> takeWhile(final Iterator<? extends T> iterator, final Function1<? super T, Boolean> predicate) { |
| if (iterator == null) |
| throw new NullPointerException("iterator"); |
| if (predicate == null) |
| throw new NullPointerException("predicate"); |
| return new AbstractIterator<T>() { |
| @Override |
| protected T computeNext() { |
| if (!iterator.hasNext()) |
| return endOfData(); |
| T next = iterator.next(); |
| if (predicate.apply(next)) { |
| return next; |
| } else { |
| return endOfData(); |
| } |
| } |
| }; |
| } |
| |
| /** |
| * Returns an Iterator containing all elements starting from the first element for which the drop-predicate returned |
| * false. The resulting Iterator is a lazily computed view, so any modifications to the |
| * underlying Iterators will be reflected on iteration. The result does not support {@link Iterator#remove()} |
| * |
| * @param iterator |
| * 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> Iterator<T> dropWhile(final Iterator<? extends T> iterator, final Function1<? super T, Boolean> predicate) { |
| if (iterator == null) |
| throw new NullPointerException("iterator"); |
| if (predicate == null) |
| throw new NullPointerException("predicate"); |
| return new AbstractIterator<T>() { |
| private boolean headFound = false; |
| |
| @Override |
| protected T computeNext() { |
| while (!headFound) { |
| if (!iterator.hasNext()) |
| return endOfData(); |
| T next = iterator.next(); |
| if (!predicate.apply(next)) { |
| headFound = true; |
| return next; |
| } |
| } |
| if (iterator.hasNext()) { |
| return iterator.next(); |
| } else { |
| return endOfData(); |
| } |
| } |
| }; |
| } |
| |
| /** |
| * Returns an Iterator of Pairs where the nth pair is created by taking the nth element of the source as the value |
| * and 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 Iterator is a lazily computed view, so any modifications to the underlying Iterator will be |
| * reflected on iteration. The result does not support {@link Iterator#remove()} |
| * |
| * @param iterator |
| * the elements. May not be <code>null</code>. |
| * @return the zipped result |
| * @since 2.7 |
| */ |
| public static <A> Iterator<Pair<Integer, A>> indexed(final Iterator<? extends A> iterator) { |
| if (iterator == null) |
| throw new NullPointerException("iterator"); |
| return new AbstractIterator<Pair<Integer, A>>() { |
| int i = 0; |
| @Override |
| protected Pair<Integer, A> computeNext() { |
| if (iterator.hasNext()) { |
| Pair<Integer, A> next = new Pair<Integer, A>(i, iterator.next()); |
| if (i != Integer.MAX_VALUE) |
| i++; |
| return next; |
| } else { |
| return endOfData(); |
| } |
| } |
| }; |
| } |
| |
| /** |
| * Finds the minimum of the given elements according to their natural ordering. If there are several mimina, the |
| * first one will be returned. |
| * |
| * <p>Note that this will advance or even exhaust the given iterator.</p> |
| * |
| * @param iterator |
| * the mutually comparable elements. May not be <code>null</code>. |
| * @return the minimum |
| * @throws NoSuchElementException |
| * if the iterator is empty |
| * @since 2.7 |
| */ |
| public static <T extends Comparable<? super T>> T min(final Iterator<T> iterator) { |
| return min(iterator, Ordering.natural()); |
| } |
| |
| /** |
| * Finds the element that yields the minimum value when passed to <code>compareBy</code>. If there are several |
| * maxima, the first one will be returned. |
| * |
| * <p>Note that this will advance or even exhaust the given iterator.</p> |
| * |
| * @param iterator |
| * 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 iterator is empty |
| * @since 2.7 |
| */ |
| public static <T, C extends Comparable<? super C>> T minBy(final Iterator<T> iterator, final Function1<? super T, C> compareBy) { |
| if (compareBy == null) |
| throw new NullPointerException("compareBy"); |
| return min(iterator, new KeyComparator<T, C>(compareBy)); |
| } |
| |
| /** |
| * Finds the mininmum element according to <code>comparator</code>. If there are several minima, the first one will |
| * be returned. |
| * |
| * <p>Note that this will advance or even exhaust the given iterator.</p> |
| * |
| * @param iterator |
| * 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 iterator is empty |
| * @since 2.7 |
| */ |
| public static <T> T min(final Iterator<T> iterator, Comparator<? super T> comparator) { |
| if (comparator == null) |
| throw new NullPointerException("comparator"); |
| T min = iterator.next(); |
| while (iterator.hasNext()) { |
| T element = iterator.next(); |
| min = comparator.compare(min, element) <= 0 ? min : element; |
| } |
| return min; |
| } |
| |
| /** |
| * Finds the maximum of the elements according to their natural ordering. If there are several maxima, the first one |
| * will be returned. |
| * |
| * <p>Note that this will advance or even exhaust the given iterator.</p> |
| * |
| * @param iterator |
| * the mutually comparable elements. May not be <code>null</code>. |
| * @return the maximum |
| * @throws NoSuchElementException |
| * if the iterator is empty |
| * @since 2.7 |
| */ |
| public static <T extends Comparable<? super T>> T max(final Iterator<T> iterator) { |
| return max(iterator, Ordering.natural()); |
| } |
| |
| /** |
| * 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. |
| * |
| * <p>Note that this will advance or even exhaust the given iterator.</p> |
| * |
| * @param iterator |
| * 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 iterator is empty |
| * @since 2.7 |
| */ |
| public static <T, C extends Comparable<? super C>> T maxBy(final Iterator<T> iterator, final Function1<? super T, C> compareBy) { |
| if (compareBy == null) |
| throw new NullPointerException("compareBy"); |
| return max(iterator, new KeyComparator<T, C>(compareBy)); |
| } |
| |
| /** |
| * Finds the maximum element according to <code>comparator</code>. If there are several maxima, the first one will |
| * be returned. |
| * |
| * <p>Note that this will advance or even exhaust the given iterator.</p> |
| * |
| * @param iterator |
| * 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 iterator is empty |
| * @since 2.7 |
| */ |
| public static <T> T max(final Iterator<T> iterator, Comparator<? super T> comparator) { |
| if (comparator == null) |
| throw new NullPointerException("comparator"); |
| T max = iterator.next(); |
| while (iterator.hasNext()) { |
| T element = iterator.next(); |
| max = comparator.compare(max, element) >= 0 ? max : element; |
| } |
| return max; |
| } |
| |
| /** |
| * Returns <tt>true</tt> if this Iterator contains the specified element. |
| * More formally, returns <tt>true</tt> if and only if this Iterator |
| * contains at least one element <tt>e</tt> such that |
| * <tt>(o==null ? e==null : o.equals(e))</tt>. |
| * |
| * <p> |
| * Note that this will advance or even exhaust the given iterator. |
| * </p> |
| * |
| * @param iterator |
| * the elements to test |
| * @param o |
| * element whose presence in this Iterator is to be tested |
| * @return <tt>true</tt> if this Iterator contains the specified element |
| */ |
| public static boolean contains(Iterator<?> iterator, Object o) { |
| while (iterator.hasNext()) { |
| if (Objects.equals(o, iterator.next())) { |
| return true; |
| } |
| } |
| return false; |
| } |
| } |