Java tutorial
/******************************************************************************* * 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.ArrayList; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; 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}. * @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. * * @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 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)); } /** * 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}. * * @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}. * * @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} 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. * * @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. * * @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. * * @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. * * @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. * * @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. * * @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; } }