blob: 97661fa92eafd7ab72181b98a21ff4d2eb3bdf96 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.jena.atlas.iterator ;
import java.io.PrintStream ;
import java.util.* ;
import java.util.function.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream ;
import java.util.stream.StreamSupport ;
import org.apache.jena.atlas.lib.Closeable ;
import org.apache.jena.atlas.lib.Sink ;
/**
* Iter provides general utilities for working with {@link Iterator}s.
* This class provides functionality similar to {@code Stream}
* except for iterators (and hence single threaded).
* <p>
* Style 1: functional style using statics.
*
* <pre>
* import static org.apache.jena.atlas.iterator.Iter.* ;
*
* filter(map(iterator, function), predicate)
* </pre>
*
* Style 2: Stream-like: The class {@code Iter} provides methods to call on an iterator.
*
* <pre>
* import static org.apache.jena.atlas.iterator.Iter.iter ;
*
* iter(iterator).map(...).filter(...)
* </pre>
*
* @param <T> the type of element over which an instance of {@code Iter} iterates,
*/
public class Iter<T> implements Iterator<T> {
/** Shorter form of "forEachRemaining" */
public static <T> void forEach(Iterator<T> iter, Consumer<T> action) {
iter.forEachRemaining(action);
}
// IteratorSlotted needed? IteratorPeek
// IteratorSlotted.inspect
public static <T> Stream<T> asStream(Iterator<T> iterator) {
return asStream(iterator, false);
}
public static <T> Stream<T> asStream(Iterator<T> iterator, boolean parallel) {
// Why isn't there a JDK operation for Iterator -> (sequential) stream?
int characteristics = 0 ; //Spliterator.IMMUTABLE;
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, characteristics), parallel);
}
// ---- Special iterators.
public static <T> Iterator<T> singleton(T item) {
// There is a singleton iterator in Collections but it is not public.
return new SingletonIterator<>(item) ;
}
public static <T> Iterator<T> nullIterator() {
// Java7 caught up.
return Collections.emptyIterator();
}
// ---- Collectors.
/** Collect an iterator into a set. */
public static <T> Set<T> toSet(Iterator<? extends T> stream) {
return collect(stream, Collectors.toSet());
}
/** Collect an iterator into a list. */
public static <T> List<T> toList(Iterator<? extends T> stream) {
return collect(stream, Collectors.toList());
}
/**
* Create another iterator without risk of concurrent modification
* exceptions. This materializes the input iterator.
*/
public static <T> Iterator<T> iterator(Iterator<? extends T> iterator) {
List<T> x = Iter.toList(iterator) ;
return x.iterator() ;
}
// Note fold-left and fold-right
// http://en.wikipedia.org/wiki/Fold_%28higher-order_function%29
// This reduce is a kind of fold-left (take first element, apply to rest of list)
// and can deal with lists of zero elements.
// -- Operations on iterators.
@FunctionalInterface
public interface Folder<X, Y> extends BiFunction<Y,X,Y> {}
public static <T, R> R foldLeft(Iterator<? extends T> stream, R value, Folder<T, R> function) {
// Tail recursion, unwound
for (; stream.hasNext();) {
T item = stream.next() ;
value = function.apply(value, item) ;
}
return value ;
}
public static <T, R> R foldRight(Iterator<? extends T> stream, R value, Folder<T, R> function) {
// Recursive.
if ( !stream.hasNext() )
return value ;
T item = stream.next() ;
return function.apply(foldRight(stream, value, function), item) ;
}
public static <T> Optional<T> reduce(Iterator<T> iter, BinaryOperator<T> accumulator) {
T r = reduce(iter, null, accumulator);
return Optional.ofNullable(r);
}
public static <T> T reduce(Iterator<T> iter, T identity, BinaryOperator<T> accumulator) {
T result = identity;
while(iter.hasNext()) {
T elt = iter.next();
result = (result == null) ? elt : accumulator.apply(result, elt);
}
return result;
}
// ---- min and max
public static <T> Optional<T> min(Iterator<T> iter, Comparator<T> comparator) {
T x = null;
while(iter.hasNext()) {
T elt = iter.next();
if ( x == null )
x = elt;
else {
int cmp = comparator.compare(x, elt);
if ( cmp > 0 )
x = elt;
}
}
return Optional.ofNullable(x);
}
public static <T> Optional<T> max(Iterator<T> iter, Comparator<T> comparator) {
// Or min(iter, comparator.reversed())
T x = null;
while(iter.hasNext()) {
T elt = iter.next();
if ( x == null )
x = elt;
else {
int cmp = comparator.compare(x, elt);
if ( cmp < 0 )
x = elt;
}
}
return Optional.ofNullable(x);
}
// ---- collect
/** See {@link Stream#collect(Supplier, BiConsumer, BiConsumer)}, except without the {@code BiConsumer<R, R> combiner} */
public static <T,R> R collect(Iterator<T> iter, Supplier<R> supplier, BiConsumer<R, ? super T> accumulator) {
R result = supplier.get();
while(iter.hasNext()) {
T elt = iter.next();
accumulator.accept(result, elt);
}
return result;
}
/** See {@link Stream#collect(Collector)} */
public static <T, R, A> R collect(Iterator<T> iter, Collector<? super T, A, R> collector) {
A a = collect(iter, collector.supplier(), collector.accumulator());
return collector.finisher().apply(a);
}
/** Act on elements of an iterator.
* @see #map(Iterator, Function)
*/
public static <T> void apply(Iterator<? extends T> stream, Consumer<T> action) {
for (; stream.hasNext();) {
T item = stream.next() ;
action.accept(item) ;
}
}
// ---- Filter
public static <T> Iterator<T> filter(final Iterator<? extends T> stream, final Predicate<T> filter) {
final Iterator<T> iter = new Iterator<T>() {
boolean finished = false ;
boolean slotOccupied = false ;
T slot ;
@Override
public boolean hasNext() {
if ( finished )
return false ;
while (!slotOccupied) {
if ( !stream.hasNext() ) {
finished = true ;
break ;
}
T nextItem = stream.next() ;
if ( filter.test(nextItem) ) {
slot = nextItem ;
slotOccupied = true ;
break ;
}
}
return slotOccupied ;
}
@Override
public T next() {
if ( hasNext() ) {
slotOccupied = false ;
return slot ;
}
throw new NoSuchElementException("filter.next") ;
}
@Override
public void remove() {
throw new UnsupportedOperationException("filter.remove") ;
}
} ;
return iter ;
}
public static <T> Iterator<T> notFilter(final Iterator<? extends T> stream, final Predicate<T> filter) {
return filter(stream, filter.negate()) ;
}
// Filter-related
/**
* Return true if every element of stream passes the filter (reads the
* stream until the first element not passing the filter)
* @deprecated Use {@link #allMatch}
*/
@Deprecated
public static <T> boolean every(Iterator<? extends T> iter, Predicate<T> predicate) {
return Iter.allMatch(iter, predicate);
}
/**
* Return true if every element of stream passes the filter (reads the
* stream until the first element not passing the filter)
*/
public static <T> boolean allMatch(Iterator<T> iter, Predicate<? super T> predicate) {
while ( iter.hasNext() ) {
T item = iter.next() ;
if ( !predicate.test(item) )
return false ;
}
return true ;
}
/**
* Return true if one or more elements of stream passes the filter (reads
* the stream to first element passing the filter)
* @deprecated Use {@link #anyMatch}
*/
@Deprecated
public static <T> boolean some(Iterator<T> iter, Predicate<? super T> predicate) {
return Iter.anyMatch(iter, predicate);
}
/**
* Return true if one or more elements of stream passes the filter (reads
* the stream to first element passing the filter)
*/
public static <T> boolean anyMatch(Iterator<T> iter, Predicate<? super T> predicate) {
while ( iter.hasNext() ) {
T item = iter.next() ;
if ( predicate.test(item) )
return true ;
}
return false ;
}
/**
* Return true if none of the elements of the iterator passes the predicate test reads
* the stream to first element passing the filter)
*/
public static <T> boolean noneMatch(Iterator<T> iter, Predicate<? super T> predicate) {
return ! anyMatch(iter, predicate);
}
/**
* Return an Optional with the first element of an iterator that matches the predicate.
* Return {@code Optional.empty} if none match.
* Reads the iterator until the first match.
*/
public static <T> Optional<T> findFirst(Iterator<T> iter, Predicate<? super T> predicate) {
while ( iter.hasNext() ) {
T item = iter.next() ;
if ( predicate.test(item) )
return Optional.of(item);
}
return Optional.empty() ;
}
/**
* Return an Optional with an element of an iterator that matches the predicate.
* Return {@code Optional.empty} if none match.
* The element returned is not specified by the API contract.
*/
public static <T> Optional<T> findAny(Iterator<T> iter, Predicate<? super T> predicate) {
return findFirst(iter, predicate);
}
// ---- Map
/** Apply a function to every element of an iterator, transforming it
* from a {@code T} to an {@code R}.
*/
public static <T, R> Iterator<R> map(Iterator<? extends T> stream, Function<T, R> converter) {
final Iterator<R> iter = new Iterator<R>() {
@Override
public boolean hasNext() {
return stream.hasNext() ;
}
@Override
public R next() {
return converter.apply(stream.next()) ;
}
@Override
public void remove() {
throw new UnsupportedOperationException("map.remove") ;
}
} ;
return iter ;
}
/** Transform a list of elements to a new list of the function applied to each element.
* Using a stream is often better. This operation preserves the order of the list.
* @deprecated Use Java8 Streams
*/
@Deprecated
public static <T, R> List<R> map(List<? extends T> list, Function<T, R> converter) {
return toList(map(list.iterator(), converter)) ;
}
/**
* Apply a function to every element of an iterator, to produce possibly multiple mapping each time.
* See {@link Stream#flatMap}
*/
public static <T, R> Iterator<R> flatMap(Iterator<T> iter, Function<T, Iterator<R>> mapper) {
// Combined mapping and flattening
return new IteratorFlatMap<>(iter, mapper);
// For reference: an alternative splitting the mapping out:
// Iterator<Iterator<R>> pipeline = Iter.map(iter, mapper);
// Iterator<R> outcome = new IteratorFlatten<>(pipeline);
// IteratorFlatten is only one line and one field less complicated than IteratorFlatMap
}
/**
* Apply an action to everything in stream, yielding a stream of the
* same items.
*/
public static <T> Iterator<T> operate(final Iterator<? extends T> stream, final Consumer<T> action) {
final Iterator<T> iter = new Iterator<T>() {
@Override
public boolean hasNext() {
return stream.hasNext() ;
}
@Override
public T next() {
T t = stream.next() ;
action.accept(t) ;
return t ;
}
@Override
public void remove() {
throw new UnsupportedOperationException("operate.remove") ;
}
} ;
return iter ;
}
/** Print an iterator as it gets used - this adds a printing wrapper */
public static <T> Iterator<T> printWrapper(final Iterator<? extends T> stream) {
return Iter.printWrapper(System.out, stream) ;
}
/** Print an iterator as it gets used - this adds a printing wrapper */
public static <T> Iterator<T> printWrapper(final PrintStream out, final Iterator<? extends T> stream) {
return Iter.operate(stream, out::println) ;
}
/** Join two iterators.
* If there, potentially, going to be many iterators, it is better to
* create an {@link IteratorConcat} explicitly and add each iterator.
*/
public static <T> Iterator<T> append(Iterator<? extends T> iter1, Iterator<? extends T> iter2) {
return IteratorCons.create(iter1, iter2) ;
}
/** Return an iterator that will see each element of the underlying iterator only once.
* Note that this need working memory to remember the elements already seen.
*/
public static <T> Iterator<T> distinct(Iterator<T> iter) {
return filter(iter, new FilterUnique<T>()) ;
}
/** Remove adjacent duplicates. This operation does not need
* working memory to remember the all elements already seen,
* just a slot for the last element seen.
*/
public static <T> Iterator<T> distinctAdjacent(Iterator<T> iter) {
return filter(iter, new FilterDistinctAdjacent<T>()) ;
}
/** Remove nulls from an iterator */
public static <T> Iterator<T> removeNulls(Iterator<T> iter) {
return filter(iter, Objects::nonNull) ;
}
/** Step forward up to {@code steps} places.
* <br/>Return number of steps taken.
*
* @apiNote
* The iterator is moved at most {@code steps} places with no overshoot.
* The iterator can be used afterwards.
*/
public static int step(Iterator<?> iter, int steps) {
for ( int i = 0 ; i < steps; i++) {
if ( ! iter.hasNext() )
return i;
iter.next();
}
return steps;
}
/** Take the first N elements of an iterator - stop early if too few
* @see #limit(Iterator, long)
*/
public static <T> List<T> take(Iterator<T> iter, int N) {
iter = new IteratorN<>(iter, N) ;
List<T> x = new ArrayList<>(N) ;
while ( iter.hasNext() )
x.add(iter.next()) ;
return x ;
}
/** Create an iterator such that it yields elements while a predicate test on
* the elements is true, end the iteration.
* @see Iter#filter(Iterator, Predicate)
*/
public static <T> Iterator<T> takeWhile(Iterator<T> iter, Predicate<T> predicate) {
return new IteratorTruncate<>(iter, predicate) ;
}
/**
* Create an iterator such that it yields elements until a predicate test on
* the elements becomes true, end the iteration.
*
* @see Iter#filter(Iterator, Predicate)
*/
public static <T> Iterator<T> takeUntil(Iterator<T> iter, Predicate<T> predicate) {
return new IteratorTruncate<>(iter, predicate.negate()) ;
}
/** Create an iterator such that elements from the front while
* a predicate test become true are dropped then return all remaining elements
* are iterated over.
* The first element where the predicted becomes true is the first element of the
* returned iterator.
*/
public static <T> Iterator<T> dropWhile(Iterator<T> iter, Predicate<T> predicate) {
PeekIterator<T> iter2 = new PeekIterator<>(iter) ;
for(;;) {
T elt = iter2.peek() ;
if ( elt == null )
return Iter.nullIterator() ;
if ( ! predicate.test(elt) )
break ;
}
return iter2 ;
}
/** Create an iterator such that elements from the front until
* a predicate test become true are dropped then return all remaining elements
* are iterated over.
* The first element where the predicate becomes true is the first element of the
* returned iterator.
*/
public static <T> Iterator<T> dropUntil(Iterator<T> iter, Predicate<T> predicate) {
return dropWhile(iter, predicate.negate()) ;
}
/** Return an iterator that is limited to the given number of elements.
* If it is shorter than the limit, stop at the end.
* @see #take(Iterator, int)
*/
public static <X> Iterator<X> limit(Iterator<X> iterator, long limit) {
final Iterator<X> iter = new Iterator<X>() {
private long count = 0;
@Override
public boolean hasNext() {
if ( count < limit )
return iterator.hasNext();
return false;
}
@Override
public X next() {
if ( ! hasNext() )
throw new NoSuchElementException();
X t = next();
count++;
return t;
}
};
return iter;
}
/** Skip over a number of elements of an iterator */
public static <X> Iterator<X> skip(Iterator<X> iterator, long limit) {
for ( long i = 0; i < limit; i++ ) {
if ( iterator.hasNext() )
iterator.next();
else
// Now exhausted.
break;
}
return iterator;
}
/** Iterator that only returns upto N items */
static class IteratorN<T> implements Iterator<T> {
private final Iterator<T> iter ;
private final int N ;
private int count ;
IteratorN(Iterator<T> iter, int N) {
this.iter = iter ;
this.N = N ;
this.count = 0 ;
}
@Override
public boolean hasNext() {
if ( count >= N )
return false ;
return iter.hasNext() ;
}
@Override
public T next() {
if ( count >= N )
throw new NoSuchElementException() ;
T x = iter.next() ;
count++ ;
return x ;
}
@Override
public void remove() {
// But leave the count as-is.
iter.remove() ;
}
}
/** Count the iterator (this is destructive on the iterator) */
public static <T> long count(Iterator<T> iterator) {
long x = 0 ;
while (iterator.hasNext()) {
iterator.next() ;
x++ ;
}
return x ;
}
/** Consume the iterator */
public static <T> void consume(Iterator<T> iterator) {
count(iterator) ;
}
/** Create a string from an iterator, using the separator. Note: this consumes the iterator. */
public static <T> String asString(Iterator<T> stream, String sep) {
return Iter.iter(stream).map(x->x.toString()).collect(Collectors.joining(sep));
}
/** Create a string from an iterator, using the separator, prefix and suffix. Note: this consumes the iterator. */
public static <T> String asString(Iterator<T> stream, CharSequence sep, CharSequence prefix, CharSequence suffix) {
return Iter.iter(stream).map(x->x.toString()).collect(Collectors.joining(sep, prefix, suffix));
}
public static <T> void close(Iterator<T> iter) {
if ( iter instanceof Closeable )
((Closeable)iter).close() ;
}
/**
* Print an iterator to stdout, return a copy of the iterator. Printing
* occurs now. See {@link #debug} for an operation to print as the
* iterator is used.
*/
public static <T> Iterator<T> log(Iterator<T> stream) {
return log(System.out, stream) ;
}
/**
* Print an iterator to stdout, return a copy of the iterator. Printing
* occurs now. See {@link #debug} for an operation to print as the
* iterator is used.
*/
public static <T> Iterator<T> log(final PrintStream out, Iterator<T> stream) {
Iterator<T> iter = debug(out, stream) ;
// And force it to run.
return Iter.toList(iter).iterator();
}
/**
* Print an iterator to stdout, return a copy of the iterator. Printing
* occurs when the iterator is used. See {@link #log} for
* an operation to print now.
*/
public static <T> Iterator<T> debug(Iterator<T> stream) {
return debug(System.out, stream) ;
}
/**
* Print an iterator, return a copy of the iterator. Printing
* occurs as the returned iterator is used.
*/
public static <T> Iterator<T> debug(final PrintStream out, Iterator<T> stream) {
try {
return map(stream, item -> {out.println(item); return item;}) ;
} finally { out.flush() ; }
}
/** Print an iterator (destructive) */
public static <T> void print(Iterator<T> stream) {
print(System.out, stream) ;
}
/** Print an iterator (destructive) */
public static <T> void print(final PrintStream out, Iterator<T> stream) {
apply(stream, out::println) ;
}
/** Send the elements of the iterator to a sink - consumes the iterator */
public static <T> void sendToSink(Iterator<T> iter, Sink<T> sink) {
while ( iter.hasNext() ) {
T thing = iter.next() ;
sink.send(thing) ;
}
sink.close() ;
}
/** Send the elements of the iterable to a sink */
@Deprecated
public static <T> void sendToSink(Iterable<T> stream, Sink<T> sink) {
sendToSink(stream.iterator(), sink) ;
}
// ----
// Iter class part : factories
public static <T> Iter<T> iter(Iter<T> iter) {
return iter ;
}
public static <T> Iter<T> iter(Collection<T> collection) {
return iter(collection.iterator()) ;
}
public static <T> Iter<T> iter(Iterator<T> iterator) {
if ( iterator instanceof Iter<? > )
return (Iter<T>)iterator ;
return new Iter<>(iterator) ;
}
public static <T> Iter<T> singletonIter(T item) {
return iter(new SingletonIterator<>(item)) ;
}
public static <T> Iter<T> nullIter() {
return iter(new NullIterator<T>()) ;
}
/**
* Materialize an iterator, that is, force it to run now - useful in
* debugging or when iteration may modify underlying datastructures.
*/
public static <T> Iterator<T> materialize(Iterator<T> iter) {
return toList(iter).iterator() ;
}
/** An {@code Iter} of 2 {@code Iter}'s */
public static <T> Iter<T> concat(Iter<T> iter1, Iter<T> iter2) {
if ( iter1 == null )
return iter2 ;
if ( iter2 == null )
return iter1 ;
return iter1.append(iter2) ;
}
/** An {@code Iterator} of 2 {@code Iterator}'s.
* See also {@link IteratorConcat}.
*/
public static <T> Iter<T> concat(Iterator<T> iter1, Iterator<T> iter2) {
if ( iter1 == null )
return iter(iter2) ;
if ( iter2 == null )
return iter(iter1) ;
return iter(iter1).append(iter(iter2)) ;
}
/** Return the first element of an iterator or null if no such element.
* @param iter
* @return An item or null.
*/
public static <T> T first(Iterator<T> iter) {
return first(iter, (x)-> true ) ;
}
/** Skip to the first element meeting a condition and return that element. */
public static <T> T first(Iterator<T> iter, Predicate<T> filter) {
while (iter.hasNext()) {
T t = iter.next() ;
if ( filter.test(t) )
return t ;
}
return null ;
}
/** @deprecated Use Java8 Streams */
@Deprecated
public static <T> T first(Collection<T> collection, Predicate<T> filter) {
return collection.stream().filter(filter).findFirst().orElse(null);
}
/** Skip to the first element meeting a condition and return that element's index (zero-based). */
public static <T> int firstIndex(Iterator<T> iter, Predicate<T> filter) {
for (int idx = 0; iter.hasNext(); idx++) {
T t = iter.next() ;
if ( filter.test(t) )
return idx ;
}
return -1 ;
}
/** @deprecated Use Java8 Streams */
@Deprecated
public static <T> int firstIndex(Collection<T> collection, Predicate<T> filter) {
return firstIndex(collection.iterator(), filter) ;
}
/** Return the last element or null, if no elements. This operation consumes the iterator. */
public static <T> T last(Iterator<T> iter) {
return last(iter, (x)->true) ;
}
/** Return the last element satisfying a predicate. This operation consumes the whole iterator. */
public static <T> T last(Iterator<T> iter, Predicate<T> filter) {
T thing = null ;
while (iter.hasNext()) {
T t = iter.next() ;
if ( filter.test(t) )
thing = t ;
}
return thing ;
}
/** @deprecated Use Java8 Streams */
@Deprecated
public static <T> T last(Collection<T> collection, Predicate<T> filter) {
return last(collection.iterator(), filter) ;
}
/** Return the index of the last element satisfying a predicate (zero-based). */
public static <T> int lastIndex(Iterator<T> iter, Predicate<T> filter) {
int location = -1 ;
for (int idx = 0; iter.hasNext(); idx++) {
T t = iter.next() ;
if ( filter.test(t) )
location = idx ;
}
return location ;
}
/** @deprecated Use Java8 Streams */
@Deprecated
public static <T> int lastIndex(Collection<T> collection, Predicate<T> filter) {
return lastIndex(collection.iterator(), filter) ;
}
// ------------------------------------------------------
// The class.
private Iterator<T> iterator ;
private Iter(Iterator<T> iterator) {
this.iterator = iterator ;
}
/** Apply the Consumer to each element of the iterator */
public void forEach(Consumer<T> action) {
iterator.forEachRemaining(action);
}
/** Consume the {@code Iter} and produce a {@code Set} */
public Set<T> toSet() {
return toSet(iterator) ;
}
/** Consume the {@code Iter} and produce a {@code List} */
public List<T> toList() {
return toList(iterator) ;
}
public void sendToSink(Sink<T> sink) {
sendToSink(iterator, sink) ;
}
public T first() {
return first(iterator) ;
}
public T last() {
return last(iterator) ;
}
/** Skip to the first element meeting a condition and return that element. */
public T first(Predicate<T> filter) {
return first(iterator, filter) ;
}
/** Skip to the first element meeting a condition and return that element's index (zero-based). */
public int firstIndex(Predicate<T> filter) {
return firstIndex(iterator, filter) ;
}
/** Return the last element satisfying a predicate. This operation destroys the whole iterator. */
public T last(Predicate<T> filter) {
return last(iterator, filter) ;
}
/** Return the index of the last element satisfying a predicate (zero-based). */
public int lastIndex(Predicate<T> filter) {
return lastIndex(iterator, filter) ;
}
/** Filter by predicate */
public Iter<T> filter(Predicate<T> filter) {
return iter(filter(iterator, filter)) ;
}
/** Return true if every element satisfies a predicate */
public boolean every(Predicate<T> predicate) {
return every(iterator, predicate) ;
}
/** Return true if some element satisfies a predicate */
public boolean some(Predicate<T> filter) {
return some(iterator, filter) ;
}
public boolean allMatch(Predicate<? super T> predicate) {
return allMatch(iterator, predicate);
}
public boolean anyMatch(Predicate<? super T> predicate) {
return anyMatch(iterator, predicate);
}
public boolean noneMatch(Predicate<? super T> predicate) {
return noneMatch(iterator, predicate);
}
public Optional<T> findFirst(Predicate<? super T> predicate) {
return findFirst(iterator, predicate);
}
public Optional<T> findAny(Predicate<? super T> predicate) {
return findAny(iterator, predicate);
}
/** Remove nulls */
public Iter<T> removeNulls() {
return iter(removeNulls(this)) ;
}
/** Map each element using given function */
public <R> Iter<R> map(Function<T, R> converter) {
return iter(map(iterator, converter)) ;
}
/** FlatMap each element using given function of element to iterator of mapped elements.s */
public <R> Iter<R> flatMap(Function<T, Iterator<R>> converter) {
return iter(flatMap(iterator, converter)) ;
}
/**
* Apply an action to everything in the stream, yielding a stream of the
* original items.
*/
public Iter<T> operate(Consumer<T> action) {
return iter(operate(iterator, action)) ;
}
public <R> R foldLeft(R initial, Folder<T, R> accumulator) {
return foldLeft(iterator, initial, accumulator) ;
}
public <R> R foldRight(R initial, Folder<T, R> accumulator) {
return foldRight(iterator, initial, accumulator) ;
}
/** Reduce.
* This reduce is fold-left (take first element, apply to rest of list)
*/
public Optional<T> reduce(BinaryOperator<T> accumulator) {
return reduce(iterator, accumulator) ;
}
public T reduce(T identity, BinaryOperator<T> accumulator) {
return Iter.reduce(iterator, identity, accumulator);
}
public Optional<T> min(Comparator<T> comparator) {
return min(iterator, comparator);
}
public Optional<T> max(Comparator<T> comparator) {
return max(iterator, comparator);
}
/** See {@link Stream#collect(Supplier, BiConsumer, BiConsumer)}, except without the {@code BiConsumer<R, R> combiner} */
public <R> R collect(Supplier<R> supplier, BiConsumer<R, T> accumulator/*, BiConsumer<R, R> combiner*/) {
return Iter.collect(iterator, supplier, accumulator);
}
/** See {@link Stream#collect(Collector)} */
public <R, A> R collect(Collector<? super T, A, R> collector) {
return collect(iterator, collector);
}
/** Apply an action to every element of an iterator */
public void apply(Consumer<T> action) {
apply(iterator, action) ;
}
/** Join on an {@code Iterator}..
* If there are going to be many iterators, uit is better to create an {@link IteratorConcat}
* and <tt>.add</tt> each iterator. The overheads are much lower.
*/
public Iter<T> append(Iterator<T> iter) {
return iter(IteratorCons.create(iterator, iter)) ;
}
/** Return an Iter that yields at most the first N items */
public Iter<T> take(int N) {
return iter(take(iterator, N)) ;
}
/** Create an {@code Iter} such that it yields elements while a predicate test on
* the elements is true, end the iteration.
* @see Iter#filter(Predicate)
*/
public Iter<T> takeWhile(Predicate<T> predicate) {
return iter(takeWhile(iterator, predicate)) ;
}
/**
* Create an {@code Iter} such that it yields elements until a predicate test on
* the elements becomes true, end the iteration.
*
* @see Iter#filter(Predicate)
*/
public Iter<T> takeUntil(Predicate<T> predicate) {
return iter(takeUntil(iterator, predicate)) ;
}
/** Create an {@code Iter} such that elements from the front while
* a predicate test become true are dropped then return all remaining elements
* are iterated over.
* The first element where the predicted becomes true is the first element of the
* returned iterator.
*/
public Iter<T> dropWhile(Predicate<T> predicate) {
return iter(dropWhile(iterator, predicate)) ;
}
/** Create an {@code Iter} such that elements from the front until
* a predicate test become true are dropped then return all remaining elements
* are iterated over.
* The first element where the predicate becomes true is the first element of the
* returned iterator.
*/
public Iter<T> dropUntil(Predicate<T> predicate) {
return iter(dropWhile(iterator, predicate.negate())) ;
}
/** Limit the number of elements. */
public Iter<T> limit(long N) {
return Iter.iter(limit(null, N));
}
/** Skip over a number of elements. */
public Iter<T> skip(long N) {
return Iter.iter(skip(null, N));
}
/** Count the iterator (this is destructive on the iterator) */
public long count() {
ActionCount<T> action = new ActionCount<>() ;
apply(action) ;
return action.getCount() ;
}
/**
* Return an {@code Iter} that will see each element of the underlying iterator only once.
* Note that this need working memory to remember the elements already seen.
*/
public Iter<T> distinct() {
return iter((distinct(iterator))) ;
}
/** Remove adjacent duplicates. This operation does not need
* working memory to remember the all elements already seen,
* just a slot for the last element seen.
*/
public Iter<T> distinctAdjacent() {
return iter(distinctAdjacent(iterator)) ;
}
// ---- Iterator
@Override
public boolean hasNext() {
return iterator.hasNext() ;
}
@Override
public T next() {
return iterator.next() ;
}
@Override
public void remove() {
iterator.remove() ;
}
}