All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.common.collect.Iterables Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 34.0.0.Final
Show newest version
/*
 * Copyright (C) 2007 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.collect;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.CollectPreconditions.checkRemove;

import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.RandomAccess;
import java.util.Set;
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.stream.Stream;
import javax.annotation.CheckForNull;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * An assortment of mainly legacy static utility methods that operate on or return objects of type
 * {@code Iterable}. Except as noted, each method has a corresponding {@link Iterator}-based method
 * in the {@link Iterators} class.
 *
 * 

Java 8 users: several common uses for this class are now more comprehensively addressed * by the new {@link java.util.stream.Stream} library. Read the method documentation below for * comparisons. This class is not being deprecated, but we gently encourage you to migrate to * streams. * *

Performance notes: Unless otherwise noted, all of the iterables produced in this class * are lazy, which means that their iterators only advance the backing iteration when * absolutely necessary. * *

See the Guava User Guide article on {@code * Iterables}. * * @author Kevin Bourrillion * @author Jared Levy * @since 2.0 */ @GwtCompatible(emulated = true) @ElementTypesAreNonnullByDefault public final class Iterables { private Iterables() {} /** Returns an unmodifiable view of {@code iterable}. */ public static Iterable unmodifiableIterable( final Iterable iterable) { checkNotNull(iterable); if (iterable instanceof UnmodifiableIterable || iterable instanceof ImmutableCollection) { @SuppressWarnings("unchecked") // Since it's unmodifiable, the covariant cast is safe Iterable result = (Iterable) iterable; return result; } return new UnmodifiableIterable<>(iterable); } /** * Simply returns its argument. * * @deprecated no need to use this * @since 10.0 */ @Deprecated public static Iterable unmodifiableIterable(ImmutableCollection iterable) { return checkNotNull(iterable); } private static final class UnmodifiableIterable extends FluentIterable { private final Iterable iterable; private UnmodifiableIterable(Iterable iterable) { this.iterable = iterable; } @Override public Iterator iterator() { return Iterators.unmodifiableIterator(iterable.iterator()); } @Override public void forEach(Consumer action) { iterable.forEach(action); } @SuppressWarnings("unchecked") // safe upcast, assuming no one has a crazy Spliterator subclass @Override public Spliterator spliterator() { return (Spliterator) iterable.spliterator(); } @Override public String toString() { return iterable.toString(); } // no equals and hashCode; it would break the contract! } /** Returns the number of elements in {@code iterable}. */ public static int size(Iterable iterable) { return (iterable instanceof Collection) ? ((Collection) iterable).size() : Iterators.size(iterable.iterator()); } /** * Returns {@code true} if {@code iterable} contains any element {@code o} for which {@code * Objects.equals(o, element)} would return {@code true}. Otherwise returns {@code false}, even in * cases where {@link Collection#contains} might throw {@link NullPointerException} or {@link * ClassCastException}. */ // instead of because of Kotlin b/189937072, discussed in Joiner. public static boolean contains( Iterable iterable, @CheckForNull Object element) { if (iterable instanceof Collection) { Collection collection = (Collection) iterable; return Collections2.safeContains(collection, element); } return Iterators.contains(iterable.iterator(), element); } /** * Removes, from an iterable, every element that belongs to the provided collection. * *

This method calls {@link Collection#removeAll} if {@code iterable} is a collection, and * {@link Iterators#removeAll} otherwise. * * @param removeFrom the iterable to (potentially) remove elements from * @param elementsToRemove the elements to remove * @return {@code true} if any element was removed from {@code iterable} */ @CanIgnoreReturnValue public static boolean removeAll(Iterable removeFrom, Collection elementsToRemove) { return (removeFrom instanceof Collection) ? ((Collection) removeFrom).removeAll(checkNotNull(elementsToRemove)) : Iterators.removeAll(removeFrom.iterator(), elementsToRemove); } /** * Removes, from an iterable, every element that does not belong to the provided collection. * *

This method calls {@link Collection#retainAll} if {@code iterable} is a collection, and * {@link Iterators#retainAll} otherwise. * * @param removeFrom the iterable to (potentially) remove elements from * @param elementsToRetain the elements to retain * @return {@code true} if any element was removed from {@code iterable} */ @CanIgnoreReturnValue public static boolean retainAll(Iterable removeFrom, Collection elementsToRetain) { return (removeFrom instanceof Collection) ? ((Collection) removeFrom).retainAll(checkNotNull(elementsToRetain)) : Iterators.retainAll(removeFrom.iterator(), elementsToRetain); } /** * Removes, from an iterable, every element that satisfies the provided predicate. * *

Removals may or may not happen immediately as each element is tested against the predicate. * The behavior of this method is not specified if {@code predicate} is dependent on {@code * removeFrom}. * *

Java 8 users: if {@code removeFrom} is a {@link Collection}, use {@code * removeFrom.removeIf(predicate)} instead. * * @param removeFrom the iterable to (potentially) remove elements from * @param predicate a predicate that determines whether an element should be removed * @return {@code true} if any elements were removed from the iterable * @throws UnsupportedOperationException if the iterable does not support {@code remove()}. * @since 2.0 */ @CanIgnoreReturnValue public static boolean removeIf( Iterable removeFrom, Predicate predicate) { if (removeFrom instanceof Collection) { return ((Collection) removeFrom).removeIf(predicate); } return Iterators.removeIf(removeFrom.iterator(), predicate); } /** Removes and returns the first matching element, or returns {@code null} if there is none. */ @CheckForNull static T removeFirstMatching( Iterable removeFrom, Predicate predicate) { checkNotNull(predicate); Iterator iterator = removeFrom.iterator(); while (iterator.hasNext()) { T next = iterator.next(); if (predicate.apply(next)) { iterator.remove(); return next; } } return null; } /** * Determines whether two iterables contain equal elements in the same order. More specifically, * this method returns {@code true} if {@code iterable1} and {@code iterable2} contain the same * number of elements and every element of {@code iterable1} is equal to the corresponding element * of {@code iterable2}. */ public static boolean elementsEqual(Iterable iterable1, Iterable iterable2) { if (iterable1 instanceof Collection && iterable2 instanceof Collection) { Collection collection1 = (Collection) iterable1; Collection collection2 = (Collection) iterable2; if (collection1.size() != collection2.size()) { return false; } } return Iterators.elementsEqual(iterable1.iterator(), iterable2.iterator()); } /** * Returns a string representation of {@code iterable}, with the format {@code [e1, e2, ..., en]} * (that is, identical to {@link java.util.Arrays Arrays}{@code * .toString(Iterables.toArray(iterable))}). Note that for most implementations of {@link * Collection}, {@code collection.toString()} also gives the same result, but that behavior is not * generally guaranteed. */ public static String toString(Iterable iterable) { return Iterators.toString(iterable.iterator()); } /** * Returns the single element contained in {@code iterable}. * *

Java 8 users: the {@code Stream} equivalent to this method is {@code * stream.collect(MoreCollectors.onlyElement())}. * * @throws NoSuchElementException if the iterable is empty * @throws IllegalArgumentException if the iterable contains multiple elements */ @ParametricNullness public static T getOnlyElement(Iterable iterable) { return Iterators.getOnlyElement(iterable.iterator()); } /** * Returns the single element contained in {@code iterable}, or {@code defaultValue} if the * iterable is empty. * *

Java 8 users: the {@code Stream} equivalent to this method is {@code * stream.collect(MoreCollectors.toOptional()).orElse(defaultValue)}. * * @throws IllegalArgumentException if the iterator contains multiple elements */ @ParametricNullness public static T getOnlyElement( Iterable iterable, @ParametricNullness T defaultValue) { return Iterators.getOnlyElement(iterable.iterator(), defaultValue); } /** * Copies an iterable's elements into an array. * * @param iterable the iterable to copy * @param type the type of the elements * @return a newly-allocated array into which all the elements of the iterable have been copied */ @GwtIncompatible // Array.newInstance(Class, int) public static T[] toArray( Iterable iterable, Class<@NonNull T> type) { return toArray(iterable, ObjectArrays.newArray(type, 0)); } static T[] toArray(Iterable iterable, T[] array) { Collection collection = castOrCopyToCollection(iterable); return collection.toArray(array); } /** * Copies an iterable's elements into an array. * * @param iterable the iterable to copy * @return a newly-allocated array into which all the elements of the iterable have been copied */ static @Nullable Object[] toArray(Iterable iterable) { return castOrCopyToCollection(iterable).toArray(); } /** * Converts an iterable into a collection. If the iterable is already a collection, it is * returned. Otherwise, an {@link java.util.ArrayList} is created with the contents of the * iterable in the same iteration order. */ private static Collection castOrCopyToCollection( Iterable iterable) { return (iterable instanceof Collection) ? (Collection) iterable : Lists.newArrayList(iterable.iterator()); } /** * Adds all elements in {@code iterable} to {@code collection}. * * @return {@code true} if {@code collection} was modified as a result of this operation. */ @CanIgnoreReturnValue public static boolean addAll( Collection addTo, Iterable elementsToAdd) { if (elementsToAdd instanceof Collection) { Collection c = (Collection) elementsToAdd; return addTo.addAll(c); } return Iterators.addAll(addTo, checkNotNull(elementsToAdd).iterator()); } /** * Returns the number of elements in the specified iterable that equal the specified object. This * implementation avoids a full iteration when the iterable is a {@link Multiset} or {@link Set}. * *

Java 8 users: In most cases, the {@code Stream} equivalent of this method is {@code * stream.filter(element::equals).count()}. If {@code element} might be null, use {@code * stream.filter(Predicate.isEqual(element)).count()} instead. * * @see java.util.Collections#frequency(Collection, Object) Collections.frequency(Collection, * Object) */ public static int frequency(Iterable iterable, @CheckForNull Object element) { if ((iterable instanceof Multiset)) { return ((Multiset) iterable).count(element); } else if ((iterable instanceof Set)) { return ((Set) iterable).contains(element) ? 1 : 0; } return Iterators.frequency(iterable.iterator(), element); } /** * Returns an iterable whose iterators cycle indefinitely over the elements of {@code iterable}. * *

That iterator supports {@code remove()} if {@code iterable.iterator()} does. After {@code * remove()} is called, subsequent cycles omit the removed element, which is no longer in {@code * iterable}. The iterator's {@code hasNext()} method returns {@code true} until {@code iterable} * is empty. * *

Warning: Typical uses of the resulting iterator may produce an infinite loop. You * should use an explicit {@code break} or be certain that you will eventually remove all the * elements. * *

To cycle over the iterable {@code n} times, use the following: {@code * Iterables.concat(Collections.nCopies(n, iterable))} * *

Java 8 users: The {@code Stream} equivalent of this method is {@code * Stream.generate(() -> iterable).flatMap(Streams::stream)}. */ public static Iterable cycle(final Iterable iterable) { checkNotNull(iterable); return new FluentIterable() { @Override public Iterator iterator() { return Iterators.cycle(iterable); } @Override public Spliterator spliterator() { return Stream.generate(() -> iterable).flatMap(Streams::stream).spliterator(); } @Override public String toString() { return iterable.toString() + " (cycled)"; } }; } /** * Returns an iterable whose iterators cycle indefinitely over the provided elements. * *

After {@code remove} is invoked on a generated iterator, the removed element will no longer * appear in either that iterator or any other iterator created from the same source iterable. * That is, this method behaves exactly as {@code Iterables.cycle(Lists.newArrayList(elements))}. * The iterator's {@code hasNext} method returns {@code true} until all of the original elements * have been removed. * *

Warning: Typical uses of the resulting iterator may produce an infinite loop. You * should use an explicit {@code break} or be certain that you will eventually remove all the * elements. * *

To cycle over the elements {@code n} times, use the following: {@code * Iterables.concat(Collections.nCopies(n, Arrays.asList(elements)))} * *

Java 8 users: If passing a single element {@code e}, the {@code Stream} equivalent of * this method is {@code Stream.generate(() -> e)}. Otherwise, put the elements in a collection * and use {@code Stream.generate(() -> collection).flatMap(Collection::stream)}. */ @SafeVarargs public static Iterable cycle(T... elements) { return cycle(Lists.newArrayList(elements)); } /** * Combines 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 source * iterators are not polled until necessary. * *

The returned iterable's iterator supports {@code remove()} when the corresponding input * iterator supports it. * *

Java 8 users: The {@code Stream} equivalent of this method is {@code Stream.concat(a, * b)}. */ public static Iterable concat( Iterable a, Iterable b) { return FluentIterable.concat(a, b); } /** * Combines three 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}, followed by the * elements in {@code c}. The source iterators are not polled until necessary. * *

The returned iterable's iterator supports {@code remove()} when the corresponding input * iterator supports it. * *

Java 8 users: The {@code Stream} equivalent of this method is {@code * Streams.concat(a, b, c)}. */ public static Iterable concat( Iterable a, Iterable b, Iterable c) { return FluentIterable.concat(a, b, c); } /** * Combines four 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}, followed by the * elements in {@code c}, followed by the elements in {@code d}. The source iterators are not * polled until necessary. * *

The returned iterable's iterator supports {@code remove()} when the corresponding input * iterator supports it. * *

Java 8 users: The {@code Stream} equivalent of this method is {@code * Streams.concat(a, b, c, d)}. */ public static Iterable concat( Iterable a, Iterable b, Iterable c, Iterable d) { return FluentIterable.concat(a, b, c, d); } /** * 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. * *

The returned iterable's iterator supports {@code remove()} when the corresponding input * iterator supports it. * *

Java 8 users: The {@code Stream} equivalent of this method is {@code * Streams.concat(...)}. * * @throws NullPointerException if any of the provided iterables is null */ @SafeVarargs public static Iterable concat(Iterable... inputs) { return FluentIterable.concat(inputs); } /** * 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. * *

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 is null. * *

Java 8 users: The {@code Stream} equivalent of this method is {@code * streamOfStreams.flatMap(s -> s)}. */ public static Iterable concat( Iterable> inputs) { return FluentIterable.concat(inputs); } /** * Divides an iterable into unmodifiable sublists of the given size (the final iterable may be * smaller). For example, partitioning an iterable containing {@code [a, b, c, d, e]} with a * partition size of 3 yields {@code [[a, b, c], [d, e]]} -- an outer iterable containing two * inner lists of three and two elements, all in the original order. * *

Iterators returned by the returned iterable do not support the {@link Iterator#remove()} * method. The returned lists implement {@link RandomAccess}, whether or not the input list does. * *

Note: The current implementation eagerly allocates storage for {@code size} elements. * As a consequence, passing values like {@code Integer.MAX_VALUE} can lead to {@link * OutOfMemoryError}. * *

Note: if {@code iterable} is a {@link List}, use {@link Lists#partition(List, int)} * instead. * * @param iterable the iterable to return a partitioned view of * @param size the desired size of each partition (the last may be smaller) * @return an iterable of unmodifiable lists containing the elements of {@code iterable} divided * into partitions * @throws IllegalArgumentException if {@code size} is nonpositive */ public static Iterable> partition( final Iterable iterable, final int size) { checkNotNull(iterable); checkArgument(size > 0); return new FluentIterable>() { @Override public Iterator> iterator() { return Iterators.partition(iterable.iterator(), size); } }; } /** * Divides an iterable into unmodifiable sublists of the given size, padding the final iterable * with null values if necessary. For example, partitioning an iterable containing {@code [a, b, * c, d, e]} with a partition size of 3 yields {@code [[a, b, c], [d, e, null]]} -- an outer * iterable containing two inner lists of three elements each, all in the original order. * *

Iterators returned by the returned iterable do not support the {@link Iterator#remove()} * method. * * @param iterable the iterable to return a partitioned view of * @param size the desired size of each partition * @return an iterable of unmodifiable lists containing the elements of {@code iterable} divided * into partitions (the final iterable may have trailing null elements) * @throws IllegalArgumentException if {@code size} is nonpositive */ public static Iterable> paddedPartition( final Iterable iterable, final int size) { checkNotNull(iterable); checkArgument(size > 0); return new FluentIterable>() { @Override public Iterator> iterator() { return Iterators.paddedPartition(iterable.iterator(), size); } }; } /** * Returns a view of {@code unfiltered} containing all elements that satisfy the input predicate * {@code retainIfTrue}. The returned iterable's iterator does not support {@code remove()}. * *

{@code Stream} equivalent: {@link Stream#filter}. */ public static Iterable filter( final Iterable unfiltered, final Predicate retainIfTrue) { checkNotNull(unfiltered); checkNotNull(retainIfTrue); return new FluentIterable() { @Override public Iterator iterator() { return Iterators.filter(unfiltered.iterator(), retainIfTrue); } @Override public void forEach(Consumer action) { checkNotNull(action); unfiltered.forEach( (@ParametricNullness T a) -> { if (retainIfTrue.test(a)) { action.accept(a); } }); } @Override public Spliterator spliterator() { return CollectSpliterators.filter(unfiltered.spliterator(), retainIfTrue); } }; } /** * Returns a view of {@code unfiltered} containing all elements that are of the type {@code * desiredType}. The returned iterable's iterator does not support {@code remove()}. * *

{@code Stream} equivalent: {@code stream.filter(type::isInstance).map(type::cast)}. * This does perform a little more work than necessary, so another option is to insert an * unchecked cast at some later point: * *

   * {@code @SuppressWarnings("unchecked") // safe because of ::isInstance check
   * ImmutableList result =
   *     (ImmutableList) stream.filter(NewType.class::isInstance).collect(toImmutableList());}
   * 
*/ @SuppressWarnings("unchecked") @GwtIncompatible // Class.isInstance public static Iterable filter(final Iterable unfiltered, final Class desiredType) { checkNotNull(unfiltered); checkNotNull(desiredType); return (Iterable) filter(unfiltered, Predicates.instanceOf(desiredType)); } /** * Returns {@code true} if any element in {@code iterable} satisfies the predicate. * *

{@code Stream} equivalent: {@link Stream#anyMatch}. */ public static boolean any( Iterable iterable, Predicate predicate) { return Iterators.any(iterable.iterator(), predicate); } /** * Returns {@code true} if every element in {@code iterable} satisfies the predicate. If {@code * iterable} is empty, {@code true} is returned. * *

{@code Stream} equivalent: {@link Stream#allMatch}. */ public static boolean all( Iterable iterable, Predicate predicate) { return Iterators.all(iterable.iterator(), predicate); } /** * Returns the first element in {@code iterable} that satisfies the given predicate; use this * method only when such an element is known to exist. If it is possible that no element * will match, use {@link #tryFind} or {@link #find(Iterable, Predicate, Object)} instead. * *

{@code Stream} equivalent: {@code stream.filter(predicate).findFirst().get()} * * @throws NoSuchElementException if no element in {@code iterable} matches the given predicate */ @ParametricNullness public static T find( Iterable iterable, Predicate predicate) { return Iterators.find(iterable.iterator(), predicate); } /** * Returns the first element in {@code iterable} that satisfies the given predicate, or {@code * defaultValue} if none found. Note that this can usually be handled more naturally using {@code * tryFind(iterable, predicate).or(defaultValue)}. * *

{@code Stream} equivalent: {@code * stream.filter(predicate).findFirst().orElse(defaultValue)} * * @since 7.0 */ // The signature we really want here is... // // @JointlyNullable T find( // Iterable iterable, // Predicate predicate, // @JointlyNullable T defaultValue); // // ...where "@JointlyNullable" is similar to @PolyNull but slightly different: // // - @PolyNull means "@Nullable or @Nonnull" // (That would be unsound for an input Iterable<@Nullable Foo>. So, if we wanted to use // @PolyNull, we would have to restrict this method to non-null . But it has users who pass // iterables with null elements.) // // - @JointlyNullable means "@Nullable or no annotation" @CheckForNull public static T find( Iterable iterable, Predicate predicate, @CheckForNull T defaultValue) { return Iterators.find(iterable.iterator(), predicate, defaultValue); } /** * Returns an {@link Optional} containing the first element in {@code iterable} that satisfies the * given predicate, if such an element exists. * *

Warning: avoid using a {@code predicate} that matches {@code null}. If {@code null} * is matched in {@code iterable}, a NullPointerException will be thrown. * *

{@code Stream} equivalent: {@code stream.filter(predicate).findFirst()} * * @since 11.0 */ public static Optional tryFind(Iterable iterable, Predicate predicate) { return Iterators.tryFind(iterable.iterator(), predicate); } /** * Returns the index in {@code iterable} of the first element that satisfies the provided {@code * predicate}, or {@code -1} if the Iterable has no such elements. * *

More formally, returns the lowest index {@code i} such that {@code * predicate.apply(Iterables.get(iterable, i))} returns {@code true}, or {@code -1} if there is no * such index. * * @since 2.0 */ public static int indexOf( Iterable iterable, Predicate predicate) { return Iterators.indexOf(iterable.iterator(), predicate); } /** * Returns a view containing the result of applying {@code function} to each element of {@code * fromIterable}. * *

The returned iterable's iterator supports {@code remove()} if {@code fromIterable}'s * iterator does. After a successful {@code remove()} call, {@code fromIterable} no longer * contains the corresponding element. * *

If the input {@code Iterable} is known to be a {@code List} or other {@code Collection}, * consider {@link Lists#transform} and {@link Collections2#transform}. * *

{@code Stream} equivalent: {@link Stream#map} */ public static Iterable transform( final Iterable fromIterable, final Function function) { checkNotNull(fromIterable); checkNotNull(function); return new FluentIterable() { @Override public Iterator iterator() { return Iterators.transform(fromIterable.iterator(), function); } @Override public void forEach(Consumer action) { checkNotNull(action); fromIterable.forEach((F f) -> action.accept(function.apply(f))); } @Override public Spliterator spliterator() { return CollectSpliterators.map(fromIterable.spliterator(), function); } }; } /** * Returns the element at the specified position in an iterable. * *

{@code Stream} equivalent: {@code stream.skip(position).findFirst().get()} (throws * {@code NoSuchElementException} if out of bounds) * * @param position position of the element to return * @return the element at the specified position in {@code iterable} * @throws IndexOutOfBoundsException if {@code position} is negative or greater than or equal to * the size of {@code iterable} */ @ParametricNullness public static T get(Iterable iterable, int position) { checkNotNull(iterable); return (iterable instanceof List) ? ((List) iterable).get(position) : Iterators.get(iterable.iterator(), position); } /** * Returns the element at the specified position in an iterable or a default value otherwise. * *

{@code Stream} equivalent: {@code * stream.skip(position).findFirst().orElse(defaultValue)} (returns the default value if the index * is out of bounds) * * @param position position of the element to return * @param defaultValue the default value to return if {@code position} is greater than or equal to * the size of the iterable * @return the element at the specified position in {@code iterable} or {@code defaultValue} if * {@code iterable} contains fewer than {@code position + 1} elements. * @throws IndexOutOfBoundsException if {@code position} is negative * @since 4.0 */ @ParametricNullness public static T get( Iterable iterable, int position, @ParametricNullness T defaultValue) { checkNotNull(iterable); Iterators.checkNonnegative(position); if (iterable instanceof List) { List list = Lists.cast(iterable); return (position < list.size()) ? list.get(position) : defaultValue; } else { Iterator iterator = iterable.iterator(); Iterators.advance(iterator, position); return Iterators.getNext(iterator, defaultValue); } } /** * Returns the first element in {@code iterable} or {@code defaultValue} if the iterable is empty. * The {@link Iterators} analog to this method is {@link Iterators#getNext}. * *

If no default value is desired (and the caller instead wants a {@link * NoSuchElementException} to be thrown), it is recommended that {@code * iterable.iterator().next()} is used instead. * *

To get the only element in a single-element {@code Iterable}, consider using {@link * #getOnlyElement(Iterable)} or {@link #getOnlyElement(Iterable, Object)} instead. * *

{@code Stream} equivalent: {@code stream.findFirst().orElse(defaultValue)} * * @param defaultValue the default value to return if the iterable is empty * @return the first element of {@code iterable} or the default value * @since 7.0 */ @ParametricNullness public static T getFirst( Iterable iterable, @ParametricNullness T defaultValue) { return Iterators.getNext(iterable.iterator(), defaultValue); } /** * Returns the last element of {@code iterable}. If {@code iterable} is a {@link List} with {@link * RandomAccess} support, then this operation is guaranteed to be {@code O(1)}. * *

{@code Stream} equivalent: {@link Streams#findLast Streams.findLast(stream).get()} * * @return the last element of {@code iterable} * @throws NoSuchElementException if the iterable is empty */ @ParametricNullness public static T getLast(Iterable iterable) { // TODO(kevinb): Support a concurrently modified collection? if (iterable instanceof List) { List list = (List) iterable; if (list.isEmpty()) { throw new NoSuchElementException(); } return getLastInNonemptyList(list); } return Iterators.getLast(iterable.iterator()); } /** * Returns the last element of {@code iterable} or {@code defaultValue} if the iterable is empty. * If {@code iterable} is a {@link List} with {@link RandomAccess} support, then this operation is * guaranteed to be {@code O(1)}. * *

{@code Stream} equivalent: {@code Streams.findLast(stream).orElse(defaultValue)} * * @param defaultValue the value to return if {@code iterable} is empty * @return the last element of {@code iterable} or the default value * @since 3.0 */ @ParametricNullness public static T getLast( Iterable iterable, @ParametricNullness T defaultValue) { if (iterable instanceof Collection) { Collection c = (Collection) iterable; if (c.isEmpty()) { return defaultValue; } else if (iterable instanceof List) { return getLastInNonemptyList(Lists.cast(iterable)); } } return Iterators.getLast(iterable.iterator(), defaultValue); } @ParametricNullness private static T getLastInNonemptyList(List list) { return list.get(list.size() - 1); } /** * Returns a view of {@code iterable} that skips its first {@code numberToSkip} elements. If * {@code iterable} contains fewer than {@code numberToSkip} elements, the returned iterable skips * all of its elements. * *

Modifications to the underlying {@link Iterable} before a call to {@code iterator()} are * reflected in the returned iterator. That is, the iterator skips the first {@code numberToSkip} * elements that exist when the {@code Iterator} is created, not when {@code skip()} is called. * *

The returned iterable's iterator supports {@code remove()} if the iterator of the underlying * iterable supports it. Note that it is not possible to delete the last skipped element by * immediately calling {@code remove()} on that iterator, as the {@code Iterator} contract states * that a call to {@code remove()} before a call to {@code next()} will throw an {@link * IllegalStateException}. * *

{@code Stream} equivalent: {@link Stream#skip} * * @since 3.0 */ public static Iterable skip( final Iterable iterable, final int numberToSkip) { checkNotNull(iterable); checkArgument(numberToSkip >= 0, "number to skip cannot be negative"); return new FluentIterable() { @Override public Iterator iterator() { if (iterable instanceof List) { final List list = (List) iterable; int toSkip = Math.min(list.size(), numberToSkip); return list.subList(toSkip, list.size()).iterator(); } final Iterator iterator = iterable.iterator(); Iterators.advance(iterator, numberToSkip); /* * We can't just return the iterator because an immediate call to its * remove() method would remove one of the skipped elements instead of * throwing an IllegalStateException. */ return new Iterator() { boolean atStart = true; @Override public boolean hasNext() { return iterator.hasNext(); } @Override @ParametricNullness public T next() { T result = iterator.next(); atStart = false; // not called if next() fails return result; } @Override public void remove() { checkRemove(!atStart); iterator.remove(); } }; } @Override public Spliterator spliterator() { if (iterable instanceof List) { final List list = (List) iterable; int toSkip = Math.min(list.size(), numberToSkip); return list.subList(toSkip, list.size()).spliterator(); } else { return Streams.stream(iterable).skip(numberToSkip).spliterator(); } } }; } /** * Returns a view of {@code iterable} containing its first {@code limitSize} elements. If {@code * iterable} contains fewer than {@code limitSize} elements, the returned view contains all of its * elements. The returned iterable's iterator supports {@code remove()} if {@code iterable}'s * iterator does. * *

{@code Stream} equivalent: {@link Stream#limit} * * @param iterable the iterable to limit * @param limitSize the maximum number of elements in the returned iterable * @throws IllegalArgumentException if {@code limitSize} is negative * @since 3.0 */ public static Iterable limit( final Iterable iterable, final int limitSize) { checkNotNull(iterable); checkArgument(limitSize >= 0, "limit is negative"); return new FluentIterable() { @Override public Iterator iterator() { return Iterators.limit(iterable.iterator(), limitSize); } @Override public Spliterator spliterator() { return Streams.stream(iterable).limit(limitSize).spliterator(); } }; } /** * Returns a view of the supplied iterable that wraps each generated {@link Iterator} through * {@link Iterators#consumingIterator(Iterator)}. * *

Note: If {@code iterable} is a {@link Queue}, the returned iterable will instead use {@link * Queue#isEmpty} and {@link Queue#remove()}, since {@link Queue}'s iteration order is undefined. * Calling {@link Iterator#hasNext()} on a generated iterator from the returned iterable may cause * an item to be immediately dequeued for return on a subsequent call to {@link Iterator#next()}. * *

Whether the input {@code iterable} is a {@link Queue} or not, the returned {@code Iterable} * is not thread-safe. * * @param iterable the iterable to wrap * @return a view of the supplied iterable that wraps each generated iterator through {@link * Iterators#consumingIterator(Iterator)}; for queues, an iterable that generates iterators * that return and consume the queue's elements in queue order * @see Iterators#consumingIterator(Iterator) * @since 2.0 */ public static Iterable consumingIterable( final Iterable iterable) { checkNotNull(iterable); return new FluentIterable() { @Override public Iterator iterator() { return (iterable instanceof Queue) ? new ConsumingQueueIterator<>((Queue) iterable) : Iterators.consumingIterator(iterable.iterator()); } @Override public String toString() { return "Iterables.consumingIterable(...)"; } }; } // Methods only in Iterables, not in Iterators /** * Determines if the given iterable contains no elements. * *

There is no precise {@link Iterator} equivalent to this method, since one can only ask an * iterator whether it has any elements remaining (which one does using {@link * Iterator#hasNext}). * *

{@code Stream} equivalent: {@code !stream.findAny().isPresent()} * * @return {@code true} if the iterable contains no elements */ public static boolean isEmpty(Iterable iterable) { if (iterable instanceof Collection) { return ((Collection) iterable).isEmpty(); } return !iterable.iterator().hasNext(); } /** * Returns an iterable over the merged contents of all given {@code iterables}. Equivalent entries * will not be de-duplicated. * *

Callers must ensure that the source {@code iterables} are in non-descending order as this * method does not sort its input. * *

For any equivalent elements across all {@code iterables}, it is undefined which element is * returned first. * * @since 11.0 */ public static Iterable mergeSorted( final Iterable> iterables, final Comparator comparator) { checkNotNull(iterables, "iterables"); checkNotNull(comparator, "comparator"); Iterable iterable = new FluentIterable() { @Override public Iterator iterator() { return Iterators.mergeSorted( Iterables.transform(iterables, Iterable::iterator), comparator); } }; return new UnmodifiableIterable<>(iterable); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy