removeFrom, Predicate predicate) {
checkNotNull(predicate);
boolean modified = false ;
while (removeFrom.hasNext()) {
if (predicate.apply(removeFrom.next())) {
removeFrom.remove();
modified = true ;
}
}
return modified;
}
@CanIgnoreReturnValue
public static boolean retainAll (Iterator removeFrom, Collection elementsToRetain) {
checkNotNull(elementsToRetain);
boolean result = false ;
while (removeFrom.hasNext()) {
if (!elementsToRetain.contains(removeFrom.next())) {
removeFrom.remove();
result = true ;
}
}
return result;
}
public static boolean elementsEqual (Iterator iterator1, Iterator iterator2) {
while (iterator1.hasNext()) {
if (!iterator2.hasNext()) {
return false ;
}
Object o1 = iterator1.next();
Object o2 = iterator2.next();
if (!Objects.equal(o1, o2)) {
return false ;
}
}
return !iterator2.hasNext();
}
public static String toString (Iterator iterator) {
StringBuilder sb = new StringBuilder().append('[' );
boolean first = true ;
while (iterator.hasNext()) {
if (!first) {
sb.append(", " );
}
first = false ;
sb.append(iterator.next());
}
return sb.append(']' ).toString();
}
@CanIgnoreReturnValue
public static T getOnlyElement (Iterator iterator) {
T first = iterator.next();
if (!iterator.hasNext()) {
return first;
}
StringBuilder sb = new StringBuilder().append("expected one element but was: <" ).append(first);
for (int i = 0 ; i < 4 && iterator.hasNext(); i++) {
sb.append(", " ).append(iterator.next());
}
if (iterator.hasNext()) {
sb.append(", ..." );
}
sb.append('>' );
throw new IllegalArgumentException(sb.toString());
}
@CanIgnoreReturnValue
public static @Nullable T getOnlyElement (
Iterator iterator, @Nullable T defaultValue) {
return iterator.hasNext() ? getOnlyElement(iterator) : defaultValue;
}
@GwtIncompatible
public static T[] toArray(Iterator iterator, Class type) {
List list = Lists.newArrayList(iterator);
return Iterables.toArray(list, type);
}
@CanIgnoreReturnValue
public static boolean addAll (Collection addTo, Iterator iterator) {
checkNotNull(addTo);
checkNotNull(iterator);
boolean wasModified = false ;
while (iterator.hasNext()) {
wasModified |= addTo.add(iterator.next());
}
return wasModified;
}
public static int frequency (Iterator iterator, @Nullable Object element) {
int count = 0 ;
while (contains(iterator, element)) {
count++;
}
return count;
}
public static Iterator cycle (final Iterable iterable) {
checkNotNull(iterable);
return new Iterator() {
Iterator iterator = emptyModifiableIterator();
@Override
public boolean hasNext () {
return iterator.hasNext() || iterable.iterator().hasNext();
}
@Override
public T next () {
if (!iterator.hasNext()) {
iterator = iterable.iterator();
if (!iterator.hasNext()) {
throw new NoSuchElementException();
}
}
return iterator.next();
}
@Override
public void remove () {
iterator.remove();
}
};
}
@SafeVarargs
public static Iterator cycle (T... elements) {
return cycle(Lists.newArrayList(elements));
}
private static Iterator consumingForArray (final T... elements) {
return new UnmodifiableIterator() {
int index = 0 ;
@Override
public boolean hasNext () {
return index < elements.length;
}
@Override
public T next () {
if (!hasNext()) {
throw new NoSuchElementException();
}
T result = elements[index];
elements[index] = null ;
index++;
return result;
}
};
}
public static Iterator concat (Iterator a, Iterator b) {
checkNotNull(a);
checkNotNull(b);
return concat(consumingForArray(a, b));
}
public static Iterator concat (
Iterator a, Iterator b, Iterator c) {
checkNotNull(a);
checkNotNull(b);
checkNotNull(c);
return concat(consumingForArray(a, b, c));
}
public static Iterator concat (
Iterator a,
Iterator b,
Iterator c,
Iterator d) {
checkNotNull(a);
checkNotNull(b);
checkNotNull(c);
checkNotNull(d);
return concat(consumingForArray(a, b, c, d));
}
public static Iterator concat (Iterator... inputs) {
return concatNoDefensiveCopy(Arrays.copyOf(inputs, inputs.length));
}
public static Iterator concat (Iterator> inputs) {
return new ConcatenatedIterator(inputs);
}
static Iterator concatNoDefensiveCopy (Iterator... inputs) {
for (Iterator input : checkNotNull(inputs)) {
checkNotNull(input);
}
return concat(consumingForArray(inputs));
}
public static UnmodifiableIterator> partition(Iterator iterator, int size) {
return partitionImpl(iterator, size, false );
}
public static UnmodifiableIterator> paddedPartition(Iterator iterator, int size) {
return partitionImpl(iterator, size, true );
}
private static UnmodifiableIterator> partitionImpl(
final Iterator iterator, final int size, final boolean pad) {
checkNotNull(iterator);
checkArgument(size > 0 );
return new UnmodifiableIterator>() {
@Override
public boolean hasNext () {
return iterator.hasNext();
}
@Override
public List next () {
if (!hasNext()) {
throw new NoSuchElementException();
}
Object[] array = new Object[size];
int count = 0 ;
for (; count < size && iterator.hasNext(); count++) {
array[count] = iterator.next();
}
for (int i = count; i < size; i++) {
array[i] = null ;
}
@SuppressWarnings ("unchecked" )
List list = Collections.unmodifiableList((List) Arrays.asList(array));
return (pad || count == size) ? list : list.subList(0 , count);
}
};
}
public static UnmodifiableIterator filter (
final Iterator unfiltered, final Predicate retainIfTrue) {
checkNotNull(unfiltered);
checkNotNull(retainIfTrue);
return new AbstractIterator() {
@Override
protected T computeNext () {
while (unfiltered.hasNext()) {
T element = unfiltered.next();
if (retainIfTrue.apply(element)) {
return element;
}
}
return endOfData();
}
};
}
@SuppressWarnings ("unchecked" )
@GwtIncompatible
public static UnmodifiableIterator filter (Iterator unfiltered, Class desiredType) {
return (UnmodifiableIterator) filter(unfiltered, instanceOf(desiredType));
}
public static boolean any (Iterator iterator, Predicate predicate) {
return indexOf(iterator, predicate) != -1 ;
}
public static boolean all (Iterator iterator, Predicate predicate) {
checkNotNull(predicate);
while (iterator.hasNext()) {
T element = iterator.next();
if (!predicate.apply(element)) {
return false ;
}
}
return true ;
}
public static T find (Iterator iterator, Predicate predicate) {
checkNotNull(iterator);
checkNotNull(predicate);
while (iterator.hasNext()) {
T t = iterator.next();
if (predicate.apply(t)) {
return t;
}
}
throw new NoSuchElementException();
}
public static @Nullable T find (
Iterator iterator, Predicate predicate, @Nullable T defaultValue) {
checkNotNull(iterator);
checkNotNull(predicate);
while (iterator.hasNext()) {
T t = iterator.next();
if (predicate.apply(t)) {
return t;
}
}
return defaultValue;
}
public static Optional tryFind (Iterator iterator, Predicate predicate) {
checkNotNull(iterator);
checkNotNull(predicate);
while (iterator.hasNext()) {
T t = iterator.next();
if (predicate.apply(t)) {
return Optional.of(t);
}
}
return Optional.absent();
}
public static int indexOf (Iterator iterator, Predicate predicate) {
checkNotNull(predicate, "predicate" );
for (int i = 0 ; iterator.hasNext(); i++) {
T current = iterator.next();
if (predicate.apply(current)) {
return i;
}
}
return -1 ;
}
public static Iterator transform (
final Iterator fromIterator, final Function function) {
checkNotNull(function);
return new TransformedIterator(fromIterator) {
@Override
T transform (F from) {
return function.apply(from);
}
};
}
public static T get (Iterator iterator, int position) {
checkNonnegative(position);
int skipped = advance(iterator, position);
if (!iterator.hasNext()) {
throw new IndexOutOfBoundsException(
"position ("
+ position
+ ") must be less than the number of elements that remained ("
+ skipped
+ ")" );
}
return iterator.next();
}
public static @Nullable T get (
Iterator iterator, int position, @Nullable T defaultValue) {
checkNonnegative(position);
advance(iterator, position);
return getNext(iterator, defaultValue);
}
static void checkNonnegative (int position) {
if (position < 0 ) {
throw new IndexOutOfBoundsException("position (" + position + ") must not be negative" );
}
}
public static @Nullable T getNext (Iterator iterator, @Nullable T defaultValue) {
return iterator.hasNext() ? iterator.next() : defaultValue;
}
public static T getLast (Iterator iterator) {
while (true ) {
T current = iterator.next();
if (!iterator.hasNext()) {
return current;
}
}
}
public static @Nullable T getLast (Iterator iterator, @Nullable T defaultValue) {
return iterator.hasNext() ? getLast(iterator) : defaultValue;
}
@CanIgnoreReturnValue
public static int advance (Iterator iterator, int numberToAdvance) {
checkNotNull(iterator);
checkArgument(numberToAdvance >= 0 , "numberToAdvance must be nonnegative" );
int i;
for (i = 0 ; i < numberToAdvance && iterator.hasNext(); i++) {
iterator.next();
}
return i;
}
public static Iterator limit (final Iterator iterator, final int limitSize) {
checkNotNull(iterator);
checkArgument(limitSize >= 0 , "limit is negative" );
return new Iterator() {
private int count;
@Override
public boolean hasNext () {
return count < limitSize && iterator.hasNext();
}
@Override
public T next () {
if (!hasNext()) {
throw new NoSuchElementException();
}
count++;
return iterator.next();
}
@Override
public void remove () {
iterator.remove();
}
};
}
public static Iterator consumingIterator (final Iterator iterator) {
checkNotNull(iterator);
return new UnmodifiableIterator() {
@Override
public boolean hasNext () {
return iterator.hasNext();
}
@Override
public T next () {
T next = iterator.next();
iterator.remove();
return next;
}
@Override
public String toString () {
return "Iterators.consumingIterator(...)" ;
}
};
}
static @Nullable T pollNext (Iterator iterator) {
if (iterator.hasNext()) {
T result = iterator.next();
iterator.remove();
return result;
} else {
return null ;
}
}
static void clear (Iterator iterator) {
checkNotNull(iterator);
while (iterator.hasNext()) {
iterator.next();
iterator.remove();
}
}
@SafeVarargs
public static UnmodifiableIterator forArray (final T... array) {
return forArray(array, 0 , array.length, 0 );
}
static UnmodifiableListIterator forArray (
final T[] array, final int offset, int length, int index) {
checkArgument(length >= 0 );
int end = offset + length;
Preconditions.checkPositionIndexes(offset, end, array.length);
Preconditions.checkPositionIndex(index, length);
if (length == 0 ) {
return emptyListIterator();
}
return new ArrayItr(array, offset, length, index);
}
private static final class ArrayItr extends AbstractIndexedListIterator {
static final UnmodifiableListIterator EMPTY = new ArrayItr<>(new Object[0 ], 0 , 0 , 0 );
private final T[] array;
private final int offset;
ArrayItr(T[] array, int offset, int length, int index) {
super (length, index);
this .array = array;
this .offset = offset;
}
@Override
protected T get (int index) {
return array[offset + index];
}
}
public static UnmodifiableIterator singletonIterator (final @Nullable T value) {
return new UnmodifiableIterator() {
boolean done;
@Override
public boolean hasNext () {
return !done;
}
@Override
public T next () {
if (done) {
throw new NoSuchElementException();
}
done = true ;
return value;
}
};
}
public static UnmodifiableIterator forEnumeration (final Enumeration enumeration) {
checkNotNull(enumeration);
return new UnmodifiableIterator() {
@Override
public boolean hasNext () {
return enumeration.hasMoreElements();
}
@Override
public T next () {
return enumeration.nextElement();
}
};
}
public static Enumeration asEnumeration (final Iterator iterator) {
checkNotNull(iterator);
return new Enumeration() {
@Override
public boolean hasMoreElements () {
return iterator.hasNext();
}
@Override
public T nextElement () {
return iterator.next();
}
};
}
private static class PeekingImpl implements PeekingIterator {
private final Iterator iterator;
private boolean hasPeeked;
private @Nullable E peekedElement;
public PeekingImpl (Iterator iterator) {
this .iterator = checkNotNull(iterator);
}
@Override
public boolean hasNext () {
return hasPeeked || iterator.hasNext();
}
@Override
public E next () {
if (!hasPeeked) {
return iterator.next();
}
E result = peekedElement;
hasPeeked = false ;
peekedElement = null ;
return result;
}
@Override
public void remove () {
checkState(!hasPeeked, "Can't remove after you've peeked at next" );
iterator.remove();
}
@Override
public E peek () {
if (!hasPeeked) {
peekedElement = iterator.next();
hasPeeked = true ;
}
return peekedElement;
}
}
public static PeekingIterator peekingIterator (Iterator iterator) {
if (iterator instanceof PeekingImpl) {
@SuppressWarnings ("unchecked" )
PeekingImpl peeking = (PeekingImpl) iterator;
return peeking;
}
return new PeekingImpl(iterator);
}
@Deprecated
public static PeekingIterator peekingIterator (PeekingIterator iterator) {
return checkNotNull(iterator);
}
@Beta
public static UnmodifiableIterator mergeSorted (
Iterable> iterators, Comparator comparator) {
checkNotNull(iterators, "iterators" );
checkNotNull(comparator, "comparator" );
return new MergingIterator(iterators, comparator);
}
private static class MergingIterator extends UnmodifiableIterator {
final Queue> queue;
public MergingIterator (
Iterable> iterators,
final Comparator itemComparator) {
Comparator> heapComparator =
new Comparator>() {
@Override
public int compare (PeekingIterator o1, PeekingIterator o2) {
return itemComparator.compare(o1.peek(), o2.peek());
}
};
queue = new PriorityQueue<>(2 , heapComparator);
for (Iterator iterator : iterators) {
if (iterator.hasNext()) {
queue.add(Iterators.peekingIterator(iterator));
}
}
}
@Override
public boolean hasNext () {
return !queue.isEmpty();
}
@Override
public T next () {
PeekingIterator nextIter = queue.remove();
T next = nextIter.next();
if (nextIter.hasNext()) {
queue.add(nextIter);
}
return next;
}
}
private static class ConcatenatedIterator implements Iterator {
private @Nullable Iterator toRemove;
private Iterator iterator;
private Iterator> topMetaIterator;
private @Nullable Deque>> metaIterators;
ConcatenatedIterator(Iterator> metaIterator) {
iterator = emptyIterator();
topMetaIterator = checkNotNull(metaIterator);
}
private @Nullable Iterator> getTopMetaIterator() {
while (topMetaIterator == null || !topMetaIterator.hasNext()) {
if (metaIterators != null && !metaIterators.isEmpty()) {
topMetaIterator = metaIterators.removeFirst();
} else {
return null ;
}
}
return topMetaIterator;
}
@Override
public boolean hasNext () {
while (!checkNotNull(iterator).hasNext()) {
topMetaIterator = getTopMetaIterator();
if (topMetaIterator == null ) {
return false ;
}
iterator = topMetaIterator.next();
if (iterator instanceof ConcatenatedIterator) {
@SuppressWarnings ("unchecked" )
ConcatenatedIterator topConcat = (ConcatenatedIterator) iterator;
iterator = topConcat.iterator;
if (this .metaIterators == null ) {
this .metaIterators = new ArrayDeque<>();
}
this .metaIterators.addFirst(this .topMetaIterator);
if (topConcat.metaIterators != null ) {
while (!topConcat.metaIterators.isEmpty()) {
this .metaIterators.addFirst(topConcat.metaIterators.removeLast());
}
}
this .topMetaIterator = topConcat.topMetaIterator;
}
}
return true ;
}
@Override
public T next () {
if (hasNext()) {
toRemove = iterator;
return iterator.next();
} else {
throw new NoSuchElementException();
}
}
@Override
public void remove () {
CollectPreconditions.checkRemove(toRemove != null );
toRemove.remove();
toRemove = null ;
}
}
static ListIterator cast (Iterator iterator) {
return (ListIterator) iterator;
}
}