    001    /*
    002     * Copyright (C) 2008 The Guava Authors
    003     *
    004     * Licensed under the Apache License, Version 2.0 (the "License");
    005     * you may not use this file except in compliance with the License.
    006     * You may obtain a copy of the License at
    007     *
    008     * http://www.apache.org/licenses/LICENSE-2.0
    009     *
    010     * Unless required by applicable law or agreed to in writing, software
    011     * distributed under the License is distributed on an "AS IS" BASIS,
    012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    013     * See the License for the specific language governing permissions and
    014     * limitations under the License.
    015     */
    016
    017    package com.google.common.collect;
    018
    019    import static com.google.common.base.Preconditions.checkNotNull;
    020
    021    import com.google.common.annotations.Beta;
    022    import com.google.common.annotations.GwtCompatible;
    023    import com.google.common.annotations.GwtIncompatible;
    024    import com.google.common.base.Function;
    025    import com.google.common.base.Optional;
    026    import com.google.common.base.Predicate;
    027
    028    import java.util.Comparator;
    029    import java.util.Iterator;
    030    import java.util.List;
    031    import java.util.SortedSet;
    032
    033    import javax.annotation.Nullable;
    034
    035    /**
    036     * {@code FluentIterable} provides a rich interface for manipulating {@code Iterable}s in a chained
    037     * fashion. A {@code FluentIterable} can be created from an {@code Iterable}, or from a set of
    038     * elements. The following types of methods are provided on {@code FluentIterable}:
    039     * <ul>
    040     * <li>chained methods which return a new {@code FluentIterable} based in some way on the contents
    041     * of the current one (for example {@link #transform})
    042     * <li>conversion methods which copy the {@code FluentIterable}'s contents into a new collection or
    043     * array (for example {@link #toImmutableList})
    044     * <li>element extraction methods which facilitate the retrieval of certain elements (for example
    045     * {@link #last})
    046     * <li>query methods which answer questions about the {@code FluentIterable}'s contents (for example
    047     * {@link #anyMatch})
    048     * </ul>
    049     *
    050     * <p>Here is an example that merges the lists returned by two separate database calls, transforms
    051     * it by invoking {@code toString()} on each element, and returns the first 10 elements as an
    052     * {@code ImmutableList}: <pre>   {@code
    053     *
    054     *   FluentIterable
    055     *       .from(database.getClientList())
    056     *       .filter(activeInLastMonth())
    057     *       .transform(Functions.toStringFunction())
    058     *       .limit(10)
    059     *       .toImmutableList();}</pre>
    060     *
    061     * Anything which can be done using {@code FluentIterable} could be done in a different fashion
    062     * (often with {@link Iterables}), however the use of {@code FluentIterable} makes many sets of
    063     * operations significantly more concise.
    064     *
    065     * @author Marcin Mikosik
    066     * @since 12.0
    067     */
    068    @Beta
    069    @GwtCompatible(emulated = true)
    070    public abstract class FluentIterable<E> implements Iterable<E> {
    071      // We store 'iterable' and use it instead of 'this' to allow Iterables to perform instanceof
    072      // checks on the _original_ iterable when FluentIterable.from is used.
    073      private final Iterable<E> iterable;
    074
    075      /** Constructor for use by subclasses. */
    076      protected FluentIterable() {
    077        this.iterable = this;
    078      }
    079
    080      FluentIterable(Iterable<E> iterable) {
    081        this.iterable = checkNotNull(iterable);
    082      }
    083
    084      /**
    085       * Returns a fluent iterable that wraps {@code iterable}, or {@code iterable} itself if it
    086       * is already a {@code FluentIterable}.
    087       */
    088      public static <E> FluentIterable<E> from(final Iterable<E> iterable) {
    089        return (iterable instanceof FluentIterable) ? (FluentIterable<E>) iterable
    090            : new FluentIterable<E>(iterable) {
    091              @Override
    092              public Iterator<E> iterator() {
    093                return iterable.iterator();
    094              }
    095            };
    096      }
    097
    098      /**
    099       * Construct a fluent iterable from another fluent iterable. This is obviously never necessary,
    100       * but is intended to help call out cases where one migration from {@code Iterable} to
    101       * {@code FluentIterable} has obviated the need to explicitly convert to a {@code FluentIterable}.
    102       *
    103       * @deprecated instances of {@code FluentIterable} don't need to be converted to
    104       *     {@code FluentIterable}
    105       */
    106      @Deprecated
    107      public static <E> FluentIterable<E> from(FluentIterable<E> iterable) {
    108        return checkNotNull(iterable);
    109      }
    110
    111      /**
    112       * Returns a string representation of this fluent iterable, with the format
    113       * {@code [e1, e2, ..., en]}.
    114       */
    115      @Override
    116      public String toString() {
    117        return Iterables.toString(iterable);
    118      }
    119
    120      /**
    121       * Returns the number of elements in this fluent iterable.
    122       */
    123      public final int size() {
    124        return Iterables.size(iterable);
    125      }
    126
    127      /**
    128       * Returns {@code true} if this fluent iterable contains any object for which
    129       * {@code equals(element)} is true.
    130       */
    131      public final boolean contains(@Nullable Object element) {
    132        return Iterables.contains(iterable, element);
    133      }
    134
    135      /**
    136       * Returns a fluent iterable whose {@code Iterator} cycles indefinitely over the elements of
    137       * this fluent iterable.
    138       *
    139       * <p>That iterator supports {@code remove()} if {@code iterable.iterator()} does. After
    140       * {@code remove()} is called, subsequent cycles omit the removed element, which is no longer in
    141       * this fluent iterable. The iterator's {@code hasNext()} method returns {@code true} until
    142       * this fluent iterable is empty.
    143       *
    144       * <p><b>Warning:</b> Typical uses of the resulting iterator may produce an infinite loop. You
    145       * should use an explicit {@code break} or be certain that you will eventually remove all the
    146       * elements.
    147       */
    148      public final FluentIterable<E> cycle() {
    149        return from(Iterables.cycle(iterable));
    150      }
    151
    152      /**
    153       * Returns the elements from this fluent iterable that satisfy a predicate. The
    154       * resulting fluent iterable's iterator does not support {@code remove()}.
    155       */
    156      public final FluentIterable<E> filter(Predicate<? super E> predicate) {
    157        return from(Iterables.filter(iterable, predicate));
    158      }
    159
    160      /**
    161       * Returns the elements from this fluent iterable that are instances of class {@code type}.
    162       *
    163       * @param type the type of elements desired
    164       */
    165      @GwtIncompatible("Class.isInstance")
    166      public final <T> FluentIterable<T> filter(Class<T> type) {
    167        return from(Iterables.filter(iterable, type));
    168      }
    169
    170      /**
    171       * Returns {@code true} if any element in this fluent iterable satisfies the predicate.
    172       */
    173      public final boolean anyMatch(Predicate<? super E> predicate) {
    174        return Iterables.any(iterable, predicate);
    175      }
    176
    177      /**
    178       * Returns {@code true} if every element in this fluent iterable satisfies the predicate.
    179       * If this fluent iterable is empty, {@code true} is returned.
    180       */
    181      public final boolean allMatch(Predicate<? super E> predicate) {
    182        return Iterables.all(iterable, predicate);
    183      }
    184
    185      /**
    186       * Returns an {@link Optional} containing the first element in this fluent iterable that
    187       * satisfies the given predicate, if such an element exists.
    188       *
    189       * <p><b>Warning:</b> avoid using a {@code predicate} that matches {@code null}. If {@code null}
    190       * is matched in this fluent iterable, a {@link NullPointerException} will be thrown.
    191       */
    192      public final Optional<E> firstMatch(Predicate<? super E> predicate) {
    193        return Iterables.tryFind(iterable, predicate);
    194      }
    195
    196      /**
    197       * Returns a fluent iterable that applies {@code function} to each element of this
    198       * fluent iterable.
    199       *
    200       * <p>The returned fluent iterable's iterator supports {@code remove()} if this iterable's
    201       * iterator does. After a successful {@code remove()} call, this fluent iterable no longer
    202       * contains the corresponding element.
    203       */
    204      public final <T> FluentIterable<T> transform(Function<? super E, T> function) {
    205        return from(Iterables.transform(iterable, function));
    206      }
    207
    208      /**
    209       * Applies {@code function} to each element of this fluent iterable and returns
    210       * a fluent iterable with the concatenated combination of results.  {@code function}
    211       * returns an Iterable of results.
    212       *
    213       * <p>The returned fluent iterable's iterator supports {@code remove()} if this
    214       * function-returned iterables' iterator does. After a successful {@code remove()} call,
    215       * the returned fluent iterable no longer contains the corresponding element.
    216       *
    217       * @since 13.0
    218       */
    219      public <T> FluentIterable<T> transformAndConcat(
    220          Function<? super E, ? extends Iterable<T>> function) {
    221        return from(Iterables.concat(transform(function)));
    222      }
    223
    224      /**
    225       * Returns an {@link Optional} containing the first element in this fluent iterable.
    226       * If the iterable is empty, {@code Optional.absent()} is returned.
    227       *
    228       * @throws NullPointerException if the first element is null; if this is a possibility, use
    229       *     {@code iterator().next()} or {@link Iterables#getFirst} instead.
    230       */
    231      public final Optional<E> first() {
    232        Iterator<E> iterator = iterable.iterator();
    233        return iterator.hasNext()
    234            ? Optional.of(iterator.next())
    235            : Optional.<E>absent();
    236      }
    237
    238      /**
    239       * Returns an {@link Optional} containing the last element in this fluent iterable.
    240       * If the iterable is empty, {@code Optional.absent()} is returned.
    241       *
    242       * @throws NullPointerException if the last element is null; if this is a possibility, use
    243       *     {@link Iterables#getLast} instead.
    244       */
    245      public final Optional<E> last() {
    246        // Iterables#getLast was inlined here so we don't have to throw/catch a NSEE
    247
    248        // TODO(kevinb): Support a concurrently modified collection?
    249        if (iterable instanceof List) {
    250          List<E> list = (List<E>) iterable;
    251          if (list.isEmpty()) {
    252            return Optional.absent();
    253          }
    254          return Optional.of(list.get(list.size() - 1));
    255        }
    256        Iterator<E> iterator = iterable.iterator();
    257        if (!iterator.hasNext()) {
    258          return Optional.absent();
    259        }
    260
    261        /*
    262         * TODO(kevinb): consider whether this "optimization" is worthwhile. Users
    263         * with SortedSets tend to know they are SortedSets and probably would not
    264         * call this method.
    265         */
    266        if (iterable instanceof SortedSet) {
    267          SortedSet<E> sortedSet = (SortedSet<E>) iterable;
    268          return Optional.of(sortedSet.last());
    269        }
    270
    271        while (true) {
    272          E current = iterator.next();
    273          if (!iterator.hasNext()) {
    274            return Optional.of(current);
    275          }
    276        }
    277      }
    278
    279      /**
    280       * Returns a view of this fluent iterable that skips its first {@code numberToSkip}
    281       * elements. If this fluent iterable contains fewer than {@code numberToSkip} elements,
    282       * the returned fluent iterable skips all of its elements.
    283       *
    284       * <p>Modifications to this fluent iterable before a call to {@code iterator()} are
    285       * reflected in the returned fluent iterable. That is, the its iterator skips the first
    286       * {@code numberToSkip} elements that exist when the iterator is created, not when {@code skip()}
    287       * is called.
    288       *
    289       * <p>The returned fluent iterable's iterator supports {@code remove()} if the
    290       * {@code Iterator} of this fluent iterable supports it. Note that it is <i>not</i>
    291       * possible to delete the last skipped element by immediately calling {@code remove()} on the
    292       * returned fluent iterable's iterator, as the {@code Iterator} contract states that a call
    293       * to {@code * remove()} before a call to {@code next()} will throw an
    294       * {@link IllegalStateException}.
    295       */
    296      public final FluentIterable<E> skip(int numberToSkip) {
    297        return from(Iterables.skip(iterable, numberToSkip));
    298      }
    299
    300      /**
    301       * Creates a fluent iterable with the first {@code size} elements of this
    302       * fluent iterable. If this fluent iterable does not contain that many elements,
    303       * the returned fluent iterable will have the same behavior as this fluent iterable.
    304       * The returned fluent iterable's iterator supports {@code remove()} if this
    305       * fluent iterable's iterator does.
    306       *
    307       * @param size the maximum number of elements in the returned fluent iterable
    308       * @throws IllegalArgumentException if {@code size} is negative
    309       */
    310      public final FluentIterable<E> limit(int size) {
    311        return from(Iterables.limit(iterable, size));
    312      }
    313
    314      /**
    315       * Determines whether this fluent iterable is empty.
    316       */
    317      public final boolean isEmpty() {
    318        return !iterable.iterator().hasNext();
    319      }
    320
    321      /**
    322       * Returns an {@code ImmutableList} containing all of the elements from this
    323       * fluent iterable in proper sequence.
    324       */
    325      public final ImmutableList<E> toImmutableList() {
    326        return ImmutableList.copyOf(iterable);
    327      }
    328
    329      /**
    330       * Returns an {@code ImmutableList} containing all of the elements from this
    331       * {@code FluentIterable} in the order specified by {@code comparator}.  To produce an
    332       * {@code ImmutableList} sorted by its natural ordering, use
    333       * {@code toSortedImmutableList(Ordering.natural())}.
    334       *
    335       * @param comparator the function by which to sort list elements
    336       * @throws NullPointerException if any element is null
    337       * @since 13.0
    338       */
    339      public final ImmutableList<E> toSortedImmutableList(Comparator<? super E> comparator) {
    340        return Ordering.from(comparator).immutableSortedCopy(iterable);
    341      }
    342
    343      /**
    344       * Returns an {@code ImmutableSet} containing all of the elements from this
    345       * fluent iterable with duplicates removed.
    346       */
    347      public final ImmutableSet<E> toImmutableSet() {
    348        return ImmutableSet.copyOf(iterable);
    349      }
    350
    351      /**
    352       * Returns an {@code ImmutableSortedSet} containing all of the elements from this
    353       * {@code FluentIterable} in the order specified by {@code comparator}, with duplicates
    354       * (determined by {@code comaprator.compare(x, y) == 0}) removed. To produce an
    355       * {@code ImmutableSortedSet} sorted by its natural ordering, use
    356       * {@code toImmutableSortedSet(Ordering.natural())}.
    357       *
    358       * @param comparator the function by which to sort set elements
    359       * @throws NullPointerException if any element is null
    360       */
    361      public final ImmutableSortedSet<E> toImmutableSortedSet(Comparator<? super E> comparator) {
    362        return ImmutableSortedSet.copyOf(comparator, iterable);
    363      }
    364
    365      /**
    366       * Returns an array containing all of the elements from this fluent iterable in iteration order.
    367       *
    368       * @param type the type of the elements
    369       * @return a newly-allocated array into which all the elements of this fluent iterable have
    370       *     been copied
    371       */
    372      @GwtIncompatible("Array.newArray(Class, int)")
    373      public final E[] toArray(Class<E> type) {
    374        return Iterables.toArray(iterable, type);
    375      }
    376
    377      /**
    378       * Returns the element at the specified position in this fluent iterable.
    379       *
    380       * @param position position of the element to return
    381       * @return the element at the specified position in this fluent iterable
    382       * @throws IndexOutOfBoundsException if {@code position} is negative or greater than or equal to
    383       *     the size of this fluent iterable
    384       */
    385      public final E get(int position) {
    386        return Iterables.get(iterable, position);
    387      }
    388
    389      /**
    390       * Function that transforms {@code Iterable<E>} into a fluent iterable.
    391       */
    392      private static class FromIterableFunction<E>
    393          implements Function<Iterable<E>, FluentIterable<E>> {
    394        @Override
    395        public FluentIterable<E> apply(Iterable<E> fromObject) {
    396          return FluentIterable.from(fromObject);
    397        }
    398      }
    399    }