nl.vpro.util.CloseableIterator Maven / Gradle / Ivy
package nl.vpro.util;
import java.util.*;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import com.google.common.collect.PeekingIterator;
/**
* An iterator that is also {@link AutoCloseable}.
* @author Michiel Meeuwissen
* @since 1.1
*/
public interface CloseableIterator extends Iterator, AutoCloseable {
static void closeQuietly(AutoCloseable... closeables) {
for (AutoCloseable closeable : closeables) {
try {
if (closeable != null) {
closeable.close();
}
} catch (Exception e) {
// ignore
}
}
}
/**
* @since 2.9
*/
static CloseableIterator empty() {
return new CloseableIterator() {
@Override
public void close() {
}
@Override
public boolean hasNext() {
return false;
}
@Override
public T next() {
throw new NoSuchElementException();
}
};
}
/**
* Morphs an existing {@link Iterator} into a {@link CloseableIterator}.
*
*
* If it is already a {@link CloseableIterator} it will be returned unchanged.
* If it implements {@link AutoCloseable} then its {@link AutoCloseable#close()} method will be called.
* If not then the {@link #close()} method will do nothing.
*
*
* @since 2.9
*/
@SuppressWarnings({"unchecked", "rawtypes"})
static CloseableIterator of(final Iterator iterator) {
if (iterator instanceof CloseableIterator) {
return (CloseableIterator) iterator;
} else if (iterator instanceof PeekingIterator) {
return new WrappedPeekingCloseableIterator<>((PeekingIterator) iterator);
} else {
return new WrappedCloseableIterator<>(iterator);
}
}
static CloseablePeekingIterator peeking(CloseableIterator wrapped){
return wrapped == null ? null : wrapped.peeking();
}
default Stream stream() {
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(this, Spliterator.ORDERED),
false).onClose(() -> {
try {
this.close();
} catch (Exception exception) {
throw new RuntimeException(exception);
}
});
}
/**
* If you need a guava {@link PeekingIterator}, this will make you one. It remains also a {@link CloseableIterator}
*/
default CloseablePeekingIterator peeking() {
return new CloseablePeekingIteratorImpl<>(this);
}
class WrappedCloseableIterator implements CloseableIterator {
protected final Iterator iterator;
protected WrappedCloseableIterator(Iterator iterator) {
this.iterator = iterator;
}
@Override
public void close() throws Exception {
if (iterator instanceof AutoCloseable) {
((AutoCloseable) iterator).close();
}
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public S next() {
return iterator.next();
}
@Override
public void remove() {
iterator.remove();
}
@Override
public String toString() {
return "Closeable[" + iterator + "]";
}
}
class WrappedPeekingCloseableIterator extends WrappedCloseableIterator implements PeekingIterator {
protected WrappedPeekingCloseableIterator(PeekingIterator iterator) {
super(iterator);
}
@Override
public S peek() {
return ((PeekingIterator) iterator).peek();
}
}
}