ru.yandex.bolts.collection.impl.AbstractIteratorF Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bolts Show documentation
Show all versions of bolts Show documentation
Collections utilities used in various Yandex projects
The newest version!
package ru.yandex.bolts.collection.impl;
import java.util.Iterator;
import java.util.NoSuchElementException;
import ru.yandex.bolts.collection.Cf;
import ru.yandex.bolts.collection.IteratorF;
import ru.yandex.bolts.collection.ListF;
import ru.yandex.bolts.collection.Option;
import ru.yandex.bolts.collection.SetF;
import ru.yandex.bolts.collection.Tuple2;
import ru.yandex.bolts.function.Function;
import ru.yandex.bolts.function.Function1B;
import ru.yandex.bolts.function.forhuman.Comparator;
public abstract class AbstractIteratorF extends AbstractTraversableF implements IteratorF {
@Override
protected IteratorF iterator() {
return this;
}
private IteratorF self() { return this; }
@Override
public ListF toList() {
return toListImpl(-1);
}
@Override
public ListF toList(int initialCapacity) {
return toListImpl(initialCapacity);
}
private ListF toListImpl(int initialCapacity) {
if (!hasNext()) return Cf.list();
ArrayListF result;
if (initialCapacity < 0) {
result = new ArrayListF<>();
} else {
result = new ArrayListF<>(initialCapacity);
}
forEach(result.addF());
return result.convertToReadOnly();
}
public SetF toSet() {
if (!hasNext()) return Cf.set();
SetF result = Cf.hashSet();
forEach(result.addF());
return result.unmodifiable();
}
@Override
public IteratorF map(final Function super E, B> f) {
class MappedIterator extends AbstractIteratorF {
public boolean hasNext() {
return self().hasNext();
}
public B next() {
return f.apply(self().next());
}
public void remove() {
self().remove();
}
}
return new MappedIterator();
}
@Override
public IteratorF flatMap(final Function super E, ? extends Iterator> f) {
class FlatMappedIterator extends AbstractIteratorF {
private IteratorF cur = Cf.emptyIterator();
@Override
public boolean hasNext() {
while (!cur.hasNext() && self().hasNext()) {
cur = Cf.x(f.apply(self().next()));
}
return cur.hasNext();
}
@Override
public B next() {
if (hasNext()) return cur.next();
throw new NoSuchElementException("next on empty iterator");
}
}
return new FlatMappedIterator();
}
@SuppressWarnings("unchecked")
@Override
public IteratorF flatMapL(Function super E, ? extends Iterable> f0) {
Function> f = (Function>) f0;
Function> g = f.andThen((Function, Iterator>) Iterable::iterator);
return flatMap(g);
}
@Override
public IteratorF flatMapO(Function super E, Option> f) {
return flatMapL(f);
}
private static abstract class AbstractPrefetchingIterator extends AbstractIteratorF {
private Option next = Option.none();
private boolean eof = false;
private void fill() {
while (!eof && next.isEmpty()) {
next = fetchNext();
eof = next.isEmpty();
}
}
@Override
public boolean hasNext() {
fill();
return !eof && next.isDefined();
}
@Override
public E next() {
if (!hasNext())
throw new NoSuchElementException("next on empty iterator");
E r = next.get();
next = Option.none();
return r;
}
protected abstract Option fetchNext();
}
@Override
public IteratorF filter(final Function1B super E> f) {
class FilterIterator extends AbstractPrefetchingIterator {
@Override
protected Option fetchNext() {
while (self().hasNext()) {
E e = self().next();
if (f.apply(e))
return Option.some(e);
}
return Option.none();
}
};
return new FilterIterator();
}
@Override
public IteratorF filterNot(Function1B super E> f) {
return filter(f.notF());
}
@Override
public IteratorF filterNotNull() {
return filter(Function1B.notNullF());
}
public IteratorF> zipWithIndex() {
class ZippedIterator extends AbstractIteratorF> {
private int i = 0;
public boolean hasNext() {
return self().hasNext();
}
public Tuple2 next() {
return Tuple2.tuple(self().next(), i++);
}
public void remove() {
self().remove();
}
}
return new ZippedIterator();
}
public IteratorF plus(final Iterator b) {
return new AbstractIteratorF() {
final IteratorF a = self();
public boolean hasNext() {
return a.hasNext() || b.hasNext();
}
public E next() {
if (a.hasNext()) return a.next();
else return b.next();
}
};
}
public IteratorF unmodifiable() {
return UnmodifiableDefaultIteratorF.wrap(this);
}
public Option nextO() {
if (hasNext()) return Option.some(next());
else return Option.none();
}
@Override
public int count() {
return count(Function1B.trueF());
}
public IteratorF drop(int count) {
int left = count;
while (left > 0 && hasNext()) {
next();
--left;
}
return this;
}
public IteratorF take(final int count) {
if (count <= 0) return Cf.emptyIterator();
class TakeIterator extends AbstractIteratorF {
int left = count;
public boolean hasNext() {
return left > 0 && self().hasNext();
}
public E next() {
if (left == 0) throw new NoSuchElementException();
E next = self().next();
--left;
return next;
}
};
return new TakeIterator();
}
@Override
public ListF takeSorted(int count) {
return takeSorted(Comparator.naturalComparator().uncheckedCastC(), count);
}
@Override
public ListF takeSortedDesc(int count) {
return takeSorted(Comparator.naturalComparator().invert().uncheckedCastC(), count);
}
@Override
public ListF takeSorted(java.util.Comparator super E> comparator, int count) {
if (count == 0) {
return Cf.list();
}
if (count < 0) {
throw new IllegalArgumentException("K must be greater than 0");
}
FixedSizeTop top = FixedSizeTop.cons(count, (java.util.Comparator) comparator);
while (hasNext()) {
top.add(next());
}
return top.getTopElements();
}
@Override
public ListF takeSortedBy(Function super E, ?> f, int count) {
return takeSorted(f.andThenNaturalComparator().nullLowC(), count);
}
@Override
public ListF takeSortedByDesc(Function super E, ?> f, int count) {
return takeSorted(f.andThenNaturalComparator().nullLowC().invert(), count);
}
public IteratorF dropWhile(Function1B super E> p) {
// XXX: should be lazy
while (hasNext()) {
E e = next();
if (!p.apply(e))
return Cf.list(e).iterator().plus(this);
}
return Cf.emptyIterator();
}
public IteratorF takeWhile(final Function1B super E> f) {
class TakeWhileIterator extends AbstractPrefetchingIterator {
boolean end = false;
@Override
protected Option fetchNext() {
if (!end && self().hasNext()) {
E e = self().next();
if (f.apply(e))
return Option.some(e);
else {
end = true;
return Option.none();
}
}
return Option.none();
}
}
return new TakeWhileIterator();
}
@Override
public IteratorF> paginate(int pageSize) {
if (pageSize <= 0) throw new IllegalArgumentException();
return new AbstractIteratorF>() {
@Override
public boolean hasNext() {
return AbstractIteratorF.this.hasNext();
}
@Override
public ListF next() {
if (!hasNext()) throw new NoSuchElementException();
ArrayListF items = new ArrayListF<>(pageSize);
for (int i = 0; i < pageSize && AbstractIteratorF.this.hasNext(); ++i) {
items.add(AbstractIteratorF.this.next());
}
return items.convertToReadOnly();
}
};
}
} //~