alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (Iterables.java)

This example Java source code file (Iterables.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

annotation, canignorereturnvalue, collection, fluentiterable, function, iterable, iterator, list, nullable, object, override, predicate, string, unmodifiableiterable, util

The Iterables.java Java example source code

/*
 * 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.Beta;
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.errorprone.annotations.CanIgnoreReturnValue;

import java.util.Collection;
import java.util.Collections;
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 javax.annotation.Nullable;

/**
 * This class contains 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.
 *
 * <p>Performance notes: Unless otherwise noted, all of the iterables
 * produced in this class are <i>lazy, which means that their iterators
 * only advance the backing iteration when absolutely necessary.
 *
 * <p>See the Guava User Guide article on  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<T> result = (Iterable) iterable;
      return result;
    }
    return new UnmodifiableIterable<T>(iterable);
  }

  /**
   * Simply returns its argument.
   *
   * @deprecated no need to use this
   * @since 10.0
   */
  @Deprecated
  public static <E> Iterable unmodifiableIterable(ImmutableCollection iterable) {
    return checkNotNull(iterable);
  }

  private static final class UnmodifiableIterable<T> extends FluentIterable {
    private final Iterable<? extends T> iterable;

    private UnmodifiableIterable(Iterable<? extends T> iterable) {
      this.iterable = iterable;
    }

    @Override
    public Iterator<T> iterator() {
      return Iterators.unmodifiableIterator(iterable.iterator());
    }

    @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 object for which {@code equals(element)}
   * is true.
   */
  public static boolean contains(Iterable<?> iterable, @Nullable 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.
   *
   * <p>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.
   *
   * <p>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.
   *
   * <p>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}.
   *
   * @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 <T> boolean removeIf(Iterable removeFrom, Predicate predicate) {
    if (removeFrom instanceof RandomAccess && removeFrom instanceof List) {
      return removeIfFromRandomAccessList((List<T>) removeFrom, checkNotNull(predicate));
    }
    return Iterators.removeIf(removeFrom.iterator(), predicate);
  }

  private static <T> boolean removeIfFromRandomAccessList(
      List<T> list, Predicate predicate) {
    // Note: Not all random access lists support set(). Additionally, it's possible
    // for a list to reject setting an element, such as when the list does not permit
    // duplicate elements. For both of those cases,  we need to fall back to a slower
    // implementation.
    int from = 0;
    int to = 0;

    for (; from < list.size(); from++) {
      T element = list.get(from);
      if (!predicate.apply(element)) {
        if (from > to) {
          try {
            list.set(to, element);
          } catch (UnsupportedOperationException e) {
            slowRemoveIfForRemainingElements(list, predicate, to, from);
            return true;
          } catch (IllegalArgumentException e) {
            slowRemoveIfForRemainingElements(list, predicate, to, from);
            return true;
          }
        }
        to++;
      }
    }

    // Clear the tail of any remaining items
    list.subList(to, list.size()).clear();
    return from != to;
  }

  private static <T> void slowRemoveIfForRemainingElements(
      List<T> list, Predicate predicate, int to, int from) {
    // Here we know that:
    // * (to < from) and that both are valid indices.
    // * Everything with (index < to) should be kept.
    // * Everything with (to <= index < from) should be removed.
    // * The element with (index == from) should be kept.
    // * Everything with (index > from) has not been checked yet.

    // Check from the end of the list backwards (minimize expected cost of
    // moving elements when remove() is called). Stop before 'from' because
    // we already know that should be kept.
    for (int n = list.size() - 1; n > from; n--) {
      if (predicate.apply(list.get(n))) {
        list.remove(n);
      }
    }
    // And now remove everything in the range [to, from) (going backwards).
    for (int n = from - 1; n >= to; n--) {
      list.remove(n);
    }
  }

  /**
   * Removes and returns the first matching element, or returns {@code null} if there is none.
   */
  @Nullable
  static <T> T removeFirstMatching(Iterable removeFrom, Predicate predicate) {
    checkNotNull(predicate);
    Iterator<T> 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
   * <i>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}.
   *
   * @throws NoSuchElementException if the iterable is empty
   * @throws IllegalArgumentException if the iterable contains multiple
   *     elements
   */
  public static <T> 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.
   *
   * @throws IllegalArgumentException if the iterator contains multiple
   *     elements
   */
  @Nullable
  public static <T> T getOnlyElement(Iterable iterable, @Nullable 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> T[] toArray(Iterable iterable, Class type) {
    return toArray(iterable, ObjectArrays.newArray(type, 0));
  }

  static <T> T[] toArray(Iterable iterable, T[] array) {
    Collection<? extends T> 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 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 <E> Collection castOrCopyToCollection(Iterable iterable) {
    return (iterable instanceof Collection)
        ? (Collection<E>) 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 <T> boolean addAll(Collection addTo, Iterable elementsToAdd) {
    if (elementsToAdd instanceof Collection) {
      Collection<? extends T> c = Collections2.cast(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}.
   *
   * @see Collections#frequency
   */
  public static int frequency(Iterable<?> iterable, @Nullable 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}.
   *
   * <p>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.
   *
   * <p>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.
   *
   * <p>To cycle over the iterable {@code n} times, use the following:
   * {@code Iterables.concat(Collections.nCopies(n, iterable))}
   */
  public static <T> Iterable cycle(final Iterable iterable) {
    checkNotNull(iterable);
    return new FluentIterable<T>() {
      @Override
      public Iterator<T> iterator() {
        return Iterators.cycle(iterable);
      }

      @Override
      public String toString() {
        return iterable.toString() + " (cycled)";
      }
    };
  }

  /**
   * Returns an iterable whose iterators cycle indefinitely over the provided
   * elements.
   *
   * <p>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.
   *
   * <p>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.
   *
   * <p>To cycle over the elements {@code n} times, use the following:
   * {@code Iterables.concat(Collections.nCopies(n, Arrays.asList(elements)))}
   */
  public static <T> 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.
   *
   * <p>The returned iterable's iterator supports {@code remove()} when the
   * corresponding input iterator supports it.
   */
  public static <T> 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.
   *
   * <p>The returned iterable's iterator supports {@code remove()} when the
   * corresponding input iterator supports it.
   */
  public static <T> Iterable concat(
      Iterable<? extends T> 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.
   *
   * <p>The returned iterable's iterator supports {@code remove()} when the
   * corresponding input iterator supports it.
   */
  public static <T> Iterable concat(
      Iterable<? extends T> a,
      Iterable<? extends T> b,
      Iterable<? extends T> c,
      Iterable<? extends T> 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.
   *
   * <p>The returned iterable's iterator supports {@code remove()} when the
   * corresponding input iterator supports it.
   *
   * @throws NullPointerException if any of the provided iterables is null
   */
  public static <T> Iterable concat(Iterable... inputs) {
    return concat(ImmutableList.copyOf(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.
   *
   * <p>The returned iterable's iterator supports {@code remove()} when the
   * corresponding input iterator supports it. The methods of the returned
   * iterable may throw {@code NullPointerException} if any of the input
   * iterators is null.
   */
  public static <T> 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.
   *
   * <p>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.
   *
   * <p>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 <T> Iterable> partition(final Iterable iterable, final int size) {
    checkNotNull(iterable);
    checkArgument(size > 0);
    return new FluentIterable<List() {
      @Override
      public Iterator<List 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.
   *
   * <p>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 <T> Iterable> paddedPartition(final Iterable iterable, final int size) {
    checkNotNull(iterable);
    checkArgument(size > 0);
    return new FluentIterable<List() {
      @Override
      public Iterator<List 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()}.
   */
  public static <T> Iterable filter(
      final Iterable<T> unfiltered, final Predicate retainIfTrue) {
    checkNotNull(unfiltered);
    checkNotNull(retainIfTrue);
    return new FluentIterable<T>() {
      @Override
      public Iterator<T> iterator() {
        return Iterators.filter(unfiltered.iterator(), 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()}.
   */
  @GwtIncompatible // Class.isInstance
  public static <T> Iterable filter(final Iterable unfiltered, final Class desiredType) {
    checkNotNull(unfiltered);
    checkNotNull(desiredType);
    return new FluentIterable<T>() {
      @Override
      public Iterator<T> iterator() {
        return Iterators.filter(unfiltered.iterator(), desiredType);
      }
    };
  }

  /**
   * Returns {@code true} if any element in {@code iterable} satisfies the predicate.
   */
  public static <T> 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.
   */
  public static <T> 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 <i>no element will match, use {@link #tryFind} or
   * {@link #find(Iterable, Predicate, Object)} instead.
   *
   * @throws NoSuchElementException if no element in {@code iterable} matches
   *     the given predicate
   */
  public static <T> 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)}.
   *
   * @since 7.0
   */
  @Nullable
  public static <T> T find(
      Iterable<? extends T> iterable, Predicate predicate, @Nullable 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.
   *
   * <p>Warning: avoid using a {@code predicate} that matches {@code
   * null}. If {@code null} is matched in {@code iterable}, a
   * NullPointerException will be thrown.
   *
   * @since 11.0
   */
  public static <T> 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.
   *
   * <p>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 <T> 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}.
   *
   * <p>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.
   *
   * <p>If the input {@code Iterable} is known to be a {@code List} or other
   * {@code Collection}, consider {@link Lists#transform} and {@link
   * Collections2#transform}.
   */
  public static <F, T> Iterable transform(
      final Iterable<F> fromIterable, final Function function) {
    checkNotNull(fromIterable);
    checkNotNull(function);
    return new FluentIterable<T>() {
      @Override
      public Iterator<T> iterator() {
        return Iterators.transform(fromIterable.iterator(), function);
      }
    };
  }

  /**
   * Returns the element at the specified position in an iterable.
   *
   * @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}
   */
  public static <T> T get(Iterable iterable, int position) {
    checkNotNull(iterable);
    return (iterable instanceof List)
        ? ((List<T>) iterable).get(position)
        : Iterators.get(iterable.iterator(), position);
  }

  /**
   * Returns the element at the specified position in an iterable or a default
   * value otherwise.
   *
   * @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
   */
  @Nullable
  public static <T> T get(Iterable iterable, int position, @Nullable T defaultValue) {
    checkNotNull(iterable);
    Iterators.checkNonnegative(position);
    if (iterable instanceof List) {
      List<? extends T> list = Lists.cast(iterable);
      return (position < list.size()) ? list.get(position) : defaultValue;
    } else {
      Iterator<? extends T> 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}.
   *
   * <p>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.
   *
   * @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
   */
  @Nullable
  public static <T> T getFirst(Iterable iterable, @Nullable 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)}.
   *
   * @return the last element of {@code iterable}
   * @throws NoSuchElementException if the iterable is empty
   */
  public static <T> T getLast(Iterable iterable) {
    // TODO(kevinb): Support a concurrently modified collection?
    if (iterable instanceof List) {
      List<T> 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)}.
   *
   * @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
   */
  @Nullable
  public static <T> T getLast(Iterable iterable, @Nullable T defaultValue) {
    if (iterable instanceof Collection) {
      Collection<? extends T> c = Collections2.cast(iterable);
      if (c.isEmpty()) {
        return defaultValue;
      } else if (iterable instanceof List) {
        return getLastInNonemptyList(Lists.cast(iterable));
      }
    }

    return Iterators.getLast(iterable.iterator(), defaultValue);
  }

  private static <T> 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.
   *
   * <p>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.
   *
   * <p>The returned iterable's iterator supports {@code remove()} if the
   * iterator of the underlying iterable supports it. Note that it is
   * <i>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}.
   *
   * @since 3.0
   */
  public static <T> Iterable skip(final Iterable iterable, final int numberToSkip) {
    checkNotNull(iterable);
    checkArgument(numberToSkip >= 0, "number to skip cannot be negative");

    if (iterable instanceof List) {
      final List<T> list = (List) iterable;
      return new FluentIterable<T>() {
        @Override
        public Iterator<T> iterator() {
          // TODO(kevinb): Support a concurrently modified collection?
          int toSkip = Math.min(list.size(), numberToSkip);
          return list.subList(toSkip, list.size()).iterator();
        }
      };
    }

    return new FluentIterable<T>() {
      @Override
      public Iterator<T> iterator() {
        final Iterator<T> 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<T>() {
          boolean atStart = true;

          @Override
          public boolean hasNext() {
            return iterator.hasNext();
          }

          @Override
          public T next() {
            T result = iterator.next();
            atStart = false; // not called if next() fails
            return result;
          }

          @Override
          public void remove() {
            checkRemove(!atStart);
            iterator.remove();
          }
        };
      }
    };
  }

  /**
   * 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.
   *
   * @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 <T> Iterable limit(final Iterable iterable, final int limitSize) {
    checkNotNull(iterable);
    checkArgument(limitSize >= 0, "limit is negative");
    return new FluentIterable<T>() {
      @Override
      public Iterator<T> iterator() {
        return Iterators.limit(iterable.iterator(), limitSize);
      }
    };
  }

  /**
   * Returns a view of the supplied iterable that wraps each generated
   * {@link Iterator} through {@link Iterators#consumingIterator(Iterator)}.
   *
   * <p>Note: If {@code iterable} is a {@link Queue}, the returned iterable will
   * get entries from {@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()}.
   *
   * @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 <T> Iterable consumingIterable(final Iterable iterable) {
    if (iterable instanceof Queue) {
      return new FluentIterable<T>() {
        @Override
        public Iterator<T> iterator() {
          return new ConsumingQueueIterator<T>((Queue) iterable);
        }

        @Override
        public String toString() {
          return "Iterables.consumingIterable(...)";
        }
      };
    }

    checkNotNull(iterable);

    return new FluentIterable<T>() {
      @Override
      public Iterator<T> iterator() {
        return 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.
   *
   * <p>There is no precise {@link Iterator} equivalent to this method, since
   * one can only ask an iterator whether it has any elements <i>remaining
   * (which one does using {@link Iterator#hasNext}).
   *
   * @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.
   *
   * <p>Callers must ensure that the source {@code iterables} are in
   * non-descending order as this method does not sort its input.
   *
   * <p>For any equivalent elements across all {@code iterables}, it is
   * undefined which element is returned first.
   *
   * @since 11.0
   */
  @Beta
  public static <T> Iterable mergeSorted(
      final Iterable<? extends Iterable iterables,
      final Comparator<? super T> comparator) {
    checkNotNull(iterables, "iterables");
    checkNotNull(comparator, "comparator");
    Iterable<T> iterable =
        new FluentIterable<T>() {
          @Override
          public Iterator<T> iterator() {
            return Iterators.mergeSorted(
                Iterables.transform(iterables, Iterables.<T>toIterator()), comparator);
          }
        };
    return new UnmodifiableIterable<T>(iterable);
  }

  // TODO(user): Is this the best place for this? Move to fluent functions?
  // Useful as a public method?
  static <T> Function, Iterator> toIterator() {
    return new Function<Iterable>() {
      @Override
      public Iterator<? extends T> apply(Iterable iterable) {
        return iterable.iterator();
      }
    };
  }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.