Should Stream<T> be covariant?
Ali Lahijani
alahijani at gmail.com
Wed Jan 30 12:36:15 PST 2013
Here is the code:
public class Covariance {
/**
* Lemma: {@code Optional<T>} is covariant in {@code T}
*/
public static <T> Optional<T> elevate(final Optional<? extends T>
delegate) {
return delegate.isPresent() ? Optional.of(delegate.get()) :
Optional.<T>empty();
}
/**
* Lemma: {@code Iterator<T>} is covariant in {@code T}
*/
public static <T> Iterator<T> elevate(final Iterator<? extends T>
delegate) {
return new Iterator<T>() {
@Override
public boolean hasNext() {
return delegate.hasNext();
}
@Override
public T next() {
return delegate.next();
}
@Override
public void remove() {
delegate.remove();
}
};
}
/**
* Lemma: {@code Spliterator<T>} is covariant in {@code T}
*/
public static <T> Spliterator<T> elevate(final Spliterator<? extends T>
delegate) {
return new Spliterator<T>() {
public int getNaturalSplits() {
return delegate.getNaturalSplits();
}
public Spliterator<T> split() {
return elevate(delegate.split());
}
public Iterator<T> iterator() {
return elevate(delegate.iterator());
}
public boolean isPredictableSplits() {
return delegate.isPredictableSplits();
}
public void forEach(Block<? super T> block) {
delegate.forEach(block);
}
public long getSizeIfKnown() {
return delegate.getSizeIfKnown();
}
public long estimateSize() {
return delegate.estimateSize();
}
};
}
/**
* Theorem: {@code Stream<T>} is covariant in {@code T}
*/
public static <T> Stream<T> elevate(final Stream<? extends T> delegate)
{
return new Stream<T>() {
@Override
public Stream<T> filter(Predicate<? super T> predicate) {
return elevate(delegate.filter(predicate));
}
@Override
public <R> Stream<R> map(Function<? super T, ? extends R>
mapper) {
return delegate.map(mapper);
}
@Override
public IntStream map(ToIntFunction<? super T> mapper) {
return delegate.map(mapper);
}
@Override
public LongStream map(ToLongFunction<? super T> mapper) {
return delegate.map(mapper);
}
@Override
public DoubleStream map(ToDoubleFunction<? super T> mapper) {
return delegate.map(mapper);
}
@Override
public <R> Stream<R> explode(BiConsumer<Downstream<R>, ? super
T> exploder) {
return delegate.explode(exploder);
}
@Override
public Stream<T> distinct() {
return elevate(delegate.distinct());
}
@Override
public Stream<T> sorted() {
return elevate(delegate.sorted());
}
@Override
public Stream<T> sorted(Comparator<? super T> comparator) {
return elevate(delegate.sorted(comparator));
}
@Override
public void forEach(Consumer<? super T> consumer) {
delegate.forEach(consumer);
}
@Override
public void forEachUntil(Consumer<? super T> consumer,
BooleanSupplier until) {
delegate.forEachUntil(consumer, until);
}
@Override
public Stream<T> peek(Consumer<? super T> consumer) {
return elevate(delegate.peek(consumer));
}
@Override
public Stream<T> limit(long maxSize) {
return elevate(delegate.limit(maxSize));
}
@Override
public Stream<T> substream(long startingOffset) {
return elevate(delegate.substream(startingOffset));
}
@Override
public Stream<T> substream(long startingOffset, long
endingOffset) {
return elevate(delegate.substream(startingOffset,
endingOffset));
}
@Override
protected Object[] toArray() {
return delegate.toArray();
}
@Override
public <A> A[] toArray(IntFunction<A[]> generator) {
return delegate.toArray(generator);
}
@Override
public T reduce(T identity, BinaryOperator<T> reducer) {
/*
* TODO this one does work, but the implementation is not
"mechanically generated"
*/
// return delegate.reduce(identity, reducer, reducer);
return delegate.reduce(identity, reducer);
}
@Override
public Optional<T> reduce(BinaryOperator<T> reducer) {
/*
* TODO there is no hope for this one
*/
return delegate.reduce(reducer);
}
@Override
public <U> U reduce(U identity, BiFunction<U, ? super T, U>
accumulator, BinaryOperator<U> reducer) {
return delegate.reduce(identity, accumulator, reducer);
}
@Override
public <R> R collect(Supplier<R> resultFactory, BiConsumer<R, ?
super T> accumulator, BiConsumer<R, R> reducer) {
return delegate.collect(resultFactory, accumulator,
reducer);
}
@Override
public <R> R collect(Collector<? super T, R> collector) {
return delegate.collect(collector);
}
@Override
public <R> R collectUnordered(Collector<? super T, R>
collector) {
return delegate.collectUnordered(collector);
}
@Override
protected Optional<T> max(Comparator<? super T> comparator) {
return elevate(delegate.max(comparator));
}
@Override
protected Optional<T> min(Comparator<? super T> comparator) {
return elevate(delegate.min(comparator));
}
@Override
public boolean anyMatch(Predicate<? super T> predicate) {
return delegate.anyMatch(predicate);
}
@Override
public boolean allMatch(Predicate<? super T> predicate) {
return delegate.allMatch(predicate);
}
@Override
public boolean noneMatch(Predicate<? super T> predicate) {
return delegate.noneMatch(predicate);
}
@Override
public Optional<T> findFirst() {
return elevate(delegate.findFirst());
}
@Override
public Optional<T> findAny() {
return elevate(delegate.findAny());
}
@Override
public Stream<T> sequential() {
return elevate(delegate.sequential());
}
@Override
public Stream<T> parallel() {
return elevate(delegate.parallel());
}
@Override
public Iterator<T> iterator() {
return elevate(delegate.iterator());
}
@Override
public Spliterator<T> spliterator() {
return elevate(delegate.spliterator());
}
@Override
public boolean isParallel() {
return delegate.isParallel();
}
@Override
public int getStreamFlags() {
return delegate.getStreamFlags();
}
};
}
}
More information about the lambda-dev
mailing list