| /* |
| * Copyright (C) 2007 Google Inc. |
| * |
| * 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.inject.internal; |
| |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Enumeration; |
| import java.util.Iterator; |
| import java.util.ListIterator; |
| import java.util.NoSuchElementException; |
| |
| /** |
| * This class contains static utility methods that operate on or return objects |
| * of type {@code Iterator}. Also see the parallel implementations in {@link |
| * Iterables}. |
| * |
| * @author Kevin Bourrillion |
| * @author Scott Bonneau |
| */ |
| public final class Iterators { |
| private Iterators() {} |
| |
| static final Iterator<Object> EMPTY_ITERATOR |
| = new UnmodifiableIterator<Object>() { |
| public boolean hasNext() { |
| return false; |
| } |
| public Object next() { |
| throw new NoSuchElementException(); |
| } |
| }; |
| |
| |
| /** Returns the empty {@code Iterator}. */ |
| // Casting to any type is safe since there are no actual elements. |
| @SuppressWarnings("unchecked") |
| public static <T> UnmodifiableIterator<T> emptyIterator() { |
| return (UnmodifiableIterator<T>) EMPTY_ITERATOR; |
| } |
| |
| private static final ListIterator<Object> EMPTY_LIST_ITERATOR = |
| new ListIterator<Object>() { |
| public boolean hasNext() { |
| return false; |
| } |
| public boolean hasPrevious() { |
| return false; |
| } |
| public int nextIndex() { |
| return 0; |
| } |
| public int previousIndex() { |
| return -1; |
| } |
| public Object next() { |
| throw new NoSuchElementException(); |
| } |
| public Object previous() { |
| throw new NoSuchElementException(); |
| } |
| public void set(Object o) { |
| throw new UnsupportedOperationException(); |
| } |
| public void add(Object o) { |
| throw new UnsupportedOperationException(); |
| } |
| public void remove() { |
| throw new UnsupportedOperationException(); |
| } |
| }; |
| |
| /** Returns the empty {@code ListIterator}. */ |
| // Casting to any type is safe since there are no actual elements. |
| @SuppressWarnings("unchecked") |
| public static <T> ListIterator<T> emptyListIterator() { |
| return (ListIterator<T>) EMPTY_LIST_ITERATOR; |
| } |
| |
| /** Returns an unmodifiable view of {@code iterator}. */ |
| public static <T> UnmodifiableIterator<T> unmodifiableIterator( |
| final Iterator<T> iterator) { |
| Preconditions.checkNotNull(iterator); |
| return new UnmodifiableIterator<T>() { |
| public boolean hasNext() { |
| return iterator.hasNext(); |
| } |
| public T next() { |
| return iterator.next(); |
| } |
| }; |
| } |
| |
| |
| /** |
| * Returns a string representation of {@code iterator}, with the format |
| * {@code [e1, e2, ..., en]}. The iterator will be left exhausted: its |
| * {@code hasNext()} method will return {@code false}. |
| */ |
| public static String toString(Iterator<?> iterator) { |
| if (!iterator.hasNext()) { |
| return "[]"; |
| } |
| StringBuilder builder = new StringBuilder(); |
| builder.append('[').append(iterator.next()); |
| while (iterator.hasNext()) { |
| builder.append(", ").append(iterator.next()); |
| } |
| return builder.append(']').toString(); |
| } |
| |
| /** |
| * Returns the single element contained in {@code iterator}. |
| * |
| * @throws NoSuchElementException if the iterator is empty |
| * @throws IllegalArgumentException if the iterator contains multiple |
| * elements. The state of the iterator is unspecified. |
| */ |
| public static <T> T getOnlyElement(Iterator<T> iterator) { |
| T first = iterator.next(); |
| if (!iterator.hasNext()) { |
| return first; |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| sb.append("expected one element but was: <" + first); |
| for (int i = 0; i < 4 && iterator.hasNext(); i++) { |
| sb.append(", " + iterator.next()); |
| } |
| if (iterator.hasNext()) { |
| sb.append(", ..."); |
| } |
| sb.append(">"); |
| |
| throw new IllegalArgumentException(sb.toString()); |
| } |
| |
| /** |
| * Combines multiple iterators into a single iterator. The returned iterator |
| * iterates across the elements of each iterator in {@code inputs}. The input |
| * iterators are not polled until necessary. |
| * |
| * <p>The returned iterator supports {@code remove()} when the corresponding |
| * input iterator supports it. The methods of the returned iterator may throw |
| * {@code NullPointerException} if any of the input iterators are null. |
| */ |
| public static <T> Iterator<T> concat( |
| final Iterator<? extends Iterator<? extends T>> inputs) { |
| Preconditions.checkNotNull(inputs); |
| return new Iterator<T>() { |
| Iterator<? extends T> current = emptyIterator(); |
| Iterator<? extends T> removeFrom; |
| |
| public boolean hasNext() { |
| while (!current.hasNext() && inputs.hasNext()) { |
| current = inputs.next(); |
| } |
| return current.hasNext(); |
| } |
| public T next() { |
| if (!hasNext()) { |
| throw new NoSuchElementException(); |
| } |
| removeFrom = current; |
| return current.next(); |
| } |
| public void remove() { |
| Preconditions.checkState(removeFrom != null, |
| "no calls to next() since last call to remove()"); |
| removeFrom.remove(); |
| removeFrom = null; |
| } |
| }; |
| } |
| |
| |
| /** |
| * Returns an iterator that applies {@code function} to each element of {@code |
| * fromIterator}. |
| * |
| * <p>The returned iterator supports {@code remove()} if the provided iterator |
| * does. After a successful {@code remove()} call, {@code fromIterator} no |
| * longer contains the corresponding element. |
| */ |
| public static <F, T> Iterator<T> transform(final Iterator<F> fromIterator, |
| final Function<? super F, ? extends T> function) { |
| Preconditions.checkNotNull(fromIterator); |
| Preconditions.checkNotNull(function); |
| return new Iterator<T>() { |
| public boolean hasNext() { |
| return fromIterator.hasNext(); |
| } |
| public T next() { |
| F from = fromIterator.next(); |
| return function.apply(from); |
| } |
| public void remove() { |
| fromIterator.remove(); |
| } |
| }; |
| } |
| |
| // Methods only in Iterators, not in Iterables |
| |
| /** |
| * Returns an iterator containing the elements of {@code array} in order. The |
| * returned iterator is a view of the array; subsequent changes to the array |
| * will be reflected in the iterator. |
| * |
| * <p><b>Note:</b> It is often preferable to represent your data using a |
| * collection type, for example using {@link Arrays#asList(Object[])}, making |
| * this method unnecessary. |
| */ |
| public static <T> UnmodifiableIterator<T> forArray(final T... array) { |
| // optimized. benchmarks at nearly 2x of the straightforward impl |
| return new UnmodifiableIterator<T>() { |
| final int length = array.length; |
| int i = 0; |
| public boolean hasNext() { |
| return i < length; |
| } |
| public T next() { |
| try { |
| // 'return array[i++];' almost works |
| T t = array[i]; |
| i++; |
| return t; |
| } catch (ArrayIndexOutOfBoundsException e) { |
| throw new NoSuchElementException(); |
| } |
| } |
| }; |
| } |
| |
| /** |
| * Returns an iterator containing the elements in the specified range of |
| * {@code array} in order. The returned iterator is a view of the array; |
| * subsequent changes to the array will be reflected in the iterator. |
| * |
| * @param array array to read elements out of |
| * @param offset index of first array element to retrieve |
| * @param length number of elements in iteration |
| * |
| * @throws IndexOutOfBoundsException if {@code offset} is negative, |
| * {@code length} is negative, or {@code offset + length > array.length} |
| */ |
| public static <T> UnmodifiableIterator<T> forArray( |
| final T[] array, final int offset, final int length) { |
| Preconditions.checkArgument(length >= 0); |
| final int end = offset + length; |
| |
| // Technically we should give a slightly more descriptive error on overflow |
| Preconditions.checkPositionIndexes(offset, end, array.length); |
| |
| // If length == 0 is a common enough case, we could return emptyIterator(). |
| |
| return new UnmodifiableIterator<T>() { |
| int i = offset; |
| public boolean hasNext() { |
| return i < end; |
| } |
| public T next() { |
| if (!hasNext()) { |
| throw new NoSuchElementException(); |
| } |
| return array[i++]; |
| } |
| }; |
| } |
| |
| /** |
| * Returns an iterator containing only {@code value}. |
| */ |
| public static <T> UnmodifiableIterator<T> singletonIterator( |
| @Nullable final T value) { |
| return new UnmodifiableIterator<T>() { |
| boolean done; |
| public boolean hasNext() { |
| return !done; |
| } |
| public T next() { |
| if (done) { |
| throw new NoSuchElementException(); |
| } |
| done = true; |
| return value; |
| } |
| }; |
| } |
| |
| /** |
| * Adapts an {@code Iterator} to the {@code Enumeration} interface. |
| * |
| * @see Collections#enumeration(Collection) |
| */ |
| public static <T> Enumeration<T> asEnumeration(final Iterator<T> iterator) { |
| Preconditions.checkNotNull(iterator); |
| return new Enumeration<T>() { |
| public boolean hasMoreElements() { |
| return iterator.hasNext(); |
| } |
| public T nextElement() { |
| return iterator.next(); |
| } |
| }; |
| } |
| } |