Why does PrimitiveIterator.OfInt
extend Iterator<Integer>
but IntStream
doesn't extend Stream<Integer>
?
I'm trying to design a primitive collection type (similar to the interfaces from the Apache Commons Primitives library (http://commons.apache.org/dormant/commons-primitives/) and trying to be as consistent and compatible with the collections library, but I can't decide whether I should make my ByteList
extend List<Byte>
or not.
My guess is that this is because Iterator
has direct syntax support in the language (i.e. for loops using iterators) so it's worth making the iterator compatible with that syntax even though it forces boxing, but I'm curious if anyone knows if there's a deeper reason. Thanks!
It is seldom possible to tell why the JDK APIs were designed the way they did it, but in this case we can easily see that trying to make the APIs of Stream<Integer>
and IntStream
work together would be hard to do because there are a number of ambiguities in the method definitions of both interfaces.
Consider the following:
interface Stream<T> {
Stream<T> distinct();
Optional<T> findFirst();
}
interface IntStream extends Stream<Integer> {
IntStream distinct();
OptionalInt findFirst();
}
The second interface would not event compile since the signature of the methods is the same, but the return type is different in the second interface.
Even compatible methods may become difficult to use when we provide multiple implementations of the same method that accept lambdas. Lambdas and overloading of methods typically do not play well together because a given lambda may implement multiple functional interfaces. For example:
interface Stream<T> {
Stream<T> filter(Predicate<T> p);
<S> Stream<S> map(Function<T,S> mapper);
}
interface IntStream extends Stream<Integer> {
IntStream filter(IntPredicate p);
IntStream map(IntUnaryOperator mapper);
}
Now, if you have a invocation like stream.filter(n -> n > 10)
this lambda can actually implement both Predicate<Integer>
or IntPredicate
and now the API user is forced to do some sort of disambiguation, e.g. (int n) -> n > 10
, since the compiler cannot tell the difference.
I suppose, in the long term, this may hinder the evolution of the Stream
and IntStream
APIs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With